UTF-8 Encoding
UTF stands for Unicode Transformation Format. The '8' means it uses 8-bit blocks to represent a character.
Every character you type on a web page — a plain Latin letter, an accented é, a Greek π, the euro sign €, or an emoji — has to be turned into bytes before it can be stored or sent over the network. The rules that map characters to bytes are called a character encoding. Unicode is the universal catalog that gives every character a unique number (a code point), and UTF-8 is the encoding that writes those code points as bytes. As an HTML author, getting the encoding right is what stands between you and the dreaded "mojibake" — garbled output like é where an é should be. This page explains what UTF-8 is, how to declare it, how to insert any Unicode character by its code point, and includes a reference table of common Unicode ranges.
Related chapters: HTML Entities lists the named shortcuts like
©and&, and HTML Character Sets explains how Unicode, UTF-8, and the document charset relate to one another.
What Is UTF-8?
8-bit Unicode Transformation Format, called UTF-8, is a variable-width character encoding that can encode all of the 1,114,112 valid code points in Unicode with one to four 8-bit bytes. The number "8" means 8-bit blocks are used by UTF for representing a character.
Since 2009, UTF-8 has been the leading encoding for the World Wide Web, and today it is used by the overwhelming majority of all web pages.
Declaring the Encoding in HTML
A browser cannot reliably guess which encoding your bytes use, so you should always tell it. In HTML5 you do this with a single <meta> tag, placed as the first thing inside <head> (within the first 1024 bytes of the document):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>UTF-8 example</title>
</head>
<body>
<p>Prices: €10 · Greek letter: π · Smiley: 😀</p>
</body>
</html>Save the file itself as UTF-8 in your editor and declare <meta charset="UTF-8">, and the two will agree. If the <meta charset> is missing, the browser falls back to a guess (historically windows-1252 for many Western locales, or a heuristic), which is exactly how garbled text appears. Learn more in the HTML <meta> Tag chapter.
Why the Declaration Must Come Early
A browser does not wait for the whole HTML file to arrive before it starts working — it begins decoding bytes into characters as soon as the first chunk streams in. To do that, it has to pick an encoding before it has read the entire document. The HTML specification therefore requires <meta charset> to appear within the first 1024 bytes, so the browser can find it during that initial pass.
If you declare the encoding too late (for example, after a long block of comments or content), the browser will already have decoded the earlier bytes using its fallback guess. Those bytes get misinterpreted, and by the time the late declaration is found, the page may need a full re-parse — or simply display garbled text. Keeping <meta charset="UTF-8"> as the very first child of <head> guarantees it is seen in time.
Using Unicode Code Points in HTML
You don't need to type an exotic character directly to use it. Any Unicode code point can be inserted with a numeric character reference, in decimal (&#NNNN;) or hexadecimal (&#xHHHH;). Many common characters also have a memorable named entity.
For example, the euro sign (code point U+20AC) can be written three equivalent ways:
<p>Euro: € € €</p>
<!-- all three render as: € -->The same works for letters from any script, such as the Greek capital letter sigma (U+03A3):
<p>Greek sigma: Σ Σ Σ</p>
<!-- renders as: Σ -->Numeric references are handy for characters that are hard to type, or to be explicit and avoid encoding ambiguity. For the full list of named shortcuts (like ©, &, <), see HTML Entities.
Numeric Character References
Both &#NNN; (decimal) and &#xHHHH; (hexadecimal) name a character by its Unicode code point — the same number Unicode assigns to it, just written in two different bases. The x after &# is what marks the digits as hexadecimal. Because they reference the code point directly, numeric references work for every Unicode character, even those without a named entity.
For example, the heavy black heart (code point U+2764, decimal 10084) has no widely supported named entity, but you can still write it:
<p>Heart: ❤ and the same in hex: ❤</p>
<!-- both render as: ❤ -->The leading zeros are optional, so ❤ and ❤ are equivalent. Hex is convenient because it matches the U+.... notation you see in Unicode charts.
Tip: For an overview of how encodings, code points, and the document charset fit together, see HTML Character Sets.
How Many Bytes a Character Takes
UTF-8 is variable-width: characters with small code points take fewer bytes, so plain English text stays compact while still allowing the full Unicode range. A code point's value alone determines how many bytes UTF-8 uses for it, according to four inclusive ranges:
| Code point range | Decimal | Bytes | Example character |
|---|---|---|---|
| U+0000 – U+007F | 0 – 127 | 1 byte | A (U+0041) |
| U+0080 – U+07FF | 128 – 2047 | 2 bytes | é (U+00E9), π (U+03C0) |
| U+0800 – U+FFFF | 2048 – 65535 | 3 bytes | € (U+20AC), 中 (U+4E2D) |
| U+10000 – U+10FFFF | 65536 – 1114111 | 4 bytes | 😀 (U+1F600) |
- 1 byte (U+0000–U+007F). These bytes are identical to the original ASCII values, which is why any plain-ASCII file is already valid UTF-8.
- 2 bytes (U+0080–U+07FF). Covers most Latin letters with accents, plus Greek, Cyrillic, Hebrew, and Arabic.
- 3 bytes (U+0800–U+FFFF). Includes most other modern scripts along with many symbols and CJK (Chinese, Japanese, Korean) characters. This range goes all the way up to and including U+FFFF.
- 4 bytes (U+10000–U+10FFFF). Holds less common scripts, historic characters, and emoji, up to the highest valid Unicode code point, U+10FFFF.
Why UTF-8 Won the Web
Older encodings such as ASCII, Latin-1 (ISO-8859-1), and Windows-1252 each used a single byte per character, so they could only represent up to 256 characters. That is fine for one language, but a page can't mix, say, French, Russian, and Japanese in one file. UTF-8 fixes this by covering every character in Unicode while staying backward compatible with ASCII — the first 128 code points map to the exact same single bytes. That compatibility, plus its compactness for English text, is why UTF-8 displaced the legacy single-byte encodings and became the web's default.
The Byte Order Mark (BOM)
Some editors prepend a few invisible bytes to the very start of a UTF-8 file, called a byte order mark (BOM).
Should You Use a BOM in HTML?
In UTF-8 the BOM is the three-byte sequence EF BB BF. It can act as a signal that a file is UTF-8 encoded, but for HTML it is unnecessary and best avoided: your <meta charset="UTF-8"> declaration already states the encoding, and a stray BOM can cause subtle bugs (for instance, unexpected whitespace before <!DOCTYPE>, or breaking PHP scripts that emit output). If your editor offers the choice, save as "UTF-8 without BOM."
Unicode Range Reference
The list below shows some commonly used Unicode blocks, each given by its decimal and hexadecimal code-point range. The sample column shows one glyph from the block.
| Character Codes | Decimal | Hexadecimal | Sample |
|---|---|---|---|
| C0 Controls and Basic Latin | 0-127 | 0000-007F | A B c 7 ? |
| C1 Controls and Latin-1 Supplement | 128-255 | 0080-00FF | é ñ ü © ÷ |
| Latin Extended-A | 256-383 | 0100-017F | ā Œ ş ž ł |
| Latin Extended-B | 384-591 | 0180-024F | ƀ Ɛ ǎ ǔ |
| Spacing Modifiers | 688-767 | 02B0-02FF | ˆ ˜ ˘ |
| Diacritical Marks | 768-879 | 0300-036F | combining accents |
| Greek and Coptic | 880-1023 | 0370-03FF | α β π Σ Ω |
| Cyrillic Basic | 1024-1279 | 0400-04FF | Д Ж и я ё |
| Cyrillic Supplement | 1280-1327 | 0500-052F | Ҡ ҩ Ӂ |
| Latin Extended Additional | 7680-7935 | 1E00-1EFF | ḅ ẁ ẞ ṩ |
| General Punctuation | 8192-8303 | 2000-206F | — … ‹ › † |
| Currency Symbols | 8352-8399 | 20A0-20CF | € £ ¥ ₽ ₹ |
| Letterlike Symbols | 8448-8527 | 2100-214F | ™ ℃ № ℅ |
| Arrows | 8592-8703 | 2190-21FF | ← ↑ → ↓ ↔ |
| Mathematical Operators | 8704-8959 | 2200-22FF | ∑ √ ∞ ≠ ≤ |
| Box Drawings | 9472-9599 | 2500-257F | ─ │ ┌ ┐ └ |
| Block Elements | 9600-9631 | 2580-259F | ░ ▒ ▓ █ |
| Geometric Shapes | 9632-9727 | 25A0-25FF | ■ ● ▲ ◆ ◇ |
| Miscellaneous Symbols | 9728-9983 | 2600-26FF | ☀ ☂ ★ ☎ ✿ |
| Dingbats | 9984-10175 | 2700-27BF | ✂ ✈ ✉ ✏ ❤ |
| Emoji (Emoticons) | 128512-128591 | 1F600-1F64F | 😀 😂 😍 🙏 😎 |