Character encoding 2026-11-05
A character encoding specifies how characters are represented by numerical units and ultimately stored or transmitted as bytes. Unicode assigns code points; UTF-8 is one character encoding for those code points. Keeping identity and representation separate lets the same text have several byte representations.[ref]
UTF-8, a transformation format of ISO 10646 by Francois Yergeau. §3, UTF-8 definition and encoding table
For example,
U+00E9 becomes hexadecimal C3 A9 in UTF-8. A reader using an incompatible character encoding can interpret those two bytes as two unrelated characters. Correct decoding therefore requires the character encoding, and invalid sequences require an explicit error policy. The character encoding alone does not determine the font or glyph used to display the result. Francois Yergeau 2026-11-05
Francois Yergeau authored RFC 3629, the UTF-8 specification cited here. It describes a variable-length encoding of Unicode scalar values using one to four octets, retaining ordinary ASCII values as single octets. The author-address section supplies the identity spelling used in this article.[ref]
A key technical detail is that accepting arbitrary byte sequences is unsafe: the specification excludes surrogate code points and requires valid encodings rather than overlong alternatives. Thus decoding is not just collecting low bits from whichever bytes happen to arrive. Checking the permitted forms prevents distinct byte representations from bypassing a text-based security check.[ref]
UTF-8, a transformation format of ISO 10646 by Francois Yergeau. §§3–4 and §10, Security Considerations
UTF-8 2026-11-05
UTF-8 encodes each Unicode scalar value in one to four bytes. ASCII values use one byte; non-ASCII leading bytes announce the sequence length, and continuation bytes begin with the bit pattern
10. This makes byte boundaries identifiable without using a separate delimiter after every character.[ref]For example,
U+00E9 is encoded as hexadecimal C3 A9, while U+1F600 uses F0 9F 98 80. Valid decoding excludes surrogate values, values above U+10FFFF and overlong encodings of smaller values. A byte offset therefore need not be a code-point boundary, and a code-point boundary need not be a grapheme cluster boundary. Correct slicing and validation must state which unit they operate on.