Cookies for analytics and advertising
We use cookies for analytics and advertising, both sent to Google. Refusing changes nothing you can see.Read the privacy page
Paste text containing character references and read what it says. Named ones, decimal ones and hexadecimal ones are all handled, and anything unrecognised is left visibly alone rather than quietly dropped — which is what tells you whether the input was odd or the decoder was.
Where it runs
Nothing is uploaded, because there is no file — it is worked out in this page.
No queue, no account
It answers as fast as your machine can, and it never asks who you are.
As often as you like
Nothing is counted and nothing is capped — answering again costs us nothing.
The one-line implementation is to set `innerHTML` on a detached element and read `textContent` back. It handles all 2,231 named references for free, it is what nearly every snippet on the internet suggests, and it is an HTML parser being handed untrusted input.
A detached element does not run scripts. It does still fetch: an image tag with a remote source produces a request the moment it is parsed, before anything is read back. A page whose whole claim is that your input never leaves the device cannot contain a path where pasting the wrong string sends one. So the named set here is a lookup table, and that table is what lets this page make the claim it makes.
The table holds the references that actually turn up: the five structural ones, the typographic set a CMS produces — dashes, curly quotation marks, the ellipsis — currency symbols, the common mathematical operators, the German umlauts and a handful of arrows. Numeric references need no table at all, since they name a code point directly.
Anything else comes back exactly as it went in. That is deliberate and it is the more useful behaviour: an untouched reference is visible, so you can see that a strange one was in your input rather than wondering where a word went. Dropping the unknown would give tidier output and a worse answer.
If the result still contains references, the text was escaped twice — the doubled form decodes to the single one, and only a second pass gives the character itself. It is the commonest reason to be on this page, and the cause is almost always the same: a value escaped when it was stored and escaped again when it was displayed.
Decode as many times as it takes to read it, then fix it once at the source rather than repeatedly at the destination. Text should be stored as it was written and escaped only when it is inserted into a page; escaping on the way in is how the doubled form got into the database to begin with.
A numeric reference naming a surrogate — the range from U+D800 to U+DFFF — is left alone, as is anything past U+10FFFF. Both are outside the range of real characters, and a decoder that produces one anyway hands back a string that cannot be encoded to UTF-8 at all.
The practical effect of doing it the other way is that the next thing you paste the result into throws, somewhere unrelated, with an error about invalid input that mentions none of this. Leaving the reference visible keeps the problem where the problem is.
RSS and Atom feeds, where an item body is escaped so it can live inside XML. CMS exports, where a title carries a numeric reference because an editor typed a curly apostrophe. Log lines and error messages that passed through a template on the way out. API responses from something that renders HTML internally and hands you the rendering.
In every one of those the escaping was correct where it happened and is wrong where you are now, which makes decoding a step in a pipeline rather than a repair. If you are doing it by hand more than once, the thing to change is whatever is giving you HTML when you asked for text.
Because it is not in the table this uses, or because it names something that is not a valid character. Unknown references are left visible on purpose — dropping them would give tidier output and hide the fact that something odd was in the input. If it is a real reference that ought to be recognised, it is worth reporting.
The text was escaped twice, so one pass peeled off one layer. Decode again and you will get the real character. The cause is nearly always a value escaped when it was saved and escaped again when it was rendered, which is worth correcting at the source rather than at every place it is read.
Yes — decimal and hexadecimal both, and neither needs a lookup table because each names a code point directly. What is deliberately excluded is any reference to a surrogate or past the last valid code point, since decoding those yields a string that cannot be encoded back to UTF-8.
Yes, and the design is specifically about that. The usual implementation of an entity decoder feeds the text to an HTML parser, which can issue network requests for images before anything is read back. This one uses a lookup table and never parses, so pasting a hostile string does nothing but decode it.
You can, but you probably do not want to. Decoding a document turns its escaped examples of markup back into markup, which changes what the document means. This is for a field, a title or a line of text that was escaped once and should not have been.