UTF-8 is the default text encoding on the web. In a hex dump it has recognizable patterns: ASCII stays single-byte, while non-ASCII characters become multi-byte sequences with distinctive leading bits. Learning those patterns prevents false conclusions like “the file is corrupt” when it is simply UTF-8.
Decode confirmed text bytes with Hex to String (choose UTF-8). Read dumps systematically via How to read hex dumps.
ASCII vs multi-byte
"Hello" → 48 65 6c 6c 6f
"中" → e4 b8 ad
"€" → e2 82 ac
emoji 🙂 → f0 9f 99 82
- Bytes
00–7F: single ASCII/Unicode code points. - Leading
C2–DF: 2-byte sequences. - Leading
E0–EF: 3-byte sequences (common for CJK). - Leading
F0–F4: 4-byte sequences (many emoji).
Continuation bytes
Bytes that follow a multi-byte lead should look like 80–BF in hex. If you see an E4 followed by 20 (space), you are not looking at valid UTF-8—or your slice cut a character in half.
BOM
EF BB BF → UTF-8 BOM at start of file
Some Windows tools still emit a BOM. It is not required for UTF-8 and can break shebangs or naive parsers. Detect it, then decide whether to strip.
Mojibake in hex terms
Classic failure: interpret UTF-8 bytes as Latin-1/Windows-1252, then re-encode. The hex changes and no longer matches the original authoring bytes. When debugging:
- Capture the raw bytes (hex).
- Decode as UTF-8 explicitly.
- If that fails, try the legacy charset that the producer actually used—not a random guess loop without notes.
b = bytes.fromhex("e4b8ad")
print(b.decode("utf-8")) # 中
# print(b.decode("latin-1")) # three separate characters, not "中"
Cutting strings safely
Do not chop hex strings on odd indices or arbitrary byte counts if you still need valid UTF-8 text. Prefer character-aware APIs after decoding, or keep operations on Unicode strings—not on hex text.
Quick visual drill
61 62 63 → abc (ASCII)
c3 a9 → é (UTF-8)
e4 b8 ad e6 96 87 → 中文 (two 3-byte chars)
f0 9f 98 80 → 😀
ff fe ... → likely UTF-16 BOM, not UTF-8 text
Train your eye on lead bytes first; then confirm with a decoder. Online: Hex to String with UTF-8 selected.
FAQ
Why does Hex to String show weird symbols?
Wrong encoding selected, or the bytes are binary—not text. Try UTF-8 first for modern web data.
Is UTF-16 visible as hex too?
Yes, but patterns differ (often lots of 00 for English text). Do not decode UTF-16 bytes as UTF-8.
How does this relate to URL encoding?
Percent-encoding ships UTF-8 bytes as %E4%B8%AD. See percent-encoding and hex in URLs.
Language notes: PHP · Python · JavaScript. Overview: hexadecimal encoding.