HTML Entity Encoder / Decoder

Encode text to HTML entities or decode entities back to plain text, covering the five characters that matter for safety and the many that matter for display.

Only five characters actually need escaping

HTML has thousands of named entities, which makes escaping look like it needs a large lookup table. It does not. In text content and in quoted attribute values, exactly five characters can change how the markup parses — and those five are the whole job.

CharacterEscaped asWhy it matters
& & begins a character reference
< &lt; begins a tag
> &gt; ends a tag
" &quot; ends a double-quoted attribute value
' &#39; ends a single-quoted attribute value

Everything else — accented letters, symbols, currency signs, emoji — is a display question rather than a safety one, and declaring UTF-8 handles it. Turning é into &eacute; is a habit from the era before encodings could be relied on. It makes files larger, makes the source harder to read, and does not make anything safer. The "escape non-ASCII too" option above exists for the rare case where you genuinely cannot control the encoding of the destination — not as the default.

Replacing one character at a time is a bug

The obvious way to write an escaper is a chain of replacements. It is wrong unless the ampersand goes first, because &lt; contains an ampersand — so an escaper that handles < before & re-escapes its own output.

InputAmpersand first (correct)Ampersand last (broken)
a < b a &lt; b a &amp;lt; b
Tom & Jerry Tom &amp; Jerry Tom &amp; Jerry
x < y & y < z x &lt; y &amp; y &lt; z x &amp;lt; y &amp; y &amp;lt; z
<b>bold</b> &lt;b&gt;bold&lt;/b&gt; &amp;lt;b&amp;gt;bold&amp;lt;/b&amp;gt;

Getting the order right fixes it, but it leaves you with code that is correct only as long as nobody reorders five lines that look independent. A single pass over a character class cannot have the bug at all, because there is no order to get wrong — which is what this tool does. It is checked against the correctly-ordered chain on every build, and they agree on every input.

That is a reasonable general lesson: when a sequence of steps is only correct in one order, prefer the version that has no order.

And escape exactly once, at the moment of output

Escaping is not idempotent. Running it twice does not leave the text alone, it adds a layer:

PassesResult
none — the original Tom & Jerry <3
1 Tom &amp; Jerry &lt;3
2 Tom &amp;amp; Jerry &amp;lt;3
3 Tom &amp;amp;amp; Jerry &amp;amp;lt;3

This is why escaping on the way into storage goes wrong. The value gets escaped once when it is saved and again when it is rendered, and you end up with a database full of &amp;amp; that nobody can clean up reliably, because you can no longer tell which ampersands were in the original text.

Store the text as the user typed it. Escape at the moment you write it into HTML, once. If you need to reverse it, n escapes need exactly n unescapes — which is another way of saying that if you have lost count, the data has already lost information.

How to use

  1. Paste text to encode, or entities to decode.
  2. Choose whether to encode only the essential characters or everything non-ASCII.
  3. Copy the result into your markup.
  4. Never rely on encoding alone to make untrusted input safe.

Frequently asked questions

Which characters must be encoded?

Five: ampersand, less-than, greater-than, double quote and apostrophe. The first three would otherwise be read as markup, and the quotes can break out of an attribute value. Everything else is a display convenience rather than a requirement.

Why must the ampersand be encoded first?

Because it starts every entity. Encoding the less-than sign to its entity form and then encoding ampersands would mangle the entity you just produced into a literal string. Every correct encoder handles the ampersand before anything else.

Does encoding prevent cross-site scripting?

It is necessary but not sufficient, and the difference matters. Encoding for HTML content does not make a value safe inside a script block, a URL attribute, or a CSS context — each needs its own escaping. Relying on one encoding everywhere is a well-travelled route to a vulnerability.

What is the difference between a named and a numeric entity?

Named entities like the one for ampersand are readable but limited to a defined list. Numeric entities specify a code point directly, in decimal or hex, and can represent any character. Numeric is more general; named is easier to read.

Do I still need entities for accented characters?

Not if the page is served as UTF-8, which it should be. Entities for accented and non-Latin characters were a workaround for unreliable encoding declarations and are now mostly unnecessary clutter. The five structural characters are a different matter and always need encoding.

What is a non-breaking space for?

Preventing a line break at that point, and preserving a space that would otherwise be collapsed. It is useful between a number and its unit, or in a name that should not split across lines. Overusing it makes text that will not wrap properly on narrow screens.

🔒 This tool runs entirely in your browser. Nothing you enter is uploaded, logged, or stored.