W3docs

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: &euro; &#8364; &#x20AC;</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: &Sigma; &#931; &#x3A3;</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 &copy;, &amp;, &lt;), 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: &#10084; and the same in hex: &#x2764;</p>
<!-- both render as: ❤ -->

The leading zeros are optional, so &#x2764; and &#x02764; 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 rangeDecimalBytesExample character
U+0000 – U+007F0 – 1271 byteA (U+0041)
U+0080 – U+07FF128 – 20472 bytesé (U+00E9), π (U+03C0)
U+0800 – U+FFFF2048 – 655353 bytes (U+20AC), (U+4E2D)
U+10000 – U+10FFFF65536 – 11141114 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 CodesDecimalHexadecimalSample
C0 Controls and Basic Latin0-1270000-007FA B c 7 ?
C1 Controls and Latin-1 Supplement128-2550080-00FFé ñ ü © ÷
Latin Extended-A256-3830100-017Fā Œ ş ž ł
Latin Extended-B384-5910180-024Fƀ Ɛ ǎ ǔ
Spacing Modifiers688-76702B0-02FFˆ ˜ ˘
Diacritical Marks768-8790300-036Fcombining accents
Greek and Coptic880-10230370-03FFα β π Σ Ω
Cyrillic Basic1024-12790400-04FFД Ж и я ё
Cyrillic Supplement1280-13270500-052FҠ ҩ Ӂ
Latin Extended Additional7680-79351E00-1EFFḅ ẁ ẞ ṩ
General Punctuation8192-83032000-206F— … ‹ › †
Currency Symbols8352-839920A0-20CF€ £ ¥ ₽ ₹
Letterlike Symbols8448-85272100-214F™ ℃ № ℅
Arrows8592-87032190-21FF← ↑ → ↓ ↔
Mathematical Operators8704-89592200-22FF∑ √ ∞ ≠ ≤
Box Drawings9472-95992500-257F─ │ ┌ ┐ └
Block Elements9600-96312580-259F░ ▒ ▓ █
Geometric Shapes9632-972725A0-25FF■ ● ▲ ◆ ◇
Miscellaneous Symbols9728-99832600-26FF☀ ☂ ★ ☎ ✿
Dingbats9984-101752700-27BF✂ ✈ ✉ ✏ ❤
Emoji (Emoticons)128512-1285911F600-1F64F😀 😂 😍 🙏 😎

Practice

Practice
What is the main purpose of Unicode?
What is the main purpose of Unicode?
Practice
Which numeric character reference inserts the character at code point U+20AC (the euro sign)?
Which numeric character reference inserts the character at code point U+20AC (the euro sign)?
Was this page helpful?