HTML Entity Encoding: When You Actually Need It

HTML entity encoding is one of those topics developers half remember from years ago, and the half-remembered version is often wrong in a way that either breaks pages or creates a false sense of security. This post sets out exactly which characters need encoding, where, and why entity encoding alone does not stop cross-site scripting. The encoder at /dev-tools handles the mechanical conversion once you know which rules apply.
The five characters that actually matter
HTML syntax is built around a small set of characters, and only these genuinely need special handling in most content: the less-than sign, because it starts a tag; the greater-than sign, conventionally encoded to close a corresponding less-than cleanly though strictly only the less-than is dangerous; the ampersand, because it starts an entity reference; and, within attribute values, the double quote or single quote depending on which one delimits the attribute.
Every other character, including accented letters, currency symbols and punctuation, can appear literally in a correctly encoded UTF-8 HTML document without any entity at all, which surprises people who remember entity tables full of accented letters from older tutorials.
- Less-than sign: encode as <
- Ampersand: encode as &
- Double quote inside a double-quoted attribute: encode as "
- Single quote inside a single-quoted attribute: encode as '
- Greater-than sign: encode as > for symmetry, though it is optional in most text contexts
Attribute context versus text-node context
What needs encoding depends on where the value is placed. Inside a text node, between two tags, only less-than and ampersand are structurally significant, since quote characters have no special meaning there. Inside an attribute value, whichever quote character delimits that attribute becomes significant and must be encoded if it appears in the value, while the other quote type can usually be left alone, and ampersand still needs encoding because attribute values also support entity references.
An unquoted attribute value is its own case with additional characters that need care, such as whitespace and equals signs, which is one of several reasons to always quote HTML attributes rather than relying on the unquoted form the specification technically permits.
Numeric versus named entities
A named entity like & or © is easier for a human reading the raw HTML source to recognise, but only a defined subset of characters have official names, and support for the full named entity list varies slightly between parsing contexts. A numeric entity, either decimal such as & or hexadecimal such as &, can represent any Unicode code point and is unambiguous regardless of which named entities a particular parser recognises.
For the handful of characters that need encoding in ordinary HTML, either form works reliably in every modern browser, so the choice mostly comes down to readability preference rather than compatibility.
UTF-8 means you rarely need entities for accented characters
Older guidance recommended encoding every non-ASCII character as a numeric entity to guard against documents being served or interpreted with the wrong character encoding. With a document correctly declared and served as UTF-8, which is the default assumption in modern HTML and the near-universal practice today, accented letters, currency symbols and most punctuation can be written directly in the source file and will display correctly in every current browser.
Reaching for entity encoding on these characters today mostly adds noise to the HTML source without solving a real problem, and is a habit worth dropping once a project reliably serves UTF-8.
Entity encoding is not an XSS fix on its own
Encoding the five structural characters when inserting untrusted text into an HTML text node or attribute value is a necessary part of preventing cross-site scripting, but it is not sufficient by itself for every injection point. Inserting untrusted data into a script block, an event handler attribute, a URL used as an href or src, or a CSS value each has its own escaping rules, and HTML entity encoding alone does not neutralise a value placed directly inside a script tag or an inline event handler.
The safer general approach is to avoid inserting untrusted data into those higher-risk contexts entirely wherever possible, and to use context-appropriate encoding or a templating system that encodes automatically for whichever context it renders into, rather than treating one generic HTML entity encoder as a universal defence.
JSON encoding is a different job
JSON has its own escaping rules, based on backslash sequences rather than ampersand-based entities, and a string being safely embedded inside a JSON payload has nothing to do with whether it is also safe to place inside an HTML document. A value that has been correctly JSON-encoded and then inserted directly into an HTML page without further HTML encoding can still contain unescaped less-than or ampersand characters that break the surrounding markup or enable injection.
Treat JSON encoding and HTML entity encoding as two separate steps applied for two separate purposes, applying whichever one, or both in sequence, matches the actual context the data will end up in.
URL encoding is also a different job
Percent-encoding, used for characters inside a URL such as spaces becoming %20, follows yet another set of rules again, and is concerned with which characters are valid within a URL component rather than which characters have special meaning in HTML markup. A correctly percent-encoded URL placed inside an href attribute may still need its ampersand characters, which commonly appear between query string parameters, HTML entity encoded as well if the URL is embedded directly in HTML attribute syntax rather than set through script.
This is a frequent source of confusion: a query string with multiple parameters joined by ampersands is syntactically valid as a URL, but when that same string is written literally inside an href attribute in an HTML document, each ampersand should also be HTML entity encoded to keep the markup itself correct.
Using an entity encoder in practice
A dedicated HTML entity encoder such as the one on /dev-tools is useful for quickly checking exactly which characters in a string will be transformed and what the encoded output looks like, particularly when debugging why a page renders literal ampersand-hash sequences instead of the character they were meant to represent, which usually means a value was encoded twice by mistake.
Reach for the tool when preparing a static snippet of text to paste into HTML source by hand, and rely on your templating or rendering framework's automatic context-aware encoding for anything generated dynamically at runtime, since manual encoding of dynamic data is exactly the kind of step that gets missed under time pressure.
A worked example: encoding a user comment safely
Say a comment field submits the text she said "hi" & left. Inserted into a text node without encoding, the double quotes render fine since quotes have no special meaning in text content, but the ampersand needs encoding to she said "hi" & left, otherwise a browser parsing the raw source may try to interpret whatever follows the ampersand as the start of an entity reference and render the output incorrectly if it happens to match a recognised entity name.
If that same comment text is instead placed inside an HTML attribute, for example a title attribute delimited with double quotes, the double quote characters in the text now do need encoding to " to avoid closing the attribute early, while the ampersand still needs its own encoding regardless of the surrounding quote style.
Common mistakes to check for
A short list of the errors that come up repeatedly when reviewing HTML output for encoding correctness.
- Double-encoding: running an already-encoded string through the encoder again, turning & into &amp;
- Encoding on the way in and forgetting to decode on the way out, so stored values displayed elsewhere show literal entity text
- Assuming URL encoding covers HTML attribute safety, when an href built from concatenated strings still needs its ampersands HTML encoded
- Relying on entity encoding to sanitise a value destined for a script block or event handler attribute, where it provides no protection at all
- Forgetting that JSON embedded inside an HTML script tag with type application/json still needs the sequence </script> escaped if the JSON payload could ever contain that literal substring
FAQ
Do I need to encode a forward slash? No, the forward slash has no special meaning in HTML text or attribute content and does not need encoding, despite older guidance sometimes suggesting otherwise for closing tags.
Is ' safe to use? It is a valid named entity in HTML5 and current browsers render it correctly, but it was not part of the original HTML4 named entity list, so ' is the more universally compatible numeric alternative if you need to support very old parsers.
Should I encode emoji or other characters outside the basic multilingual plane? No, as long as the document is served as UTF-8, which handles the full Unicode range including emoji and characters outside the basic multilingual plane, without any entity encoding required.
Questions about the tools in this guide
Short answers about the hubs this article touches, each linking straight to the tool.