Spec & internals
UTF-8 and Unicode in QR codes — emoji, CJK and the legacy trap
QR codes carry Unicode by encoding text as UTF-8 in byte mode — emoji, CJK and accented characters all work on modern phone scanners without an ECI header. The costs: each character takes 1–4 bytes (an emoji is typically 4), and some legacy readers wrongly assume Shift-JIS and show garbled text.
How Unicode gets into a QR code
There is no "Unicode mode". Byte mode stores whatever octets you give it, so the universal recipe is: encode the string as UTF-8, store the bytes, and rely on the decoder to interpret them as UTF-8 — which every current iOS and Android camera does by default. No ECI header needed in practice.
That means a QR code can carry Grüße aus Köln, 東京タワー, مرحبا, or I ♥ QR 🎉
— any Unicode text — subject only to capacity.
What Unicode costs
UTF-8 is variable-width, and QR capacity is counted in bytes, not characters:
| Characters | UTF-8 bytes each | Bits in the symbol |
|---|---|---|
| ASCII (URLs, A–Z, digits) | 1 | 8 |
| Latin accents (é, ü, ñ) | 2 | 16 |
| CJK, most scripts | 3 | 24 |
| Emoji (🎉 = U+1F389) | 4 | 32 |
A 100-character Japanese message is ~300 bytes — the size of a 300-character English one. An emoji costs four times an ASCII letter, and composed emoji (skin tones, families) chain multiple code points: 👨👩👧 is 18 bytes. Capacity ceilings are byte ceilings — 2,953 bytes at version 40-L is only ~980 CJK characters or ~730 emoji. For dense text, Kanji mode can beat UTF-8 for pure Japanese, at a compatibility price.
The legacy Shift-JIS trap
QR codes were designed at Denso Wave in 1994 for Japanese industry, and the original byte-mode assumption was JIS/Shift-JIS text. Consequences that survive today:
- Old Japanese-market readers (and some embedded decoders derived from them)
interpret unlabelled bytes as Shift-JIS. Your UTF-8
caférenders as mojibake. - Some decoders sniff and guess wrong on short, ambiguous payloads — a few bytes of accented Latin-1 can also be valid Shift-JIS, and the guess goes to the wrong one.
- The reverse trap exists too: text encoded as Shift-JIS by a Japanese generator shows garbled on a UTF-8-assuming Western app.
For URLs none of this matters — ASCII is identical in every candidate encoding, which is one more reason payloads that must work everywhere should be a plain ASCII URL with the interesting content behind it.
A real implementation bug worth knowing
Unicode handling is where QR libraries quietly go wrong. A concrete example from UseQR's
own stack: the underlying qrcode-generator library's default string handling keeps only
the low byte of each JavaScript character code — multi-byte characters are silently
mangled. UseQR pre-expands every string into its UTF-8 octets before encoding, so 東京
or an emoji arrives intact. If you use a QR library directly, test a non-ASCII payload
and decode the output before trusting it — this class of bug produces codes
that look perfect and scan to garbage.
The same caution applies to WiFi passwords and vCards, where special characters meet format-specific escaping rules on top of the encoding question.
FAQ
Can a QR code contain emoji?
Yes. Emoji are encoded as UTF-8 in byte mode — typically 4 bytes each, more for composed sequences — and modern phone scanners display them correctly. They work in text payloads; inside URLs they must additionally be percent-encoded.
Does a QR code support Chinese, Japanese and Korean text?
Yes, as UTF-8 at 3 bytes per character, readable by all current phone cameras. For pure Japanese text, kanji mode stores Shift-JIS characters in 13 bits instead of 24, but with narrower generator and reader support.
Why does my QR code show garbled characters?
Almost always an encoding mismatch: the bytes are UTF-8 but the reader assumed Shift-JIS or Latin-1, or the generator mangled multi-byte characters before encoding. Regenerate as clean UTF-8 and test on the scanners your audience actually uses.
Do special characters make a QR code bigger?
Yes. Any non-ASCII character forces byte mode and costs 2–4 bytes in UTF-8, so accented or CJK text reaches a given QR version sooner than plain ASCII. Capacity limits are counted in bytes, not characters.
Try it — free, no signup
Related
- ECI — how QR codes declare a character encoding — The Extended Channel Interpretation header tells decoders how to interpret byte mode — UTF-8 is ECI 26. Most decoders assume UTF-8 anyway; old ones choke.
- QR code data encoding modes — numeric, alphanumeric, byte, kanji — Numeric packs 3.33 bits per character, alphanumeric 5.5, byte 8, kanji 13. Mode choice is why HTTPS://USEQR.APP makes a smaller code than the lowercase URL.
- Kanji mode explained — 13 bits per character — Kanji mode packs double-byte Shift-JIS characters into 13 bits — 46% denser than UTF-8 byte mode — but few generators emit it and UTF-8 rules in practice.
- How much data fits in a QR code — Theoretical ceilings are 7,089 digits, 4,296 alphanumeric characters or 2,953 bytes — but the practical answer is to keep URLs under about 50 characters.