UTF-8 and character sets

Why 'one character = one byte' is wrong, what code points are, and how UTF-8 became the default for the web.

Characters are not bytes

A code point is a number assigned to a character by the Unicode standard (for example, A is U+0041, Γ© is U+00E9, πŸ˜€ is U+1F600). An encoding decides how that number is stored as bytes. The same character can be stored differently by UTF-8, UTF-16, or UTF-32.

⚠️
Mixing encodings is the classic cause of mojibake (garbled text like é). Always declare and agree on one encoding end to end.

How UTF-8 works

UTF-8 is a variable-width encoding: ASCII characters (0–127) take exactly one byte and are identical to ASCII, which is why legacy English text keeps working. Other characters take 2–4 bytes.

Code point rangeUTF-8 bytes
U+0000 – U+007F1 byte (same as ASCII)
U+0080 – U+07FF2 bytes
U+0800 – U+FFFF3 bytes
U+10000 – U+10FFFF4 bytes
A      β†’ 0x41            (1 byte)
Γ©      β†’ 0xC3 0xA9      (2 bytes)
δΈ­      β†’ 0xE4 0xB8 0xAD  (3 bytes)
πŸ˜€  β†’ 0xF0 0x9F 0x98 0x80 (4 bytes)

UTF-8 is the web default

πŸ’‘
The Byte Order Mark (BOM) is meaningless for UTF-8 and often breaks parsers (JSON, shell scripts). Save UTF-8 without BOM.

FAQ

Is UTF-8 the same as Unicode?
No. Unicode is the character table (code points); UTF-8 is one way to encode those code points into bytes.
Why do I get Ò€’ instead of β€’?
The β€’ (U+2022) was written as UTF-8 but read as Latin-1. Re-decode as UTF-8 to fix it.

Base64 encoding URL encoding (percent-encoding)

Last refreshed 2026-09-17.