ToolSite

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.

By ToolSite5 min readguides

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:

&lt;div&gt;

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:

  1. &amp; for ampersand (&)
  2. &lt; for less-than (<)
  3. &gt; for greater-than (>)
  4. &quot; for double quote (")
  5. &#x27; 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 &apos; but it is not universally supported by older parsers. Use the numeric form &#x27; (hex) or &#39; (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>&lt;script&gt;alert(&#x27;XSS&#x27;)&lt;/script&gt;</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: &amp;, &lt;, &gt;, &quot;. Easier to read and remember.
  • Numeric decimal: &#38;, &#60;, &#62;, &#34;. Decimal code points.
  • Numeric hexadecimal: &#x26;, &#x3C;, &#x3E;, &#x22;. 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. Use JSON.stringify or 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. A javascript: URL injected into href is 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 | |---|---|---| | &nbsp; | non-breaking space | Prevent line wrapping between words | | &copy; | (C) | Copyright notices in footers | | &mdash; | em dash | When you intentionally want an em dash | | &ndash; | en dash | Ranges like 9-5 | | &rarr; | 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, like Great post! <3, and see that the < in <3 is escaped. The browser would otherwise treat <3 as the start of a tag.

Related Reading