mb_chr

Returns the character for a given Unicode code point, encoded in the requested character encoding.

Signature
mb_chr(int $codepoint, ?string $encoding = null): string|false
  • Added in PHP 7.2.0

Parameters

ParameterTypeDescription
$codepointintA Unicode code point, for example 128024 for U+1F418 ELEPHANT.
$encodingoptional?string= nullThe encoding the returned character should be in. If omitted or null, the internal encoding is used.

Return value

string|falseA string containing the character for the code point, or false if the code point cannot be represented in the requested encoding.

Errors

Throws a ValueError if encoding is not a name mbstring recognises. An unrepresentable code point is reported by returning false, not by throwing.

Changelog

  • PHP 8.0.0encoding became nullable.

mb_chr() is the multibyte counterpart of chr(). Where chr() takes a byte value from 0 to 255 and hands back one byte, mb_chr() takes a Unicode code point and hands back the complete multi-byte character — one to four bytes for UTF-8.

You reach for it whenever you have a number and need the character it names: decoding numeric HTML entities such as é, turning a U+1F600 style token from a data feed into a real emoji, generating a character range, or reversing something that mb_ord() produced. It is the natural building block for any code that reasons about characters as numbers.

The return type is string|false and the false case matters. If the code point has no representation in the target encoding — asking for the euro sign in ISO-8859-1, or any emoji in a single-byte encoding — you get false, not a substitution character. Test with === against false before concatenating, because false silently becomes an empty string inside a string context and the character just vanishes from your output.

Passing a negative code point, or one above U+10FFFF, also yields false. Surrogate code points in the U+D800–U+DFFF range are not valid characters and are rejected too.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Decode numeric HTML entities like 😀 into the actual characters.
  • Turn a "U+1F600" style code point column from a data export into real emoji.
  • Build a test string covering a specific Unicode block, one code point at a time.
  • Round-trip characters through their numeric values alongside mb_ord().

Frequently asked questions

What is the difference between chr and mb_chr?

chr() takes a byte value 0–255 and returns exactly one byte, so it cannot produce any character outside the single-byte range. mb_chr() takes a Unicode code point and returns the full multi-byte encoding of that character.

Why does mb_chr return false?

Because the code point cannot be represented in the requested encoding, or because it is out of range — negative, above U+10FFFF, or a surrogate in U+D800–U+DFFF. Compare with === false before using the result.

How do I convert a Unicode code point to an emoji in PHP?

Call mb_chr($codepoint, 'UTF-8') — for example mb_chr(0x1F600, 'UTF-8') returns 😀. The equivalent literal form is "\u{1F600}" in a double-quoted string, which is preferable when the code point is a constant.

More examples

Build a string from a list of code points

Four code points become four characters but nine bytes: two ASCII letters at one byte each, a heart at three and a globe at four. The gap between mb_strlen() and strlen() is exactly why you use mb_chr() instead of chr() as soon as your data leaves ASCII.

Example · php
<?php
$points = [72, 101, 0x2764, 0x1F30D];

$out = '';
foreach ($points as $p) {
    $out .= mb_chr($p, 'UTF-8');
}

echo $out, "\n";
echo mb_strlen($out, 'UTF-8'), " characters, ", strlen($out), " bytes\n";

Decode numeric HTML entities

Each &#N; token is replaced by the character for code point N, producing "Café 😀 €". This works for any decimal entity, including astral-plane characters above U+FFFF that older entity tables often miss.

Example · php
<?php
$html = "Caf&#233; &#128512; &#8364;";

$decoded = preg_replace_callback(
    '/&#(\d+);/',
    fn(array $m): string => mb_chr((int) $m[1], 'UTF-8'),
    $html
);

echo $decoded, "\n";

Guard against unrepresentable characters

A and é exist in Latin-1 and come back as characters; the euro sign and the elephant do not, so mb_chr() returns false and the fallback prints a readable placeholder instead of dropping the character. Without the === false test those two lines would print nothing at all.

Example · php
<?php
function toLatin1(int $cp): string {
    $c = mb_chr($cp, 'ISO-8859-1');
    return $c === false ? '[U+' . strtoupper(dechex($cp)) . ']' : $c;
}

foreach ([0x41, 0xE9, 0x20AC, 0x1F418] as $cp) {
    echo mb_convert_encoding(toLatin1($cp), 'UTF-8', 'ISO-8859-1'), "\n";
}

Discussion

  • Be the first to comment on this lesson.