HTML entity encode/decode · Guide
html_entity_decode in PHP: Flags, Charsets and Pitfalls
PHP has four functions in this area and they differ in exactly which entities they touch. Picking the wrong one leaves quotes undecoded, or decodes more than you intended.
The four functions
htmlspecialchars($s) // encode: & < > " and optionally '
htmlspecialchars_decode($s) // decode: only those few
htmlentities($s) // encode: everything with a named entity
html_entity_decode($s) // decode: every named and numeric entityhtml_entity_decode is the broad one — it handles &, , →, → and → alike. htmlspecialchars_decode only reverses the five structural characters, which is what you usually want when undoing your own escaping.
Always pass the flags
Before PHP 8.1 the default was ENT_COMPAT, which left ' undecoded. Code written then and running now behaves differently:
html_entity_decode($s, ENT_QUOTES | ENT_HTML5, 'UTF-8');ENT_QUOTES covers both quote styles, ENT_HTML5 recognises the full HTML5 entity set including ', and naming the charset explicitly avoids depending on default_charset. Being explicit makes the behaviour version-independent.
The double-decoding hazard
Decoding twice is a genuine security bug. &lt;script> decodes once to the literal text <script> and twice to an executable <script> tag.
Decode exactly once, at the point of display, and never in a loop "until nothing changes". If content arrives already escaped, store it escaped and decode only when rendering into a context that needs raw text.
Where the functions belong
Encode on output, not on input. Storing htmlspecialchars-encoded text in the database means every non-HTML consumer — a JSON API, a CSV export, an email — receives entities it will not decode.
Store raw text, escape at render time with htmlspecialchars($s, ENT_QUOTES, 'UTF-8'), and let the template engine do it automatically where it can. Modern frameworks escape by default, which is why html_entity_decode in application code is often a sign that something was escaped too early.
Frequently asked questions
Why is my apostrophe not decoded?
Without ENT_QUOTES, ' is left alone on older PHP defaults. Pass the flag explicitly.
html_entity_decode or htmlspecialchars_decode?
The second when reversing your own htmlspecialchars; the first when the input may contain any named or numeric entity.
Should I decode user input before storing it?
No. Store raw text and escape on output.
Ready to try it?
Open the free browser-based HTML entity encode/decode and apply what you just read — no sign-up, runs locally.
Open the HTML entity encode/decode tool