Free online HTML entity encoder
HTML encode for the context it lands in
Paste a value and get it back as HTML entities — free, instantly, with no account — but first tell the page where the value is going, because that is what decides the answer. A text node needs only & < and >; a quoted attribute value needs the two quote characters as well, and getting that distinction wrong is behind a good share of real XSS bugs. Named, decimal and hexadecimal forms are all available, with a switch for the one name that is genuinely unsafe to use. Decoding runs the same page in reverse across 253 named entities and every numeric reference, including the 27 that HTML requires to be read through Windows-1252 rather than as the control characters their numbers name.
- 100% free
- No signup
- Encode and decode
- 253 named entities
- Text and attribute contexts
The escaped markup appears here as you type.
Waiting for something to work on — paste markup here, or press Ctrl+V anywhere on the page.
The five that XML defines
| Character | Named | Decimal | Hex | When it is required |
|---|---|---|---|---|
| & | & | & | & | Always. It starts every other reference, so an unescaped one turns the next word into a broken entity. |
| < | < | < | < | Always. This is the character that opens a tag and the one an injected payload needs. |
| > | > | > | > | In text, only to close a CDATA end marker safely — but escaping it costs nothing and keeps the output XML-clean. |
| " | " | " | " | Inside a double-quoted attribute value. Not needed in a text node. |
| ' | ' | ' | ' | Inside a single-quoted attribute value. Write ' rather than ' — HTML 4 never defined that name, so old parsers print it literally. |
Escaping is the last step before output, not a cleaning stage: escape once, at the moment the value is written, and never store the escaped form. Markup that needs re-indenting rather than escaping belongs in the HTML formatter.
How to encode and decode HTML entities
Name the destination, pick the reference form, copy the result.
Say where the value is going
The “Where it lands” menu is the important control, and it changes the answer rather than the presentation. Text node covers a value written between two tags. Attribute value covers one written inside quotes, and escapes both quote characters rather than guessing which the template used. ASCII-only output is for a channel that cannot carry UTF-8 at all — an email declared as us-ascii, or a system stuck on latin-1.
Pick the form of the references
Named references read well and are what a human will maintain; decimal and hex are what a strict XML consumer wants, because XML defines only five names and treats the rest as undeclared entities. With named selected there is one extra switch: write the apostrophe as ' rather than ', which is the safe choice because HTML 4 never defined that name.
Or go the other way
Switch to Decode and paste text full of & and —. Named references resolve from a table of 253 names, numeric ones from any decimal or hex value, and anything unrecognised is left exactly as written rather than deleted. Where the input holds a reference between € and Ÿ the page says so, because those do not mean what the number says they mean.
Technical specifications
| Escape sets | Text node (& < >), attribute value (& < > " '), and ASCII-only, which adds every character above U+007E plus the control characters other than tab, CR and LF |
|---|---|
| Reference forms | Named, decimal (&) or hexadecimal (&); with named selected, the apostrophe can be forced to ' because HTML 4.01 never defined ' |
| Named entities known | 253 — the HTML 4.01 set plus apos — used for both encoding and decoding. HTML5 defines 2,231, so a rare name is left as written rather than resolved incorrectly |
| Numeric decoding | Any &#nnn; or &#xHH; up to U+10FFFF, with surrogates and U+0000 replaced by U+FFFD as the HTML parser does |
| Windows-1252 remapping | The 27 references between € and Ÿ are mapped as HTML5 §13.2.5.80 requires, so — decodes to an em dash and not to a C1 control character |
| Unknown references | Left exactly as written and listed under the output, because deleting an unrecognised &foo; would delete text that was never an entity |
| Semicolons | Required. HTML's legacy list of 106 names that parse without one is deliberately not implemented, since guessing where an entity ends changes the meaning of ordinary text |
| Maximum input and processing | 1,048,576 characters, converted in this tab as you type; free, no signup, and nothing is uploaded |
Frequently asked questions
Which characters have to be escaped in HTML?
It depends entirely on where the value lands, and there are only two answers worth memorising. In a text node — between an opening and a closing tag — you must escape & and <, and escaping > as well costs nothing and keeps the output valid XML. Inside a quoted attribute value you must additionally escape the quote character that wraps it, and in practice both quote characters, because the template may change. Those five are the whole ordinary case; everything beyond it is a transport concern, not a correctness one.
' or '?
Use '. The name apos is defined in XML 1.0 and in HTML5, but not in HTML 4.01 — so an HTML 4 parser, and a surprising number of older email clients and feed readers, print the six literal characters instead of an apostrophe. The numeric reference has been valid in every version of both languages, costs one character less, and cannot be misread. This is the only one of the five where the named form is a genuine liability, which is why it has its own switch above.
Named or numeric — does it matter?
For a browser, no; for an XML parser, a great deal. HTML5 defines 2,231 named references and a browser knows all of them, so — and — are interchangeable in a web page. XML declares only five — amp, lt, gt, quot, apos — and treats any other name as an undeclared entity, which is a fatal error rather than a warning. So a value destined for an RSS feed, an SVG file, an XHTML document or a SOAP envelope should use numeric references for everything except those five.
Why did — decode to an em dash rather than a control character?
Because the HTML standard requires that particular lie. Code points U+0080 to U+009F are C1 control characters that no page ever legitimately contains, but Windows-1252 puts printable characters at those byte values — the em dash sits at 0x97 — and a generation of Microsoft editors wrote them straight into HTML. Rather than render nothing, parsers were standardised to map those 27 numeric references through Windows-1252, so — is an em dash, ’ is a curly apostrophe and € is a euro sign. This page follows the same table and tells you when it used it.
I escaped the value and it is still injectable. How?
Because entity encoding only protects two of the five places a value can land. It works in a text node and in a quoted attribute value. It does nothing for an unquoted attribute, where a space or a slash is enough to start a new attribute such as onmouseover. It does nothing inside a <script> block, where the JavaScript parser never sees entities. And it does nothing for a URL: a browser decodes entities in an href before it inspects the scheme, so javascript:alert(1) runs. Those three contexts need quoting, JSON escaping and a scheme allow-list respectively — the page warns when your input looks like the third case.
Why is my page showing &amp; instead of an ampersand?
Something escaped an already-escaped string. Each pass turns & into &, so & becomes &amp; and the browser faithfully displays the first entity as text. The cause is almost always two layers each doing the right thing — a template engine that auto-escapes plus application code that escaped first — and the fix is to remove one of them, not to decode at render time. Escape once, at the moment of output, and never store the escaped form in the database.
Do I need to encode é and 東 if my page is UTF-8?
No. A UTF-8 document can carry every character directly, so é and é are identical to the parser and the second is shorter, greppable and diff-friendly. Encoding them is only necessary when the bytes have to survive a channel that is not UTF-8 — an email declared as us-ascii, a legacy system that reads latin-1, a CSV export nobody controls — which is what the ASCII-only mode is for. Otherwise it inflates the file and makes the source harder to read for no benefit at all.
About HTML entities and where escaping stops working
An entity reference is a way of writing a character that the markup around it would otherwise claim. Only two characters genuinely need it in running text: the ampersand, because it introduces every other reference, and the less-than sign, because it opens a tag. The angle bracket that closes one is conventionally escaped too, which costs nothing and keeps the output valid XML. That leaves the quotes, and they matter only inside an attribute value, where the character that wraps the value must not appear unescaped within it. Five characters, two contexts — and the reason tools disagree so much is that most of them apply one rule everywhere and escape quotes in body text, producing output that shows up mangled in search results and in anything that copies the page as plain text.
The two vocabularies are a common source of surprise. XML defines exactly five named entities and nothing else, so an SVG file, an RSS feed or a SOAP envelope containing is not merely sloppy — it is a fatal parse error under the XML rules, because the entity was never declared. HTML is the opposite: HTML 4.01 defined 252 names, HTML5 raised it to 2,231, and a browser also recognises a legacy list of 106 that work without their closing semicolon, which is why © in the middle of a sentence about copying can turn into a symbol. Numeric references sidestep all of it: they mean the same thing in both languages and in every version, at the cost of being unreadable. This page keeps the 253-name table for the cases where readability wins and offers the numeric forms for the cases where it does not.
The part worth internalising is where escaping stops helping. Entity encoding is a defence for two contexts — a text node and a quoted attribute value — and it is worth nothing in three others. An unquoted attribute can be escaped perfectly and still be broken out of with a single space, because the attribute ends at whitespace. Inside a <script> block the JavaScript parser never decodes entities at all, so the value needs JSON-style escaping instead. And a URL is decoded before its scheme is examined, so no amount of entity encoding stops javascript: from running — only an allow-list of schemes does. Escape at the point of output, once, with the rule that matches the destination; if what you are looking at is a document that needs re-indenting rather than a value that needs escaping, the formatter is the page you want.
Where the text is converted
Entirely in this tab. Both directions are table lookups running in JavaScript on your machine, with no request behind them, so the markup you paste is not transmitted and not recorded. It also means the page keeps working offline once loaded — useful, given how often the thing being escaped is a fragment of a page that has not shipped yet.