Why an emoji is four bytes

In UTF-8, a character takes between one and four bytes depending on how far up the Unicode range it sits. The letter H is 01001000 — one byte. The letter é is 11000011 10101001 — two. A grinning face is 11110000 10011111 10011000 10000000 — four. The leading bits of the first byte announce how many bytes the character occupies, which is what makes the encoding self-describing.

That design is why UTF-8 won. A decoder can find character boundaries anywhere in a stream without reading from the beginning, and a file of plain English is byte-for-byte identical to the ASCII it would have been.

How does the first byte announce the length?

By the number of leading ones before the first zero. Continuation bytes always start 10, so they can never be mistaken for a starting byte.

Bytes First byte starts Continuation bytes Covers
1 0 ASCII, U+0000 to U+007F
2 110 10 Latin accents, Greek, Cyrillic, to U+07FF
3 1110 10 Most of the rest, to U+FFFF
4 11110 10 Emoji and rare scripts, to U+10FFFF

Read the emoji sequence against that table. The first byte 11110000 has four leading ones, so this is a four-byte character; the next three all start 10, so they are continuations. The actual code point is assembled from the bits after those prefixes.

Why is é two bytes and not one?

Because one byte only reaches U+007F, and é is U+00E9. The moment a character sits above 127, UTF-8 needs a second byte — and it spends five bits of the first byte and two of the second on the framing, leaving eleven bits of payload.

This is where files from older systems go wrong. In Latin-1, é is a single byte with value 233; in UTF-8 it is two bytes, 195 and 169. Open a Latin-1 file as UTF-8 and you get a decoding error or a replacement character; open a UTF-8 file as Latin-1 and é appears as two characters, which is the origin of the mojibake everyone has seen in a badly imported spreadsheet.

The prefix scheme also makes the encoding self-synchronising. Drop into the middle of a UTF-8 stream at a random byte and you can tell immediately whether you are on a starting byte or a continuation, because continuations always begin 10 — so a decoder recovers within at most three bytes rather than being lost for the rest of the file. Very few encodings have that property, and it is the reason UTF-8 is safe to search, split and concatenate.

Is most binary you find online actually UTF-8?

Usually it is ASCII, which is the same thing for the first 128 characters. Seven-bit ASCII padded to eight bits decodes cleanly as UTF-8 because UTF-8 was designed for exactly that compatibility, so a puzzle written in 1990 still reads today.

Where it diverges is anything above 127. A stream that is genuinely Latin-1 or Windows-1252 will decode as UTF-8 for the English parts and break on the accents, which is why a decoder needs a sensible fallback rather than a refusal.

What about seven-bit binary?

It decodes if you know to expect it. Some sources write ASCII as seven bits per character with no padding, so 1001000 rather than 01001000 for H. A decoder reading eight bits at a time will produce nonsense from that stream, and the fix is to group by seven instead.

The giveaway is length. A message of n characters is 8n bits in padded form and 7n unpadded, so a bit count divisible by seven but not by eight is a strong hint about which you are holding.

Why do emoji sometimes count as two characters?

Because of how the code point is stored rather than how it is encoded. Programming languages that store text as sequences of 16-bit units represent anything above U+FFFF as a surrogate pair — two units for one character — so a string length function returns 2 for a single emoji.

It gets worse with composed emoji. A family emoji or a flag is several code points joined by zero-width joiners, so one visible glyph can be six or more code points and twenty-plus bytes. Any character limit counting units rather than glyphs will charge accordingly, which is why an emoji-heavy message can hit a limit long before the visible characters suggest.

Questions people ask

Can I paste binary without spaces? Yes. A continuous stream is grouped into bytes from the start, which works as long as the encoding really is eight bits per character.

Why does my decode produce a replacement character? Because the byte sequence is not valid UTF-8 — usually a Latin-1 file being read as UTF-8, or a stream that was truncated mid-character.

Is my text uploaded anywhere? No. The conversion is arithmetic on the characters and happens entirely in the browser.

Does UTF-8 waste space for non-Latin scripts? Compared with UTF-16, yes — Chinese and Japanese characters take three bytes in UTF-8 and two in UTF-16. For mixed content and for markup-heavy formats, UTF-8 still comes out ahead, which is why the web standardised on it.

The leading bits carry the length, and everything else about UTF-8 follows from that one decision. The binary translator shows the bytes for anything you paste, the morse code translator is the same idea a century earlier, and the QR code generator is where those bytes end up when they have to survive being printed.