html_entity_decode

Converts every HTML entity in a string back to its corresponding character.

Signature
html_entity_decode(string $string, int $flags = ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, ?string $encoding = null): string
  • Added in PHP 4.3.0

Parameters

ParameterTypeDescription
$stringstringThe input string containing HTML entities.
$flagsoptionalint= ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401Bitmask controlling which quote styles are decoded, how invalid sequences are handled, and which document type's entity table is used.
$encodingoptional?string= nullThe character encoding to decode into. When null the default_charset ini setting is used.

Return value

stringThe decoded string, with every recognised entity replaced by the character it names.

Errors

Does not throw. An unrecognised encoding is not an error: the default encoding is used instead and a warning is emitted.

Changelog

  • PHP 8.1.0The default flags changed from ENT_COMPAT to ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, so single quotes are now decoded by default.
  • PHP 8.0.0encoding is nullable.

html_entity_decode is the full inverse of htmlentities: it recognises the entire named-entity table for the chosen document type — ©, é,   and hundreds more — plus numeric references such as A and B.

When to reach for it

Reach for it when text arrives already HTML-encoded and you need the real characters: a feed or scraped page you are turning into plain text, a database column that was double-escaped by an old CMS, or an email subject you are about to send as text/plain. If you only need the five characters htmlspecialchars handles, htmlspecialchars_decode is the narrower and safer choice.

What trips people up

Decoding is the opposite of sanitising. Running it on user input and then printing the result reintroduces working <script> tags — never decode on the way out to a browser.

Always pass the encoding explicitly. With the wrong one, &eacute; decodes to a byte your page cannot render. Note also that &nbsp; becomes U+00A0, a non-breaking space that trim does not remove and that == against a normal space fails on. And &apos; only decodes under ENT_HTML5 or ENT_XML1; the HTML 4.01 table does not define it.

Example

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

When to use it

  • Convert a scraped or RSS-sourced HTML fragment into plain text for indexing or a text-only email.
  • Repair database rows that were stored HTML-encoded by an older application.
  • Decode entity-encoded values from a legacy XML or SOAP payload before comparing them.

Frequently asked questions

What is the difference between html_entity_decode and htmlspecialchars_decode?

html_entity_decode resolves the whole named entity table plus numeric references, while htmlspecialchars_decode only reverses the five characters htmlspecialchars encodes. Use the narrower one when you only ever encoded with htmlspecialchars.

Why is &nbsp; still not matching a normal space after decoding?

Because it decodes to U+00A0, a non-breaking space, which is a different character from the ASCII space. Replace it explicitly if you need plain spaces.

Is it safe to run html_entity_decode on user input?

Not before output. Decoding turns &lt;script&gt; back into a live tag, so never decode data on its way to a browser — decode only for plain-text processing.

More examples

Round trip with htmlentities

htmlentities converts both the markup characters and the accented letters into named entities. Decoding with the same flags and encoding returns a string identical to the original, which is what the final bool(true) confirms.

Example · php
<?php
$original = "caf\u{00E9} & <cr\u{00E8}me> \"br\u{00FB}l\u{00E9}e\"";

$encoded = htmlentities($original, ENT_QUOTES, "UTF-8");
echo $encoded, "\n";

$decoded = html_entity_decode($encoded, ENT_QUOTES, "UTF-8");
echo $decoded, "\n";
var_dump($decoded === $original);

How much each function decodes

html_entity_decode resolves every entity including &copy; and &eacute;; htmlspecialchars_decode leaves those two untouched because they are outside its five-character set. The last line shows &nbsp; decoding to U+00A0, which trim leaves in place.

Example · php
<?php
$s = "&amp; &lt; &quot; &copy; &eacute; &nbsp;|";

echo html_entity_decode($s, ENT_QUOTES, "UTF-8"), "\n";
echo htmlspecialchars_decode($s, ENT_QUOTES), "\n";

var_dump(html_entity_decode("&nbsp;", ENT_QUOTES, "UTF-8") === "\u{00A0}");
var_dump(trim(html_entity_decode("&nbsp;x&nbsp;", ENT_QUOTES, "UTF-8")));

Document type changes the entity table

&apos; is not part of the HTML 4.01 entity table, so with ENT_HTML401 it passes through untouched; ENT_HTML5 decodes it to an apostrophe. The numeric reference &#39; works under every document type, which is why encoders prefer it.

Example · php
<?php
echo html_entity_decode("&apos;", ENT_QUOTES | ENT_HTML401, "UTF-8"), "\n";
echo html_entity_decode("&apos;", ENT_QUOTES | ENT_HTML5, "UTF-8"), "\n";
echo html_entity_decode("&#39;", ENT_QUOTES, "UTF-8"), "\n";
echo html_entity_decode("&hearts;", ENT_QUOTES | ENT_HTML5, "UTF-8"), "\n";

Discussion

  • Be the first to comment on this lesson.