HTML Entity Encoder/Decoder

Encode special characters to HTML entities and back

TextHTML entities

About HTML Entity Encoder/Decoder

Encoding turns the five characters & < > " ' into &amp; &lt; &gt; &quot; &#39;, converts 22 common symbols such as ©, € and — into named entities, and writes any other non-ASCII character as a decimal reference like &#233; for é. Decoding follows the same rules as a browser: all 2,125 names in the HTML Standard plus decimal and hex references are reversed, and names that are not in the table are left exactly as written.

Entities exist for two reasons: to show HTML syntax characters as text, and to stop user input from being parsed as markup or script. The second is a security job, and it only works if you know which characters matter in which place.

The characters that actually matter for XSS

OWASP's XSS prevention guidance is organised by output context, because the dangerous characters differ. In text between tags, escaping < and & is enough to prevent a new tag from opening. Inside a quoted attribute value, the quote character that delimits it and & are what count; miss the quote and an attacker can close the value and add onmouseover=... as a fresh attribute. Because this tool escapes all five characters, its output is safe in both element text and quoted attributes.

Some places are out of reach for entity encoding altogether:

  • Unquoted attribute values: in <div class=value>, a space, / or = can end the value. Always quote attributes.
  • Inside <script> and <style>: these are raw text elements, so entities are not decoded — &lt; stays four literal characters. The danger there is the string </script>. Serialise data as JSON and escape < as \u003c.
  • URL attributes like href and src: javascript:alert(1) contains nothing to escape. Worse, attribute values are entity-decoded before use, so javascript&#58;alert(1) still runs. Validate URLs against an allow-list of schemes such as https:.

&#39; versus &apos;

The tool writes the apostrophe as &#39; for historical reasons. &apos; has always existed in XML but was not part of HTML 4, so older browsers and some email clients did not recognise it. The current WHATWG HTML Standard includes &apos;, so both work in modern browsers; &#39; is the conservative choice for HTML email and legacy renderers.

Decoding follows the browser's rules

The HTML Standard defines 2,125 named character references, and for legacy compatibility 106 of them — &amp, &lt, &copy, &eacute and others — are recognised even without the semicolon. The decoder uses the same table, so &hearts;, &eacute; and a bare &copy all come back. Without a semicolon only the longest legacy name is replaced, so &notit; becomes ¬it;. One difference remains: inside an attribute value a browser leaves &copy= alone when the name is followed by = or a letter, while this tool always applies the element-text rule.

Numeric references follow the standard too. &#128; through &#159; are remapped to the Windows-1252 characters old documents meant by them, so &#150; becomes – (U+2013) and &#146; becomes ’ (U+2019) instead of invisible C1 control characters. &#0;, lone surrogates such as &#xD800; and anything above U+10FFFF become U+FFFD. As in a browser, the semicolon after a numeric reference is optional. That makes the tool safe for cleaning text exported from an old CMS or a Word-to-HTML converter.

Seeing &amp;amp;? That's double encoding

A page title that shows “Tom &amp; Jerry” literally, or a value that grows another amp; on each save, has been escaped twice — typically once on the way into the database and again by an auto-escaping template on the way out. The rule is to store the original text and escape once, at output, for the context you are writing into. To inspect already-damaged data, run the decoder repeatedly until the text stops changing.

Do you need entities for accented letters?

Not if the page is served as UTF-8, which is what the WHATWG Encoding Standard requires of new content. é is two bytes in UTF-8 and seven as &#233;. Numeric references only earn their keep when you cannot control the charset — pasting a fragment into a system with an unknown or legacy encoding, for example.

Worked examples

A comment containing markup

Input
<img src=x onerror=alert(1)>
Output
&lt;img src=x onerror=alert(1)&gt;

With < escaped, no tag opens; the browser shows the text. That is sufficient in element content.

Trying to break out of an attribute

Input
" onfocus="alert(1)
Output
&quot; onfocus=&quot;alert(1)

Placed inside value="...", the quote no longer closes the attribute. This holds only because the attribute is quoted.

Symbols and accents

Input
Café © 2026 — 10€
Output
Caf&#233; &copy; 2026 &mdash; 10&euro;

é (U+00E9) is not in the tool's name table, so it becomes decimal 233; ©, — and € have names.

A Windows-1252 leftover

Input
It&#146;s
Output
It’s

The 128–159 range is read as Windows-1252. Decoded literally, 146 would be U+0092, an invisible control character.

How to use it

  1. Paste your text.
  2. Choose encode or decode.
  3. Copy the result into your HTML or code.

Frequently asked questions

Is HTML-encoding enough to prevent XSS?

In element text and quoted attributes, yes. Script blocks, URL attributes, unquoted attributes and CSS need different handling. Prefer an auto-escaping template engine and textContent over innerHTML.

What is &nbsp; really?

U+00A0 NO-BREAK SPACE. It prevents a line break at that point and is not collapsed with neighbouring spaces. When copied, it is not an ordinary space, so searches and comparisons may fail.

Why isn't &hearts (without a semicolon) decoded?

Only the 106 legacy names the HTML Standard lists (&amp, &copy, &eacute and so on) work without a semicolon, and &hearts is not one of them. Browsers leave it as text too. Write &hearts; with the semicolon.

Decimal or hex references?

They are equivalent. Hex (&#x2665;) lines up with U+2665 notation; this tool emits decimal.

Related guides

Sources

Last reviewed:

Privacy and how data is handled