Multibyte strings7 min readExamples run on PHP 8.5.10

mb_preferred_mime_name()

Learn how mb_preferred_mime_name() maps a PHP encoding name to its MIME charset string, when it returns false, and when it throws ValueError.

Signature

mb_preferred_mime_name(string $encoding): string|false
Available since PHP 4.0.67.48.08.18.28.38.48.5All versions →

Purpose

The mbstring extension accepts many encoding names, such as SJIS, ASCII or utf-8. Protocols like HTTP and email use a different vocabulary: the charset labels registered for MIME, such as Shift_JIS or US-ASCII. mb_preferred_mime_name() translates from the first world to the second. You give it an encoding name that mbstring understands, and it returns the preferred MIME charset string for that encoding.

The typical use is building a header or a metadata field, for example the charset= part of a Content-Type header, from an encoding name used internally.

Signature

Parameters and defaults

  • $encoding: the name of the encoding to look up. It is required and has no default. Names are matched without regard to case, so utf-8 and UTF-8 refer to the same encoding. Aliases that mbstring knows, like sjis, are accepted too.

There is no optional argument. In particular, the function does not fall back to the internal encoding when you omit the argument, so you must always pass a name.

Return value and failure cases

There are three outcomes:

  1. A string: the MIME charset name for the encoding, for example Shift_JIS for SJIS.
  2. false: the encoding is valid, but no charset name is preferred for it.
  3. A thrown ValueError: the name is not a valid encoding at all. This is the behavior as of PHP 8.0.0. Before that version an E_WARNING was emitted and false was returned instead.

Because false and an exception mean different things, handle them separately. false says "valid encoding, no MIME name", while ValueError says "mbstring does not know this name".

Example 1: translating common encoding names

The first example looks up four names. Notice that the result is not always identical to the input: ASCII becomes US-ASCII and SJIS becomes Shift_JIS.

Example
<?php
$names = ['UTF-8', 'ASCII', 'ISO-8859-1', 'SJIS'];
$result = [];
foreach ($names as $name) {
    $result[$name] = mb_preferred_mime_name($name);
}
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"UTF-8":"UTF-8","ASCII":"US-ASCII","ISO-8859-1":"ISO-8859-1","SJIS":"Shift_JIS"}

Example 2: building a Content-Type value safely

A small helper can turn an internal encoding name into a header value. It checks for false with a strict comparison and picks a neutral fallback when no preferred name exists. Lowercase input works because lookup ignores case.

Example
<?php
function contentType(string $encoding): string
{
    $charset = mb_preferred_mime_name($encoding);
    if ($charset === false) {
        return 'application/octet-stream';
    }
    return 'text/plain; charset=' . $charset;
}

echo contentType('utf-8'), "\n";
echo contentType('ascii'), "\n";
Output
text/plain; charset=UTF-8
text/plain; charset=US-ASCII

Example 3: handling an unknown encoding

An invalid name is a programming or input error, not a normal lookup miss. Catch ValueError where the name comes from untrusted data, such as a configuration value or a user choice.

Example
<?php
try {
    mb_preferred_mime_name('not-an-encoding');
    echo "found\n";
} catch (ValueError $e) {
    echo get_class($e), "\n";
}
Output
ValueError

Edge cases

  • Case and aliases. sjis, SJIS and other names for the same encoding all resolve to one MIME name. You do not need to normalize case yourself.
  • No preferred name. Some valid encodings have no MIME charset registered with mbstring, and those return false. Do not concatenate the result into a header without checking it, because false becomes an empty string and you would produce charset=.
  • Empty string. An empty string is not a valid encoding name, so expect the same ValueError as for any other unknown name.
  • Only names, not data. The function inspects a name, never a string of text. It tells you nothing about whether bytes are valid in that encoding. Use mb_check_encoding() for that purpose.

Common mistakes

  1. Using a loose check. Writing if (!$charset) mixes up false with other falsy values. Compare with === false.
  2. Forgetting the exception. Since PHP 8.0, scripts that relied on a warning plus a false return for unknown names will now stop with an uncaught ValueError.
  3. Assuming the output equals the input. The result is the preferred MIME label, so ASCII yields US-ASCII. Do not compare the output against your input name to decide whether an encoding is supported.
  4. Expecting conversion. The function does not convert text. Pair it with mb_convert_encoding() if you need to re-encode a string before sending it under the reported charset.
  5. Mismatched header and body. Reporting a charset in a header only helps if the body is actually encoded that way. The manual's own example sets the output encoding with mb_http_output() and then sends a Content-Type header built from the same name, which keeps them aligned.
  • mb_list_encodings(): lists the encoding names mbstring supports.
  • mb_encoding_aliases(): returns the aliases of an encoding.
  • mb_http_output(): gets or sets the HTTP output encoding.
  • mb_internal_encoding(): gets or sets the internal encoding.
  • mb_check_encoding(): verifies that a string is valid in an encoding.
  • mb_convert_encoding(): converts text between encodings.

Recap

mb_preferred_mime_name() takes one encoding name and returns the MIME charset label that goes with it, such as Shift_JIS for SJIS. It returns false when an encoding is valid but has no preferred label, and it throws ValueError for unknown encodings. Check the result with === false, catch the exception for untrusted names, and remember that it translates names only, not text.

Tested examples

Translating common encoding names
<?php
$names = ['UTF-8', 'ASCII', 'ISO-8859-1', 'SJIS'];
$result = [];
foreach ($names as $name) {
    $result[$name] = mb_preferred_mime_name($name);
}
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"UTF-8":"UTF-8","ASCII":"US-ASCII","ISO-8859-1":"ISO-8859-1","SJIS":"Shift_JIS"}
Building a Content-Type value safely
<?php
function contentType(string $encoding): string
{
    $charset = mb_preferred_mime_name($encoding);
    if ($charset === false) {
        return 'application/octet-stream';
    }
    return 'text/plain; charset=' . $charset;
}

echo contentType('utf-8'), "\n";
echo contentType('ascii'), "\n";
Output
text/plain; charset=UTF-8
text/plain; charset=US-ASCII
Handling an unknown encoding
<?php
try {
    mb_preferred_mime_name('not-an-encoding');
    echo "found\n";
} catch (ValueError $e) {
    echo get_class($e), "\n";
}
Output
ValueError