mb_check_encoding
Checks whether a string or array contains only byte sequences that are valid in a given encoding.
mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool- Added in PHP 4.4.3
Parameters
| Parameter | Type | Description |
|---|---|---|
$valueoptional | array|string|null= null | The string, or array of strings, to validate. Arrays are checked recursively, keys included. Passing null or omitting it is deprecated as of PHP 8.1. |
$encodingoptional | ?string= null | The encoding the value is expected to be in. If omitted or null, the internal encoding is used. |
Return value
booltrue when every byte in value forms a legal sequence in encoding, false otherwise.
Errors
Throws a ValueError if encoding is not a name mbstring recognises; passing null or omitting value emits a deprecation notice on PHP 8.1 and later.
Changelog
- PHP 8.1.0Calling the function with null as value, or with no arguments at all, is deprecated.
- PHP 8.0.0value and encoding became nullable.
- PHP 7.2.0value may now be an array; previously only strings were accepted.
mb_check_encoding() answers exactly one question: are these bytes a legal sequence in this encoding? It converts nothing and guesses nothing — you name the encoding, it says yes or no.
Reach for it at the edges of your program: form input, uploaded CSV files, rows pulled out of a legacy database, anything read from a socket. Invalid UTF-8 travels quietly through your code until it meets something strict, and then the failure surfaces far from its cause — json_encode() returns false, a database insert is rejected, or a response body truncates mid-page. Validating on arrival turns that into an obvious rejection at the door.
Since PHP 7.2 it accepts an array and walks it recursively, validating both keys and values, so mb_check_encoding($_POST, 'UTF-8') gates an entire request in one call.
Watch the asymmetry between encodings. Single-byte encodings such as ISO-8859-1 or Windows-1252 assign a meaning to every possible byte, so a check against them is always true and tells you nothing at all. Only variable-width encodings — UTF-8, Shift_JIS, EUC-JP — have sequences that can genuinely be malformed.
When a string fails, you have two sensible moves: reject it, or repair it with mb_scrub() (replace the bad bytes) or mb_convert_encoding() (if you know what encoding it really is).
Example
When to use it
- Reject a form submission that contains invalid UTF-8 before it reaches the database.
- Verify an uploaded CSV really is UTF-8 before parsing it row by row.
- Guard an API payload so json_encode() cannot silently return false on malformed bytes.
- Decide, per row of a legacy import, whether to convert from Windows-1252 or keep as-is.
Frequently asked questions
How do I check if a string is valid UTF-8 in PHP?
Call mb_check_encoding($string, 'UTF-8') — it returns true only when every byte forms a legal UTF-8 sequence. Always pass 'UTF-8' explicitly rather than relying on the internal encoding, so the result does not change when someone edits php.ini.
What is the difference between mb_check_encoding and mb_detect_encoding?
mb_check_encoding() verifies a string against an encoding you name and returns a boolean; mb_detect_encoding() guesses which encoding a string is in and returns a name. Use check when you know what the data should be, and detect only when you genuinely have no idea.
Why does mb_check_encoding always return true for ISO-8859-1?
ISO-8859-1 maps all 256 possible byte values to characters, so no byte sequence can be invalid in it. Validation is only informative for variable-width encodings such as UTF-8, Shift_JIS or EUC-JP.
More examples
Repair input that fails the check
The byte 0x80 is not valid UTF-8, so the first check fails. Interpreted as Windows-1252 that byte is the euro sign, so the conversion produces "price: 100€" and the second check returns true. This is the standard shape of an import routine: check, convert only if needed, check again.
<?php
$raw = "price: 100\x80";
if (!mb_check_encoding($raw, 'UTF-8')) {
$raw = mb_convert_encoding($raw, 'UTF-8', 'Windows-1252');
}
echo $raw, "\n";
var_dump(mb_check_encoding($raw, 'UTF-8'));Why json_encode() suddenly returns false
json_encode() refuses any string that is not valid UTF-8 and returns false rather than throwing, so the failure is easy to miss. mb_check_encoding() identifies the offending value before you ever get to the encoder, and json_last_error_msg() confirms the same cause.
<?php
$bad = "caf\xE9"; // Latin-1 é, not UTF-8
var_dump(mb_check_encoding($bad, 'UTF-8'));
var_dump(json_encode(['x' => $bad]));
echo json_last_error_msg(), "\n";Single-byte encodings always pass
Every byte has a meaning in ISO-8859-1, so the check is true for arbitrary binary garbage — a true result there proves nothing. Only variable-width encodings such as UTF-8 and Shift_JIS can report a malformed sequence, which is why validation is only meaningful against those.
<?php
$random = "\x00\xFF\x80\x41\xC3";
var_dump(mb_check_encoding($random, 'ISO-8859-1'));
var_dump(mb_check_encoding($random, 'UTF-8'));
var_dump(mb_check_encoding($random, 'Shift_JIS'));
Discussion