Encode & hash

HTML Unescape

Turn named, decimal and hexadecimal HTML entities back into the characters they represent.

Private by design — your data never leaves your device.
✓ Free forever✓ No sign-up✓ No ads✓ Works offline once loaded

HTML Unescape

Turn named, decimal and hexadecimal HTML entities back into the characters they represent.

Input

Escaped HTML

Nothing is uploaded.

Output

Decoded text

Your result appears herePaste on the left and select “Unescape HTML”

Escaped HTML shows up wherever markup has been stored as data and then quoted back at you: a CMS field that was escaped on the way in, an RSS description, a JSON API returning pre-rendered HTML, a scraped page, a database column, an error message echoing a request body. What you see is &lt;p&gt;Caf&eacute;&lt;/p&gt; when what you need to read is <p>Café</p>.

This tool decodes the lot: the five predefined entities, the full HTML5 named entity set — over two thousand of them, including &nbsp;, &eacute;, &mdash;, &copy; and &hellip; — plus decimal references such as &#232; and hexadecimal ones such as &#x2713;. Decoding is done by the html-entities library at html5 level, running in a Web Worker on your device. If entities survive the pass, you are told, because that means the content was escaped more than once.

How it works

How to use the html unescape

  1. 1

    Paste the escaped text

    A whole escaped document, a single field value, or a fragment quoted inside a log line. Entities are decoded wherever they appear; everything else is left exactly as it is.

  2. 2

    Check for the double-escaping warning

    If the output still contains entity-shaped sequences, a note reports how many. That is the signature of content escaped twice — &amp;lt; decoding to &lt; rather than to <.

  3. 3

    Run it again, or format the result

    Each pass removes one layer of escaping, so run it repeatedly until the warning clears. If what emerges is a full HTML document, send it to the HTML formatter to indent it.

Named, decimal and hexadecimal references

HTML supports three ways of writing the same character, and real-world content mixes all three freely because different producers made different choices.

  • Named references&amp;, &nbsp;, &eacute;, &mdash;. Readable, but HTML5 defines roughly 2,200 of them and no human remembers more than a dozen. All are decoded here.
  • Decimal references&#232; for è. Any Unicode code point written in base ten.
  • Hexadecimal references&#x2713; for a check mark. The same thing in base sixteen, which is how code points are conventionally written.

One decoded character deserves special mention because it causes real trouble downstream: &nbsp; becomes U+00A0, a non-breaking space. It looks exactly like an ordinary space in the output pane but is a different character. It will not match a \s-based split in some regex flavours, will not compare equal to a normal space, and is a frequent cause of "identical" strings that are not. If you are cleaning scraped content, replace U+00A0 with a plain space deliberately rather than assuming it already is one.

Note also that named entities are case-sensitive: &Eacute; is É while &eacute; is é. And unlike XML, which defines exactly five entities, HTML defines thousands — so text that unescapes cleanly here may not be valid XML content.

Entities remaining means it was escaped twice

When escaping is applied to already-escaped text, the ampersand of each existing entity is itself escaped. &lt; becomes &amp;lt;. One decode pass turns that back into &lt; — an entity, not a character — so the output looks stubbornly escaped.

This is why the tool counts entity-shaped sequences in its output and warns you. It is not a failure; it is a measurement, and a useful diagnostic about where content has been. Each pass strips one layer, so run it again. Content that has crossed several systems can carry three or four layers, and &amp;amp;amp;lt; in a support ticket is a real thing.

Decoding is deliberately not applied recursively in one go. Doing so would be lossy in the other direction: text that legitimately contains the literal string &lt; — a tutorial about HTML escaping, say — is correctly escaped once as &amp;lt;, and should decode to &lt; and stop there. Automatically collapsing it to < would corrupt the content. One layer per pass, with you deciding when to stop, is the only behaviour that is right in both cases.

If you are chasing the origin of double escaping in a system, the usual causes are: escaping on input and again on output, a template engine auto-escaping a value the application had already escaped by hand, or an API that returns pre-escaped HTML which a client then escapes for display. The fix is always to escape once, at the point of rendering.

Decoded is not the same as safe

Unescaping is the exact inverse of escaping, which means it removes the protection escaping provided. If the text you decoded came from a user, a scrape or any untrusted source, the result may contain live <script> tags, event handler attributes or javascript: URLs. Do not insert unescaped content into a page. Decode it to read it, then either re-escape before display or run it through a sanitiser that strips dangerous elements and attributes.

The legitimate uses are inspection and repair: reading what an API actually returned, recovering text that was escaped one time too many before storing it, extracting the real content from a scraped page, or checking whether a difference between two strings is real or just an encoding artefact.

Everything runs locally in your browser. That matters when the escaped fragment you are inspecting is a customer support ticket, an email body or a database row — none of it is transmitted anywhere.

Common questions

HTML Unescape FAQ

Why does my text still contain entities after decoding?

It was escaped more than once. Each pass removes one layer, so &amp;amp;lt; needs two passes to become <. The note tells you how many entity-shaped sequences remain, so just run it again until the count reaches zero.

Does it handle &nbsp; and other named entities?

Yes. The full HTML5 named entity set is supported — around 2,200 names including &nbsp;, &eacute;, &mdash;, &copy; and &hellip; — along with decimal and hexadecimal numeric references.

What does &nbsp; actually turn into?

A non-breaking space, U+00A0. It looks identical to a normal space but is a different character, so it will not match a plain space in a comparison or a regular expression. When cleaning scraped text, replace it explicitly.

Is it safe to put the decoded output on a web page?

Not if the source was untrusted. Decoding removes exactly the protection escaping provided, so any script tags or event handlers in the original become live again. Decode to inspect, then re-escape or sanitise before rendering.

Can it decode XML entities too?

The five predefined XML entities are all part of the HTML set, so they decode here. The reverse is not true: HTML defines thousands of names that are undefined in XML, so decoded content is not automatically valid to re-embed in an XML document.