HTML entity encoder and decoder

Encode or decode HTML entities like a browser, plus JavaScript and CSS escapes.

Direction

Escapes for code

JavaScript string

<p class=\"note\">Caf\u00E9 & cr\u00E8me \u2014 \"5 > 3\" isn\'t news. Gi\u00E1: 25.000 \u20AB \u{1F600}</p>

JavaScript (ES5, surrogate pairs)

<p class=\"note\">Caf\u00E9 & cr\u00E8me \u2014 \"5 > 3\" isn\'t news. Gi\u00E1: 25.000 \u20AB \uD83D\uDE00</p>

CSS content string

<p class=\22note\22>Caf\E9 & cr\E8me \2014 \22 5 > 3\22 isn\27t news. Gi\E1: 25.000 \20AB \1F600</p>

What this tool does

Two directions. Encode turns text into HTML character references: only the five reserved characters (& < > " '), those plus every non-ASCII character, or every character. References can be written by name where one exists (&eacute;), in decimal (&#233;) or in hexadecimal (&#xE9;). Decode turns references back into characters using the full table of 2,125 HTML5 names and the same rules browsers follow. Below the result, the same text is shown as a JavaScript string escape (\u00E9, \u{1F600} or a surrogate pair for old engines) and a CSS escape for the content property (\E9 ).

When you actually need entities

With a UTF-8 page (<meta charset="utf-8">, the default for modern sites), any character can be written directly: é, —, 😀 need no entity. What must always be escaped is markup-significant text:

  • & as &amp; and < as &lt; in page text, so they are not read as the start of a reference or a tag.
  • " as &quot; inside a double-quoted attribute value, and ' as &#39; inside a single-quoted one.
  • > as &gt; is not strictly required in text but is customary and harmless.

That is what the default "only & < > " '" scope does. Encoding every non-ASCII character is useful when the text will pass through a system that may not keep UTF-8 (some email pipelines and old databases), and &nbsp;, &shy; and &zwj; remain handy for invisible characters you want to see in the source.

Decoding like a browser

Browsers are forgiving, and the rules are precise:

  • The longest matching name wins: &notin; is ∉, while &notit; (not a name) decodes &not and leaves it;.
  • 106 legacy names from HTML 4, such as &amp, &lt, &copy and &eacute, also work without the semicolon. Newer ones such as &hellip do not.
  • In attribute values a legacy name without a semicolon is left alone if it is followed by = or a letter or digit. That keeps URLs like ?a=1&copy=2 intact. Choose "Attribute value" to see this.
  • Numeric references &#0;, surrogates and values above U+10FFFF become U+FFFD (�), and &#128; to &#159; become the Windows-1252 characters (&#150; is an en dash), for compatibility with old pages.

Unknown names such as &foo; are left exactly as written and listed, so a typo does not vanish silently. The decoder is checked against an independent implementation of the HTML specification on thousands of generated inputs.

Escaping is not sanitising

Encoding the reserved characters is how you put untrusted text into HTML safely, and it is the core defence against cross-site scripting (XSS): <script> becomes the visible text &lt;script&gt;. But it only protects page text and quoted attribute values. Inside a <script> block, a style attribute, an event handler such as onclick or a URL in href, other rules apply, and HTML-escaping alone is not enough. Your template engine's automatic escaping is the right tool in code; this page is for checking, debugging and one-off content. The article HTML entities vs UTF-8, and when escaping stops XSS covers the cases with examples. For URLs, use the URL encoder; for code points and grapheme clusters, the Unicode and emoji lookup.

Frequently asked questions

Do I need &eacute; and similar entities on a UTF-8 page?

No. With UTF-8, accented letters, symbols and emoji can be written directly. Only &, <, > and the quote character of an attribute must be escaped. Named entities for other characters are a leftover from encodings that could not represent them.

Why does &copy=2 stay as it is in an attribute but become ©=2 in text?

The HTML specification lets 106 old names work without a semicolon, but in attribute values only when the next character is not = or a letter or digit, so that query strings in URLs survive. In page text the old rule still applies.

Is &apos; valid HTML?

In HTML5, yes, but it was not part of HTML 4, and some older systems do not know it. The encoder writes &#39; for the apostrophe, which works everywhere.

Does escaping HTML prevent XSS?

It prevents it for text placed in page content and in quoted attribute values. It does not make text safe inside script blocks, style attributes, event handlers or URLs, which need their own encoding or validation.

How are emoji encoded?

As one reference for the whole code point: 😀 is &#128512; or &#x1F600;, never two references for the UTF-16 surrogate halves, which browsers would turn into two replacement characters.