htmlentities
Converts every character that has an HTML named entity into that entity.
htmlentities(string $string, int $flags = ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, ?string $encoding = null, bool $double_encode = true): string- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$string | string | The input string. |
$flagsoptional | int= ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 | Bitmask controlling quote handling, invalid-sequence handling and the document type whose entity table is used. |
$encodingoptional | ?string= null | The character encoding of the input. When null the default_charset ini setting is used. |
$double_encodeoptional | bool= true | When false, existing entities in the input are left alone instead of having their ampersands encoded again. |
Return value
stringThe encoded string; an empty string if the input contains an invalid code unit sequence and neither ENT_IGNORE nor ENT_SUBSTITUTE is set.
Errors
Does not throw. An unrecognised encoding is not an error: the default encoding is used instead and a warning is emitted. Input containing an invalid code unit sequence yields an empty string unless ENT_IGNORE or ENT_SUBSTITUTE is set.
Changelog
- PHP 8.1.0The default flags changed from ENT_COMPAT to ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, so single quotes are now encoded by default.
- PHP 8.0.0encoding is nullable.
htmlentities is the maximal HTML encoder: it converts every character that has a named entity in the chosen document type, so < becomes < and é becomes é.
When to reach for it
It is the right tool only when the output has to be pure ASCII: an email template with an uncertain charset, a legacy system that mangles high bytes, or a document you cannot guarantee will be served as UTF-8. For everything else — any modern page served as UTF-8 — htmlspecialchars is the correct choice. It escapes the five characters that actually matter for security and leaves accented letters and emoji as themselves, which keeps the output smaller and searchable.
What trips people up
The encoding argument describes the input. Get it wrong and, with the default ENT_SUBSTITUTE gone because you passed only ENT_QUOTES, the function returns an empty string — a blank page with no error. Always pass the flags and encoding together, or rely on the PHP 8.1 defaults.
Encoding twice produces &lt;. If input may already contain entities, pass double_encode: false. Note also that htmlentities never protects against XSS any better than htmlspecialchars — they cover the same dangerous characters.
Example
When to use it
- Encode accented names into pure ASCII entities for an email template whose charset you do not control.
- Prepare text for a legacy downstream system that corrupts non-ASCII bytes.
- Escape a fragment that will be embedded in a document declared as ISO-8859-1.
Frequently asked questions
What is the difference between htmlentities and htmlspecialchars?
htmlspecialchars encodes only &, <, >, " and '; htmlentities additionally encodes every character that has a named entity, such as accented letters. For UTF-8 output htmlspecialchars is the better default.
Why does htmlentities return an empty string?
The input contains bytes that are invalid in the encoding you declared, and you passed flags without ENT_SUBSTITUTE. Pass the correct encoding, or include ENT_SUBSTITUTE to get replacement characters instead.
How do I stop htmlentities encoding entities that are already there?
Pass false as the fourth argument, double_encode, so existing ampersands in entities are left alone.
More examples
Double encoding
By default every ampersand is encoded, so the existing entities become &amp;T and &lt;b&gt; — the classic double-escaping bug. With double_encode set to false the already-encoded string passes through unchanged.
<?php
$already = "AT&T <b>";
echo htmlentities($already, ENT_QUOTES, "UTF-8"), "\n";
echo htmlentities($already, ENT_QUOTES, "UTF-8", false), "\n";
var_dump(htmlentities($already, ENT_QUOTES, "UTF-8", false) === $already);The wrong encoding silently empties the string
The byte 0xE9 is é in ISO-8859-1 but invalid UTF-8. Declaring the wrong encoding without ENT_SUBSTITUTE returns an empty string; with ENT_SUBSTITUTE you get a replacement character; declaring the correct encoding produces café.
<?php
$latin1 = "caf\xe9";
var_dump(htmlentities($latin1, ENT_QUOTES, "UTF-8"));
var_dump(htmlentities($latin1, ENT_QUOTES | ENT_SUBSTITUTE, "UTF-8"));
var_dump(htmlentities($latin1, ENT_QUOTES, "ISO-8859-1"));htmlentities versus htmlspecialchars on real text
htmlentities converts ë, é and the em dash into named entities, roughly doubling the byte count for accented text. htmlspecialchars touches only the ampersand, leaving readable UTF-8 that renders identically on any UTF-8 page.
<?php
$text = "Zo\u{00EB} & co \u{2014} 100% caf\u{00E9}";
$a = htmlentities($text, ENT_QUOTES, "UTF-8");
$b = htmlspecialchars($text, ENT_QUOTES, "UTF-8");
echo $a, "\n", strlen($a), "\n";
echo $b, "\n", strlen($b), "\n";
Discussion