HTML Entities vs Unicode Characters: What Is the Difference?
A Unicode character is the actual text value, while an HTML entity or character reference is source syntax that tells the browser which character to insert.
On this page
HTML entities vs Unicode characters at a glance
| Concept | Unicode character | HTML character reference |
|---|---|---|
| Meaning | Actual text character | HTML source notation for a character |
| Example | é | é, é, é |
| Stored in parsed DOM text | Character | Character after parsing |
| Requires HTML parser | No | Yes |
| Works outside HTML automatically | Yes, as text | No |
| Best general use | Literal UTF-8 text | Reserved syntax and special escaping |
| Related to UTF-8 bytes | Encoded into bytes | Parsed first, then encoded as text |
| Always named? | No | Can be named or numeric |
Unicode defines the character. HTML defines ways to reference that character in markup. UTF-8 defines how the resulting text is encoded as bytes.
What is a Unicode character?
Unicode assigns numeric code points to text elements. A character may be written directly in a source file, and HTML documents encoded as UTF-8 can contain most Unicode characters literally. Literal Unicode is not an HTML entity. The character's identity is independent of its HTML representation, font rendering is separate from character identity, and one visible grapheme can contain several Unicode code points.
| Character | Unicode name | Code point |
|---|---|---|
| A | LATIN CAPITAL LETTER A | U+0041 |
| é | LATIN SMALL LETTER E WITH ACUTE | U+00E9 |
| © | COPYRIGHT SIGN | U+00A9 |
| € | EURO SIGN | U+20AC |
| 😀 | GRINNING FACE | U+1F600 |
Inspect exact values with What Is a Unicode Code Point? and Unicode Character Inspector.
What is an HTML entity?
Developers often say HTML entity for several related forms. More precisely, HTML has named character references such as ©, decimal numeric character references such as é, and hexadecimal numeric character references such as é. The browser's HTML parser converts references into characters, so the parsed DOM normally contains the resulting character. Entities are HTML syntax, not Unicode encodings. Not every Unicode character has a named HTML reference, but numeric references can represent valid code points under HTML rules.
é
é
éAll three produce é after HTML parsing. Use HTML Entity Encoder and Decoder to test source text.
Named HTML character references
Named references begin with &, normally end with ;, and use names defined by the HTML specification. Some names are case-sensitive. They can improve readability for common symbols, but literal Unicode is often clearer for natural-language text.
| Named reference | Character | Code point |
|---|---|---|
& | & | U+0026 |
< | < | U+003C |
> | > | U+003E |
" | " | U+0022 |
' | ' | U+0027 |
© | © | U+00A9 |
| NO-BREAK SPACE | U+00A0 |
é | é | U+00E9 |
is not an ordinary space; it produces U+00A0. See What Are Invisible Unicode Characters?.
Decimal numeric character references
A decimal numeric character reference starts with &#, uses decimal digits and ends with ;. It represents a Unicode code point under HTML parsing rules, not decimal UTF-8 bytes.
| Decimal reference | Character | Code point |
|---|---|---|
A | A | U+0041 |
é | é | U+00E9 |
© | © | U+00A9 |
€ | € | U+20AC |
😀 | 😀 | U+1F600 |
Hexadecimal numeric character references
A hexadecimal reference starts with &#x or &#X, uses hexadecimal digits and ends with ;. Hex references often map visibly to U+ notation.
| Hex reference | Character | Code point |
|---|---|---|
A | A | U+0041 |
é | é | U+00E9 |
© | © | U+00A9 |
€ | € | U+20AC |
😀 | 😀 | U+1F600 |
U+1F600
HTML: 😀Literal Unicode vs named vs numeric references
| Display | HTML source | Parsed character |
|---|---|---|
é | é | U+00E9 |
é | é | U+00E9 |
é | é | U+00E9 |
é | é | U+00E9 |
The HTML source differs, but parsed text can be identical. UTF-8 source files can contain literal characters directly. Named references depend on HTML's defined name list; numeric references are available for valid code points. Literal Unicode usually improves readability for normal text, while reserved HTML syntax still requires context-aware escaping. Equivalent rendered output does not mean the original HTML source was identical.
Interactive HTML entity and Unicode comparison
This local comparison shows how characters become named, decimal and hexadecimal references, and how references decode back to text without executing markup.
HTML entity and Unicode comparison
Compare literal characters, named references, numeric references, code points and UTF-8 bytes.
Limit: 2,000 UTF-16 code units. Text stays in your browser.
When HTML escaping is required
HTML escaping is context-specific. A literal ampersand can begin a character reference, so source text often uses &. A literal less-than sign can begin markup, so text uses <. Greater-than signs are often allowed, though > can improve clarity. A double quote must be escaped inside a double-quoted attribute as ", and an apostrophe must be escaped or avoided in single-quoted attributes with ' or an appropriate quote strategy.
Rules differ for text nodes, double-quoted attributes, single-quoted attributes, unquoted attributes, script data, style data and URL values.
Characters that usually do not need entities
With UTF-8 HTML, developers can usually write natural-language text and emoji directly.
<meta charset="utf-8">
<p>café</p>
<p>Русский текст</p>
<p>日本語</p>
<p>😀</p>Content-Type: text/html; charset=utf-8Modern HTML supports literal Unicode. Source files should be UTF-8, and HTTP and document charset declarations should agree. Accented characters do not need named entities, and emoji do not require numeric references. Use entities for HTML syntax and special cases, not as a replacement for UTF-8 text.
HTML entities are not UTF-8
Character: é
Code point: U+00E9
HTML reference: é
UTF-8 bytes: C3 A9The processing flow is source syntax first, bytes later: HTML source goes through the HTML parser, character references become Unicode text in the DOM, and the document is encoded or transmitted as UTF-8 bytes. é is not a byte sequence. C3 A9 should not be inserted as numeric HTML references for é; é produces two different characters. Use Unicode vs UTF-8 and UTF-8 Encoder and Decoder.
HTML entities vs Unicode escape sequences
| Format | Example for é | Parser |
|---|---|---|
| HTML named reference | é | HTML parser |
| HTML numeric reference | é | HTML parser |
| JavaScript Unicode escape | \u00E9 | JavaScript parser |
| JSON Unicode escape | \u00E9 | JSON parser |
| Unicode notation | U+00E9 | Human-readable notation |
| UTF-8 bytes | C3 A9 | UTF-8 decoder |
HTML does not use JavaScript \uXXXX escapes in ordinary markup. JavaScript strings embedded in <script> follow JavaScript syntax. JSON embedded in HTML follows both embedding and JSON rules. Parser context must always be known. Read Unicode Escape Sequences Explained and use Unicode Escape Converter.
HTML entities in text nodes
<p>Tom & Jerry</p>
<p>5 < 10</p>The parser resolves & to & and < to <. The DOM text node contains the character. Reading textContent returns the character, and serializing HTML may escape it again. Literal < must be escaped when intended as text.
HTML entities in attributes
<a title="Tom & Jerry">
Example
</a>The parsed attribute value contains Tom & Jerry. Quotes must be escaped when they match the attribute delimiter. HTML escaping does not automatically make a URL safe, and event-handler attributes introduce JavaScript context and should generally be avoided. Modern applications should set attributes through safe APIs or templates.
element.setAttribute("title", userValue);DOM APIs set values and perform required serialization later.
HTML entities in JavaScript
HTML entities are not interpreted inside ordinary JavaScript strings. JavaScript uses its own string escape rules. é inside a JavaScript string remains literal text unless passed through an HTML parser, while \u00E9 is JavaScript Unicode escape syntax.
const htmlReference = "é";
const unicodeEscape = "\u00E9";
console.log(htmlReference); // é
console.log(unicodeEscape); // é
element.textContent = "é";Setting textContent displays literal entity text. Using innerHTML would parse it, but must not be used with untrusted input. Use textContent for untrusted text.
HTML entities in CSS
CSS does not generally use HTML entities. CSS uses CSS escape syntax, and external CSS files do not parse HTML named references. HTML references may be resolved before CSS only when they appear inside HTML markup in a relevant context.
.icon::before {
content: "\00A9";
}
.wrong::before {
content: "©";
}The second rule normally displays literal entity text rather than the copyright symbol. The Unicode escape guide covers CSS escape syntax.
HTML entities in URLs
HTML entity escaping and URL percent encoding solve different problems. In an HTML attribute, ampersands separating query parameters may need HTML escaping, while URL bytes may also require percent encoding.
<a href="/search?q=caf%C3%A9&page=2">
Search
</a>%C3%A9 is URL percent encoding of UTF-8 bytes for é. & is HTML escaping for the query separator. The browser parses the entity first; the URL parser then processes the resulting URL. One URL inside HTML can require both URL encoding and HTML escaping. Use URL Encoder and Decoder.
What is double encoding?
Double encoding occurs when already-escaped source is escaped again.
Original entity:
é
After escaping the ampersand:
&eacute;The rendered output is literal é. The browser resolves & to &, and the remaining text is not reparsed as a second entity in the same normal text parsing step. Another example is & encoded once as & and twice as &amp;. Encode once at the output boundary. Do not repeatedly escape already-escaped content.
Missing semicolons and ambiguous references
Character references normally end with ;. Some historical named references may be parsed without a semicolon in limited contexts, but omitting it can create ambiguous parsing. Attribute parsing can behave differently from text parsing, so generated HTML should always include semicolons. Use &, not a semicolon-free shortcut.
Invalid numeric character references
Values above U+10FFFF are invalid, surrogate code points are not valid Unicode scalar values, and U+0000 is treated specially. Some invalid historical values may be replaced according to HTML parsing rules, and the parser may emit U+FFFD or another mapped character. A browser's error recovery is not a validation strategy.
�
�
�Named entity availability
Named references are defined by HTML. Some common characters have names, but many Unicode characters do not. Numeric references can represent more valid code points, and literal UTF-8 is usually simpler than memorizing names. XML has a much smaller predefined entity set unless a DTD adds more.
| Context | Built-in named references |
|---|---|
| HTML | Large named-reference set |
| XML | Primarily amp, lt, gt, quot, apos |
HTML entities and non-breaking spaces
produces U+00A0 NO-BREAK SPACE. It is not equivalent to U+0020 SPACE, affects line wrapping, may appear invisible in copied text, can break equality checks and should not be used repeatedly for page layout. Replacing it with a normal space changes layout semantics. See How to Remove Zero-Width Characters.
HTML entities and normalization
Entity decoding does not normalize Unicode. NFC é produces U+00E9. NFD é produces U+0065 U+0301. Both may render as é, but HTML parsing preserves the resulting code-point sequence, and canonically equivalent strings can still compare differently. Normalize separately when the application requires it. Use Unicode Normalization Explained, NFC vs NFD and Unicode Text Compare.
HTML entities and grapheme clusters
One grapheme can require several character references. é represents decomposed é. ♥️ requests emoji-style heart. A family emoji may be written conceptually as 👨‍👩‍👧‍👦. Each reference maps to one code point, but several code points may form one grapheme cluster. Removing joiners or variation selectors changes rendering. Read What Is a Grapheme Cluster? and use Unicode Sequence Analyzer.
Safe HTML entity encoding
- Identify the output context.
- Use a trusted HTML template engine.
- Escape dynamic text at output time.
- Do not pre-escape data before storage.
- Avoid manual replacement chains.
- Escape ampersands before introducing custom entity text.
- Use UTF-8 source files.
- Preserve already-correct Unicode.
- Do not use
innerHTMLfor untrusted content. - Keep URL encoding separate from HTML escaping.
- Keep JavaScript escaping separate from HTML escaping.
- Add round-trip and security tests.
Store Unicode text. Escape it for the destination context when rendering.
HTML entity encoding in JavaScript
const element = document.querySelector("#output");
element.textContent = userInput;textContent prevents markup interpretation. For controlled entity encoding, use a DOM text node and serialization or reuse the project's existing encoder. A simple educational helper for text-node output is:
function escapeHtmlText(text) {
return text
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">");
}Attribute contexts also require quote handling. This helper is text-node-specific; framework or template escaping is preferable. Decoding must not use untrusted innerHTML.
HTML entity encoding in Python
Template engines should autoescape HTML output. Python also provides standard-library helpers.
from html import escape, unescape
value = '<p title="example">café & tea</p>'
escaped = escape(value, quote=True)
decoded = unescape("é 😀")
print(escaped)
print(decoded)html.escape() escapes HTML-sensitive characters; it does not need to convert all Unicode into numeric references. html.unescape() follows HTML character-reference behavior. Decoded output remains text and must still be escaped when inserted into HTML.
HTML entity encoding in PHP
$escaped = htmlspecialchars(
$value,
ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5,
"UTF-8"
);
$decoded = html_entity_decode(
$value,
ENT_QUOTES | ENT_HTML5,
"UTF-8"
);ENT_QUOTES handles both quote types, ENT_SUBSTITUTE replaces invalid sequences rather than failing silently, and ENT_HTML5 selects HTML5 entity behavior. Decoded text must be escaped again before HTML output. Do not store pre-escaped HTML unless the data model explicitly requires markup. htmlspecialchars() and htmlentities() serve different purposes; normal Unicode text usually does not need broad entity conversion.
HTML entities in Jinja2
UnicodeNow uses Jinja2 templates, so autoescaping should remain enabled for HTML templates. Dynamic user text should render through ordinary escaped interpolation. Do not apply |safe to untrusted content. Article HTML generated from trusted Markdown must pass through the project's sanitization policy, values should not be pre-escaped in the database, and trust boundaries should be clear to avoid double escaping.
<p>{{ user_text }}</p><p>{{ user_text | safe }}</p>The second form is appropriate only when content is trusted and sanitized.
Common HTML entity mistakes
Converting every non-ASCII character into an entity
Literal UTF-8 is usually clearer.
Treating HTML entities as UTF-8 bytes
They are parser syntax for code points.
Writing UTF-8 bytes as numeric references
é is not é.
Using JavaScript escapes in HTML
\u00E9 is not interpreted in normal HTML text.
Using HTML entities in CSS
External CSS does not parse HTML references.
Forgetting context-specific escaping
Text and attribute contexts differ.
Decoding entities before rendering without re-escaping
This can create injection risks.
Storing pre-escaped text
This encourages double encoding.
Using innerHTML to decode untrusted entities
This can parse active markup.
Double encoding ampersands
& becomes &amp;.
Omitting semicolons
This can cause ambiguous parsing.
Treating as an ordinary space
It has different line-breaking behavior.
Confusing URL encoding with HTML escaping
Both may be required independently.
Practical debugging workflow
- Preserve the original source.
- Determine whether you are viewing source, DOM text or serialized HTML.
- Identify the parser context.
- Inspect literal characters and references.
- Decode one layer at a time.
- Check for double encoding.
- Inspect code points.
- Check UTF-8 bytes separately.
- Verify HTML escaping context.
- Check URL or JavaScript encoding separately.
- Check normalization.
- Add round-trip tests.
Use Unicode Escape Converter, Text to Unicode Code Points, Unicode Code Points to Text and Unicode Character Inspector.
Try these UnicodeNow tools
These tools encode and decode references, inspect Unicode values and compare parsed text against source representations.
HTML Entity Encoder and Decoder
Encode and decode HTML named, decimal and hexadecimal entities.
Unicode Character Inspector
Inspect each Unicode character, encoding, category, script and normalization form.
Unicode Escape Converter
Convert text to and from Unicode escape sequences and numeric entities.
Text to Unicode Code Points
Convert text into U+XXXX Unicode code point notation.
Unicode Code Points to Text
Convert U+XXXX, 0x, and escape-style code points back to text.
UTF-8 Encoder and Decoder
Convert text to UTF-8 bytes and validate byte sequences.
Unicode Sequence Analyzer
Analyze code points, grapheme clusters, bytes, scripts and directionality.
URL Encoder and Decoder
Encode and decode URL components, full URLs and form-style strings.
Unicode Text Compare
Compare strings exactly and after Unicode normalization.
Frequently asked questions
What is the difference between an HTML entity and a Unicode character?
A Unicode character is the actual text value. An HTML entity or character reference is HTML source syntax that resolves to a character.
Is é the same as é?
After HTML parsing, both normally produce U+00E9.
Is é the same as é?
Yes. One uses decimal and the other hexadecimal notation for the same code point.
Are HTML entities UTF-8?
No. They are HTML syntax. UTF-8 is a byte encoding.
Do accented characters need HTML entities?
Usually no. Literal UTF-8 is appropriate in modern HTML.
Does emoji need to be written as an HTML entity?
No. Literal emoji is valid in UTF-8 HTML.
Which characters must be escaped in HTML?
At minimum, ampersands and less-than signs require attention in text, while quotes require escaping in matching attribute contexts.
Is the same as a normal space?
No. It produces U+00A0 NO-BREAK SPACE.
Can HTML entities work in JavaScript strings?
They remain literal text unless processed by an HTML parser. JavaScript uses its own escapes.
Can HTML entities work in CSS?
Not in normal external CSS syntax. CSS uses CSS escapes.
What is double-encoded HTML?
Already-escaped text has been escaped again, such as & becoming &amp;.
Should HTML entities be stored in a database?
Usually store Unicode text and escape it when rendering.
Is decoding HTML entities safe?
Decoding produces text that must still be escaped for its destination context.
Can numeric references represent any Unicode character?
They can represent valid code points under HTML parsing rules, but invalid values are handled through parser error recovery.
Does entity decoding normalize Unicode?
No.
References
- WHATWG HTML Standard: named character references
- WHATWG HTML Standard: tokenization and character references
- The Unicode Standard
- Unicode glossary
- Unicode Character Database
- WHATWG Encoding Standard
- MDN: Character reference
- MDN: Node.textContent
- Python documentation: html module
- PHP manual: htmlspecialchars
- PHP manual: html_entity_decode
- Jinja documentation: autoescaping
- WHATWG URL Standard