Unicode Blocks Reference

Unicode planes and blocks with their code point ranges, UTF-8 byte cost and the scripts they cover — plus the surrogate, normalisation and security behaviours that catch developers out.

Updated: 2 August 2026Read: 9 minRuns: 100% in your browser

Planes and code points

Unicode defines a code space from U+0000 to U+10FFFF — 1,114,112 possible code points, divided into 17 planes of 65,536 each. As of Unicode 15.1 about 149,800 are assigned, so roughly 87% of the space remains free.

PlaneRangeNameContains
0U+0000–U+FFFFBasic Multilingual Plane (BMP)Almost every character in modern use
1U+10000–U+1FFFFSupplementary MultilingualEmoji, historic scripts, musical notation
2U+20000–U+2FFFFSupplementary IdeographicRare CJK characters
3U+30000–U+3FFFFTertiary IdeographicOracle bone script and more CJK
14U+E0000–U+EFFFFSupplementary Special-purposeTag characters, variation selectors
15–16U+F0000–U+10FFFFPrivate UseReserved for private agreement

The BMP/astral distinction matters in code. UTF-16 — used internally by JavaScript, Java and Windows — represents BMP characters in one 16-bit unit and everything above in a surrogate pair. That is why '😀'.length is 2 in JavaScript and why naive string slicing can cut an emoji in half.

Common blocks

A block is a contiguous range reserved for a related set of characters. There are over 300; these are the ones you are most likely to meet.

FromToBlockCode pointsUTF-8 bytesUsed for
U+0000U+007FBasic Latin (ASCII)1281English, digits, punctuation
U+0080U+00FFLatin-1 Supplement1282Western European accents
U+0100U+017FLatin Extended-A1282Central and Eastern European
U+0180U+024FLatin Extended-B2082African and phonetic Latin
U+0250U+02AFIPA Extensions962Phonetic alphabet
U+0370U+03FFGreek and Coptic1442Greek alphabet
U+0400U+04FFCyrillic2562Russian, Ukrainian, Bulgarian, Serbian
U+0530U+058FArmenian962Armenian
U+0590U+05FFHebrew1122Hebrew, right-to-left
U+0600U+06FFArabic2562Arabic, right-to-left, contextual shaping
U+0900U+097FDevanagari1283Hindi, Sanskrit, Marathi
U+0E00U+0E7FThai1283Thai, no word spaces
U+1000U+109FMyanmar1603Burmese
U+10A0U+10FFGeorgian963Georgian
U+1E00U+1EFFLatin Extended Additional2563Vietnamese and more
U+2000U+206FGeneral Punctuation1123Dashes, quotes, spaces
U+20A0U+20CFCurrency Symbols483Euro, rupee, ruble, bitcoin
U+2190U+21FFArrows1123Directional arrows
U+2200U+22FFMathematical Operators2563Sum, integral, set theory
U+2500U+257FBox Drawing1283Terminal UI borders
U+2600U+26FFMiscellaneous Symbols2563Weather, zodiac, early emoji
U+2700U+27BFDingbats1923Check marks, scissors, stars
U+3000U+303FCJK Symbols and Punctuation643East Asian punctuation
U+3040U+309FHiragana963Japanese syllabary
U+30A0U+30FFKatakana963Japanese syllabary for loanwords
U+4E00U+9FFFCJK Unified Ideographs20,9923Chinese, Japanese kanji, Korean hanja
U+AC00U+D7AFHangul Syllables11,1843Korean
U+D800U+DFFFSurrogates2,048n/aUTF-16 mechanism, never valid alone
U+E000U+F8FFPrivate Use Area6,4003Icon fonts, vendor glyphs
U+FB00U+FB4FAlphabetic Presentation Forms803Ligatures such as fi
U+FE00U+FE0FVariation Selectors163Emoji vs text presentation
U+FFF0U+FFFFSpecials163Replacement character U+FFFD
U+1D400U+1D7FFMathematical Alphanumerics1,0244Styled maths letters
U+1F300U+1F5FFMisc Symbols and Pictographs7684Most emoji
U+1F600U+1F64FEmoticons804Face emoji
U+1F680U+1F6FFTransport and Map1284Vehicles, signs
U+1F900U+1F9FFSupplemental Symbols2564Newer emoji
U+20000U+2A6DFCJK Extension B42,7204Rare Chinese characters

