HTML Encoder
Encode text as HTML entities, in named, decimal or hex form, and decode entities exactly as a browser reads them in a page.
Overview
In HTML, < starts a tag and & starts an entity, which the HTML standard
calls a character reference. To show such a character as text, it is written as an entity:
<, >, &, and in attribute values
" or '. Any character can also be written by its number, in decimal
as ü or in hex as ü, both for ü.
Web interface
Paste text or HTML into the input; the output updates as you type. Auto works out the direction, Encode and Decode fix it. The options only show when encoding:
- Encode Quotes, on by default:
"and'are encoded too. - All Non-ASCII, off by default: every character beyond ASCII becomes a numeric entity.
- Numbers: whether numeric entities are written in Decimal or
Hex, for non-ASCII characters and for
'.
The line under the output gives the length before and after, counted in characters as a reader counts them, and the number of entities written or decoded. Copy copies the output. Clear empties everything and returns to Auto and the default options. Ctrl/⌘ + Enter runs the conversion again. The dice in the corner of the input loads a random example.
How Auto decides
Auto decodes input that contains at least one complete entity, ending in a semicolon, that HTML knows. Everything else is encoded.
| Input | Auto | Output |
|---|---|---|
Tom & Jerry | decodes | Tom & Jerry |
<b>bold</b> | encodes | <b>bold</b> |
AT&T | encodes, &T is no entity | AT&T |
&foo; | encodes, HTML has no entity of that name | &foo; |
When Auto guesses wrong, Encode and Decode settle it.
Encoding
| Character | Becomes | When |
|---|---|---|
& | & | always |
< > | < > | always |
" | " | with Encode Quotes |
' | ' or ' | with Encode Quotes |
| anything beyond ASCII | ü or ü for ü | with All Non-ASCII |
Encoding works on whole characters: 😀 becomes the single entity 😀
(😀). The apostrophe is written as a number because ' is missing
from HTML 4, while ' works everywhere.
All Non-ASCII is for places that only pass ASCII, or for documents that are not saved as UTF-8. A UTF-8 page
shows ü and 😀 as they are. Text that already contains entities is encoded again,
& becomes &amp;, which is right for text that shows an entity.
Decoding
Decoding is done by the browser's own HTML parser, so the result is exactly what a page shows:
- every named entity of the HTML standard, from
&to…and ; - numeric entities in decimal and hex, including characters beyond the first 65,536 such as emoji;
- the old forms without a semicolon that browsers still accept:
© 2024becomes© 2024; - the numbers 128 to 159 read as Windows-1252, as browsers do:
€becomes€,ŸbecomesŸ. The five numbers Windows-1252 leaves unassigned, such as, stay the control characters they are; �, surrogate numbers and numbers beyond Unicode become�(U+FFFD).
Tags in the input stay text. The input is parsed as the content of a text field that is never added to the
page, so an <img> or <script> in it never becomes an element: nothing
is loaded and nothing runs.
Where encoding protects
Encoding is one of the main defenses against Cross-Site Scripting (XSS), but only where the browser reads the text as HTML text:
| Place in the page | Encoding |
|---|---|
between tags: <p>…</p> | protects |
in a quoted attribute value: title="…" | protects, with Encode Quotes |
in an unquoted attribute value: title=… | does not protect, a space ends the value; quote the attribute |
inside <script> or <style> | does not protect, entities are not decoded there; use the escaping of JavaScript or CSS |
in a URL: href="…", src="…" | does not protect against javascript: links, which are decoded before use; check the scheme |
No API
There is no API for this tool. Encoding and decoding run in the browser; in a program, use the escaping
of the template engine or language at hand, such as htmlspecialchars() in PHP or
html.escape() in Python.
Limits
The input has no length limit. 1 MB takes under half a second in every browser tested, drawing included.
Converting itself is fast: 10 MB take under 0.7 seconds in every browser tested. Drawing that much text in the input and output fields is what takes time, and it depends on the browser. For 10 MB it took about 1.5 seconds in Firefox, 2 seconds in Safari's engine and 4 to 4.5 seconds in Chrome.
Privacy
Nothing leaves the browser. Encoding and decoding run on the page, nothing is stored, and Copy writes to the clipboard only when you press it.