HTML Entities Explained: Escaping Special Characters
Learn what HTML entities are, the five essential ones to know, and why escaping special characters matters for security including XSS prevention on the web.
What HTML Entities Are
HTML entities are sequences that represent characters that would otherwise be
interpreted as HTML markup. They let you display <, >, &, and other
special characters as literal text on a web page instead of having the browser
parse them as tags.
Every entity starts with & and ends with ;. Between those delimiters is
either a mnemonic name or a numeric code. The browser sees the entity and
renders the corresponding character. The user sees the character. The HTML
parser never sees a tag or attribute.
For example, to display the literal text <div> on a page (not render a div
element), you write:
<div>
The Five Essential Entities
There are hundreds of named entities covering everything from copyright symbols to mathematical operators, but only five are essential for basic HTML safety. These five prevent the most common injection vectors:
&for ampersand (&)<for less-than (<)>for greater-than (>)"for double quote (")'for single quote / apostrophe (')
The ampersand is the most important one because it is the entity delimiter
itself. If you do not escape & first, you risk creating ambiguous output
where a later & followed by text looks like an unintended entity. Always
escape & before escaping the others.
There is no named entity for single quote in the HTML4 spec. HTML5 added
' but it is not universally supported by older parsers. Use the numeric
form ' (hex) or ' (decimal) for maximum compatibility.
Why Escaping Matters: XSS
When a web application inserts user input directly into HTML output without
escaping, a user can inject HTML tags. In the worst case, they can inject
<script> tags, which leads to Cross-Site Scripting (XSS):
<!-- User input: <script>alert('XSS')</script> -->
<!-- Unescaped output: -->
<p><script>alert('XSS')</script></p>
<!-- Properly escaped output: -->
<p><script>alert('XSS')</script></p>
The escaped version displays as literal text. The browser never executes it. This is not a visual trick. The HTML parser genuinely treats those bytes as text content, not as elements.
XSS is consistently in the OWASP Top 10 web security risks. Escaping output is the primary defense. It is cheap, mechanical, and effective. There is no reason to skip it.
Modern frameworks (React, Angular, Vue) escape output by default when you use template syntax or JSX. The risk is highest in server-rendered templates, legacy PHP apps, and any code that builds HTML strings with string concatenation. If you see string concatenation building HTML, that is the place to check for missing escaping.
Named vs Numeric Entities
Entities come in two forms, and the browser renders them identically:
- Named:
&,<,>,". Easier to read and remember. - Numeric decimal:
&,<,>,". Decimal code points. - Numeric hexadecimal:
&,<,>,". Hex code points, often preferred in tooling.
All three forms are equivalent to the parser. Named entities are preferred for hand-written HTML because they are readable. Numeric entities are sometimes needed for characters that have no named equivalent or when you need to be precise about which codepoint you are emitting.
Context Matters: Where to Escape
The same character needs different escaping depending on where it appears in HTML. Escaping for the wrong context is a common vulnerability:
- HTML text content: escape
<,>,&. The three core characters that can create or terminate elements. - HTML attribute values (double-quoted): escape
"and&. The"ends the attribute. The&might start an entity that the attribute parser expands. - HTML attribute values (single-quoted): escape
'and&. Same logic. - Inside
<script>tags: HTML escaping is not sufficient. HTML parsers do not process entities inside<script>the same way. The first</sequence ends the script block regardless of escaping. UseJSON.stringifyor a dedicated serializer for JavaScript contexts. Better yet, avoid inline scripts entirely. - Inside
<style>tags: similar to<script>. HTML escaping does not apply. Use CSS-specific escapes if you must inject user data into stylesheets. - URL attributes (
href,src): escape for the URL context first (percent-encoding), then for the HTML attribute context. Ajavascript:URL injected intohrefis an XSS vector even if angle brackets are escaped.
A safe approach: use a templating library that distinguishes between text content, attribute values, and JavaScript contexts, and auto-escapes for each. Do not concatenate strings into raw HTML.
Beyond the Big Five: Common Named Entities
While the five above are mandatory for safety, a handful of others come up often enough to be worth knowing:
| Entity | Renders As | When You Might Need It |
|---|---|---|
| | non-breaking space | Prevent line wrapping between words |
| © | (C) | Copyright notices in footers |
| — | em dash | When you intentionally want an em dash |
| – | en dash | Ranges like 9-5 |
| → | right arrow | UI arrows without images |
Try it yourself: open the HTML Escape Tool, type
<script>alert("XSS")</script>into the input, and click Escape. The output shows every special character converted to its entity form. Paste the escaped string back in and click Unescape to see the original. Now try a realistic example: type a comment a user might leave, likeGreat post! <3, and see that the<in<3is escaped. The browser would otherwise treat<3as the start of a tag.