How UTF-8 encodes each range

UTF-8 is a variable-width encoding. The number of bytes follows directly from the code point value:

Code pointsBytesBit pattern
U+0000–U+007F10xxxxxxx
U+0080–U+07FF2110xxxxx 10xxxxxx
U+0800–U+FFFF31110xxxx 10xxxxxx 10xxxxxx
U+10000–U+10FFFF411110xxx 10xxxxxx 10xxxxxx 10xxxxxx

The design is self-synchronising: a leading byte always starts with a distinctive prefix and continuation bytes always start with 10. Land anywhere in a UTF-8 stream and you can find the next character boundary by scanning forward for a byte that does not start with 10. That property is why UTF-8 survives truncation and packet loss so much better than UTF-16.

Practical consequence: English text costs 1 byte per character, European accented text 2, CJK 3, emoji 4. A CJK page is roughly three times the bytes of the same content in English.

Surrogates, combining marks and normalisation

Surrogates (U+D800–U+DFFF) are not characters. They exist solely as the UTF-16 mechanism for encoding astral code points and are permanently unassigned in Unicode. A lone surrogate in a string is invalid and will not encode to UTF-8.

Combining marks mean one visible glyph can be several code points. é can be U+00E9 (a single precomposed character) or U+0065 U+0301 (e followed by a combining acute accent). They look identical and compare unequal.

Normalisation resolves this. Four forms exist; two matter:

  • NFC composes where possible. This is what you want for storage, comparison and URLs, and what the W3C recommends for the web.
  • NFD decomposes. Useful for stripping accents: decompose, then remove the combining marks.
'caf\u00e9' === 'cafe\u0301'                      // false
'caf\u00e9'.normalize('NFC') === 'cafe\u0301'.normalize('NFC')  // true

// strip accents
s.normalize('NFD').replace(/\p{Diacritic}/gu, '')

Always normalise to NFC before comparing user input, storing usernames or generating slugs. The slug generator does this as part of its transliteration step.

Confusables and homograph attacks

Unicode contains many characters that look identical to Latin letters. Cyrillic а (U+0430) is visually indistinguishable from Latin a (U+0061) in most fonts. Register аpple.com and it displays as apple.com.

Defences that actually work:

  • Browsers show Punycode (xn--pple-43d.com) when a domain mixes scripts, which is the main mitigation.
  • Restrict usernames and identifiers to a single script, or to a defined allowed set.
  • Apply the Unicode confusable-skeleton algorithm from UTS #39 when uniqueness matters.
  • Reject zero-width characters (U+200B–U+200D) and bidirectional overrides (U+202A–U+202E) in identifiers. The 2021 “Trojan Source” research showed bidi overrides can make source code read differently to a human than to a compiler.

Frequently Asked Questions

How many characters does Unicode have?

Unicode 15.1 defines about 149,800 assigned code points out of a possible 1,114,112. Roughly 87% of the code space is still unassigned.

What is the Basic Multilingual Plane?

Plane 0, U+0000 to U+FFFF, containing almost every character in modern everyday use. Characters above it are called astral or supplementary.

Why is emoji length 2 in JavaScript?

JavaScript strings are UTF-16. Emoji live above U+FFFF and need a surrogate pair — two 16-bit units. Use [...str] or Intl.Segmenter to count actual characters.

How many bytes does a character take in UTF-8?

One for ASCII, two for most European scripts, three for CJK and most other scripts, and four for emoji and astral characters.

What is Unicode normalisation?

Converting text to a canonical form so that visually identical strings compare equal. NFC composes characters and is the right default for storage and comparison.

What are surrogates?

Code points U+D800 to U+DFFF, reserved as the UTF-16 mechanism for encoding astral characters. They are never valid characters on their own.

What is a homograph attack?

Using visually identical characters from different scripts to impersonate a name or domain, such as Cyrillic а in place of Latin a. Browsers mitigate it by displaying Punycode for mixed-script domains.

Sources & further reading

  1. The Unicode Standard — the authoritative specification and code charts
  2. UAX #15: Normalization Forms — the definition of NFC, NFD, NFKC and NFKD
  3. UTS #39: Security Mechanisms — confusable detection and identifier restrictions
  4. Trojan Source — bidirectional override attacks on source code