Hex to UTF-8: how bytes become characters
UTF-8 stores every character in one to four bytes. Plain English letters take one byte each, but accented letters, other scripts and emoji take more, and those bytes only make sense as a group. This hex to UTF-8 decoder reads your hex as bytes, groups them by the UTF-8 rules and shows the resulting text, including what happens when a group is broken.
Behind the scenes this page shares its decoder with Hex to String. Use that page for everyday hex-to-text jobs such as ASCII strings, protocol fields and configuration values; use this one when the bytes carry non-English text or emoji and you want to know why they decode the way they do.
Sequence lengths, with real results
The first bits of each byte announce its role: 0xxxxxxx is a complete one-byte character, 110xxxxx starts a two-byte sequence, 1110xxxx a three-byte one, 11110xxx a four-byte one, and 10xxxxxx marks a continuation byte. These inputs were decoded with this tool:
| Hex input | Text | Bytes per character |
|---|---|---|
48 69 | Hi | 1 |
c3 a9 | é (U+00E9) | 2 |
d0 9f d1 80 d0 b8 d0 b2 d0 b5 d1 82 | Привет | 2 |
d8 b3 d9 84 d8 a7 d9 85 | سلام | 2 |
e4 bd a0 e5 a5 bd | 你好 | 3 |
f0 9f 98 80 | 😀 (U+1F600) | 4 |
This is why the byte count of a string rarely equals its character count once non-ASCII text is involved, a common cause of truncated database fields and length checks that disagree.
Emoji and accents are often several code points
A single visible symbol can be built from more than one character, each with its own UTF-8 bytes:
f0 9f 91 8d f0 9f 8f bddecodes to 👍🏽: a thumbs-up (U+1F44D) followed by a skin-tone modifier (U+1F3FD).f0 9f 91 a9 e2 80 8d f0 9f 92 bbdecodes to 👩💻: woman, an invisible zero-width joinere2 80 8d(U+200D), then laptop.f0 9f 87 ae f0 9f 87 b3decodes to the flag 🇮🇳, which is two regional indicator letters.63 61 66 65 cc 81decodes to “café” with a separate combining accent (U+0301), whilec3 a9is a precomposed é. Both look identical but compare as different strings.
To list the code points in a decoded result, paste it into the Unicode Character Inspector; to reveal joiners and other invisible characters, use the Invisible Character Detector.
What invalid bytes turn into
The decoder never stops at bad data. It replaces each invalid part with the replacement character � (U+FFFD) and carries on, so the damage stays visible in place:
| Hex input | Result | Why |
|---|---|---|
f0 9f 98 | � | A four-byte emoji cut off after three bytes |
c3 a9 80 41 | é�A | A continuation byte with no lead byte |
c0 af | �� | An overlong encoding, forbidden in UTF-8 |
ed a0 80 | ��� | A UTF-16 surrogate, which UTF-8 may not encode |
e9 | � | é in Latin-1, which is a single byte, not UTF-8 |
Two input problems behave differently. Any character that is not a hex digit, separator or prefix stops decoding with the message “Input contains non-hexadecimal characters.” An odd number of digits gets a 0 added at the front, which shifts every byte after it: 4869e is read as 04 86 9e and decodes to a control character and two �. If the whole result looks scrambled, count the digits first.
Byte order marks and UTF-16 hex
UTF-8 has no byte order to choose: the bytes of each sequence always come lead byte first. A UTF-8 byte order mark, ef bb bf, may still open a file; this decoder drops it silently, so ef bb bf 48 69 gives just “Hi”.
UTF-16 is a different encoding, and its hex gives itself away. “Hi” is 00 48 00 69 in big-endian UTF-16 and 48 00 69 00 in little-endian. Decoded here, the zero bytes become invisible NUL characters between the letters, and a UTF-16 byte order mark (fe ff or ff fe) becomes �� at the start. Regular 00 bytes alternating with letters, or a leading ��, mean the data is UTF-16, which this page does not decode.
Encoding text to UTF-8 hex
The Text box works in reverse. Type é😀 and the Hex box shows c3a9f09f9880; choose a Byte format to get c3 a9 f0 9f 98 80 or \xC3\xA9\xF0\x9F\x98\x80 with Case set to uppercase. If what you have is garbled text such as “café” rather than hex, UTF-8 Decode repairs it directly. Decoding runs in your browser.