Learn how to transition to PHP’s iconv() for superior character encoding management, improving compatibility, performance, and data integrity.
Pull a product feed from a supplier, drop it into your database, and watch half the names come back as question marks or little empty boxes. The data was fine. The encoding wasn’t. Somewhere between their file and your table, bytes got read as the wrong character set.
That’s the job iconv() handles: take a string in one encoding and hand it back in another. This post covers what it actually does, where it sits next to mbstring, and the sharp edges worth knowing before you lean on it.
Table of Contents
- Understanding Character Encoding in PHP
- What is iconv()?
- Why reach for iconv()?
- Common Use Cases for iconv()
- Best Practices for Using iconv()
- Wrapping Up
Understanding Character Encoding in PHP
Encoding is how text turns into bytes and back again. Your app touches a lot of sources: form input, a database, a third-party API, an uploaded CSV. If any two of them disagree about the character set, you get garbled text or, worse, silent corruption you don’t notice until a customer does.
Older PHP code leaned on utf8_encode() and utf8_decode() for this. Both were deprecated in PHP 8.2, largely because their names lied: they only ever converted between ISO-8859-1 and UTF-8, not “to UTF-8” from anything you threw at them. mb_convert_encoding(), from the mbstring extension, is not deprecated and is the other tool most people reach for. iconv() is the third option, and often the simplest one for a straight this-encoding-to-that-encoding conversion.
What is iconv()?
iconv() converts a string from one character encoding to another. Under the hood it calls your system’s iconv library (libiconv on most builds), so the exact set of encodings it supports depends on the platform PHP is running on, not on PHP itself. It ships as a PHP extension that’s usually enabled by default, though it isn’t guaranteed. If a conversion fails outright, the iconv documentation is the place to confirm what your build has.
The signature is short:
Example of the code
<?php
/**
* Convert a string's encoding.
*
* @param string $from_encoding The current encoding of the string.
* @param string $to_encoding The target encoding.
* @param string $string The string to convert.
* @return string|false The converted string, or false on failure.
*/
$converted_string = iconv( 'from_encoding', 'to_encoding', $string );Give it the current encoding, the target encoding, and the string. On success you get the converted string back. On failure it returns false, and on invalid input it also emits a warning and may hand back only the part it managed to convert. So always check the return value.
Why reach for iconv()?
There’s no single winner between iconv() and mbstring, but iconv() earns its place for a few honest reasons:
- Wide encoding coverage: iconv() handles a long list of character sets, which helps when an app juggles multiple languages. The exact list depends on your system’s libiconv, so it can differ between machines.
- Honest failure: it returns false and raises a warning when the input is invalid, so bad data doesn’t slip through silently.
- Transliteration: the //TRANSLIT modifier approximates characters the target set can’t represent instead of just failing on them.
- Small API: for a plain “this encoding to that encoding” job, it’s one function call with nothing else to set up.
None of that makes iconv() strictly better than mbstring. They overlap a lot. mbstring does more around multibyte string handling in general; iconv() is often the leaner pick when all you need is the conversion. Choose per job, and remember both depend on their extension being compiled in.
Common Use Cases for iconv()
Here are the situations where iconv() tends to earn its keep.
1. Converting Between UTF-8 and ISO-8859-1
UTF-8 and ISO-8859-1 (Latin-1) still turn up all over the web. Here’s a UTF-8 to ISO-8859-1 conversion:
Example of the code
<?php
/**
* Convert UTF-8 encoded string to ISO-8859-1 encoding.
*
* @param string $string UTF-8 encoded string.
* @return string|false ISO-8859-1 encoded string, or false on failure.
*/
function convert_utf8_to_iso88591( $string ) {
return iconv( 'UTF-8', 'ISO-8859-1', $string );
}One thing to watch: ISO-8859-1 can’t represent every UTF-8 character. Anything outside Latin-1 makes the call fail and return false unless you add //TRANSLIT or //IGNORE to the target. Check the result before you trust it.
2. Handling Unsupported Characters with Transliteration
The //TRANSLIT option swaps characters the target set can’t hold for near equivalents, so “café” going to ASCII becomes “cafe” instead of failing.
Example of the code
<?php
/**
* Convert UTF-8 string to ASCII with transliteration.
*
* @param string $string UTF-8 encoded string.
* @return string|false ASCII encoded string with transliteration, or false on failure.
*/
function convert_utf8_to_ascii( $string ) {
return iconv( 'UTF-8', 'ASCII//TRANSLIT', $string );
}Here’s the caveat worth internalizing: what //TRANSLIT produces depends on the system’s iconv and its locale. The same code can transliterate differently on your laptop and your server, and when it can’t find an approximation it may drop in a “?” or raise a warning. Test it where it’ll actually run.
3. Sanitizing User Input in Multiple Encodings
User input arrives in all sorts of encodings, especially in multilingual apps. Converting it to UTF-8 up front keeps the rest of your code consistent.
Example of the code
<?php
/**
* Convert user input to UTF-8 encoding.
*
* @param string $input The user input string.
* @param string $input_encoding The encoding of the input string.
* @return string|false UTF-8 encoded string, or false on failure.
*/
function sanitize_user_input( $input, $input_encoding ) {
return iconv( $input_encoding, 'UTF-8', $input );
}Normalizing to one encoding at the edge saves you from mixing encodings deeper in the app. Just make sure the $input_encoding you pass is actually right. iconv() trusts you on that, and a wrong guess gives you garbage, not an error.
Best Practices for Using iconv()
A few habits keep encoding work boring, which is exactly what you want:
- Always pass both encodings: name the source and the target every time. If you get the source wrong, the output is wrong and iconv() won’t warn you.
- Check for false: a failed conversion returns false, so branch on it and handle the failure instead of storing corrupted text.
- Use //IGNORE sparingly: the //IGNORE option drops characters it can’t convert, which is silent data loss. Only reach for it when losing a few characters genuinely doesn’t matter.
- Normalize early: convert everything to one encoding (UTF-8 is the safe default) at the boundary of your app, so the rest of your code never has to think about it.
Wrapping Up
iconv() is a small, dependable tool for one job: moving a string from one encoding to another. It returns false when it can’t, transliterates when you ask, and stays out of your way otherwise.
Treat it as a peer to mbstring, not a magic upgrade. Name both encodings, check the return value, and go careful with //IGNORE and //TRANSLIT, since one loses data and the other varies by system. Do that and encoding stops being the thing that quietly breaks your data.
