Strings7 min readExamples run on PHP 8.5.10

get_html_translation_table()

Learn how get_html_translation_table() returns the character-to-entity map used by htmlspecialchars() and htmlentities(), with flags, encodings and pitfalls.

Signature

get_html_translation_table(
    int $table = HTML_SPECIALCHARS,
    int $flags = ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401,
    string $encoding = "UTF-8"
): array

Purpose

get_html_translation_table() gives you the exact map that htmlspecialchars() and htmlentities() consult internally. The result is an ordinary PHP array. Each key is a single original character and each value is the entity string that replaces it. Looking at the table is useful when you want to inspect what a given flag combination will encode, build a custom replacement with strtr(), or check what a document type such as HTML 4.01 or HTML5 supports.

Signature

Parameters and defaults

  • $table selects the table. HTML_SPECIALCHARS is the small table used by htmlspecialchars(). HTML_ENTITIES is the much larger table used by htmlentities().
  • $flags is a bitmask. Quote flags decide whether quotes are included: ENT_COMPAT includes double quotes only, ENT_QUOTES includes both quote types, and ENT_NOQUOTES includes neither. A document-type flag chooses the entity set: ENT_HTML401, ENT_XML1, ENT_XHTML or ENT_HTML5. ENT_SUBSTITUTE is part of the default value as well.
  • $encoding names the character set. The default is UTF-8. Other supported charsets include ISO-8859-1, ISO-8859-15, cp1252, Shift_JIS and EUC-JP. An empty string asks PHP to detect the encoding, which the manual marks as not recommended.

The manual's changelog records one change: since PHP 8.1.0 the default for $flags is ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 instead of ENT_COMPAT. If you rely on the default and the code must behave the same on old and new versions, pass the flags explicitly.

Return value and failure cases

The function returns an array with the original characters as keys and entities as values. For an unrecognized charset, PHP emits a warning and uses the default encoding instead. The function does not return false.

The manual also notes that a character can be written as an entity in several ways, for example ", " or ". The table lists only the form that the two encoding functions actually produce.

Example 1: the default special-characters table

The default table has five entries. The example sorts the keys so that the printed order is obvious.

Example
<?php
$table = get_html_translation_table();
ksort($table);
echo json_encode($table, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
{"\"":"&quot;","&":"&amp;","'":"&#039;","<":"&lt;",">":"&gt;"}

Example 2: how flags change the table

Quote flags change how many entries the special-characters table holds. The document type changes the form of the single-quote entity.

Example
<?php
$counts = [
    'compat' => count(get_html_translation_table(HTML_SPECIALCHARS, ENT_COMPAT | ENT_HTML401)),
    'quotes' => count(get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES | ENT_HTML401)),
    'noquotes' => count(get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES | ENT_HTML401)),
];
echo json_encode($counts), PHP_EOL;

$html5 = get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES | ENT_HTML5);
echo $html5["'"], PHP_EOL;
Output
{"compat":4,"quotes":5,"noquotes":3}
&apos;

Example 3: using the full entity table

The HTML_ENTITIES table covers named entities for accented letters and symbols. Passing it to strtr() performs the same kind of substitution as htmlentities() with matching flags.

Example
<?php
$table = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES | ENT_HTML401, 'UTF-8');
echo json_encode([$table['é'], $table['©'], count($table) > 5], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
echo strtr('café <b>', $table), PHP_EOL;
Output
["&eacute;","&copy;",true]
caf&eacute; &lt;b&gt;

Edge cases

  • With ENT_NOQUOTES neither quote character appears, so the table has only &, < and >.
  • The same character can map to a different entity in a different document type. The single quote is the common case: the HTML5 table uses &apos;.
  • HTML_ENTITIES is large and its size depends on the document type, so do not hard-code its count.
  • Keys are characters in the chosen encoding. In UTF-8 a key such as é is a multibyte string, while in ISO-8859-1 it is a single byte.

Common mistakes

  1. Relying on the default flags across versions. The default changed in PHP 8.1.0, which affects whether single quotes are in the table.
  2. Treating the table as a decoder. Flipping it with array_flip() only covers the entity forms in the table. Use html_entity_decode() or htmlspecialchars_decode() for real decoding, since they accept more forms.
  3. Mixing flags between calls. Building a table with one set of flags and then escaping with another produces inconsistent output.
  4. Using it as the escaping step itself. For output escaping, call htmlspecialchars() directly. It is the supported and clearer API.
  5. Forgetting the encoding. Reading a table for UTF-8 and applying it to text in another charset gives wrong results.
  • htmlspecialchars() converts the special characters to entities.
  • htmlentities() converts all applicable characters to entities.
  • html_entity_decode() converts entities back to characters.

Recap

get_html_translation_table() returns an array of characters to entities for the table, flags and encoding you choose. Pass flags explicitly, remember that quote flags and document type change the contents, and use the dedicated encode and decode functions for real escaping work.

Tested examples

Default special-characters table, sorted by key
<?php
$table = get_html_translation_table();
ksort($table);
echo json_encode($table, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
{"\"":"&quot;","&":"&amp;","'":"&#039;","<":"&lt;",">":"&gt;"}
How quote flags and document type change the table
<?php
$counts = [
    'compat' => count(get_html_translation_table(HTML_SPECIALCHARS, ENT_COMPAT | ENT_HTML401)),
    'quotes' => count(get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES | ENT_HTML401)),
    'noquotes' => count(get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES | ENT_HTML401)),
];
echo json_encode($counts), PHP_EOL;

$html5 = get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES | ENT_HTML5);
echo $html5["'"], PHP_EOL;
Output
{"compat":4,"quotes":5,"noquotes":3}
&apos;
Using the full entity table with strtr()
<?php
$table = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES | ENT_HTML401, 'UTF-8');
echo json_encode([$table['é'], $table['©'], count($table) > 5], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
echo strtr('café <b>', $table), PHP_EOL;
Output
["&eacute;","&copy;",true]
caf&eacute; &lt;b&gt;