Hex to Text

Turn a hex dump back into words — spaced or unspaced, decoded as UTF-8, with bytes that are not text marked rather than guessed at.

Runs 100% in your browserNothing is uploaded to a serverFree forever

Hexadecimal

Reading a hex dump back into words

Every two hex digits are one byte, and the bytes are decoded as UTF-8. Paste with spaces, without them, with a 0x in front, or straight out of a dump with its offsets stripped — the converter chunks unseparated input into byte-sized pairs from the right, so an odd number of digits leaves only the leading nibble short instead of shifting the whole run.

This is the everyday way to find out what a blob in a log, a packet capture or a database column actually says, and it is usually faster than reaching for a script.

The first byte tells you how long the character is

UTF-8 is self-describing, which is what makes decoding possible without any extra information. The value of a byte says whether it starts a character and how many bytes that character occupies:

What a UTF-8 lead byte tells you
First byteBytes in the characterWhat lives there
00–7F1plain ASCII — the byte is the character
80–BFa continuation byte; never valid on its own
C2–DF2Latin-1 supplement, Greek, Cyrillic, Hebrew, Arabic
E0–EF3most of the rest of the Basic Multilingual Plane, CJK included
F0–F44emoji, historic scripts, everything above U+FFFF
C0, C1, F5–FFnever valid anywhere in UTF-8

That structure is why UTF-8 can be resynchronised: land in the middle of a stream, skip forward until you see a byte outside 80–BF, and you are at a character boundary again. It is also why a truncated run fails loudly rather than silently producing the wrong character.

Hex in, characters out
HexBytesDecodes to
481H
691i
211!
0A1
C3A92é
E282AC3
F09F90874🐇

When it does not decode

A in the output is the standard replacement character, emitted once for every byte that cannot begin or continue a valid sequence. A few of them usually means the run was cut mid-character or a byte was mistyped. A page of them means the data is not UTF-8 text — it may be an image, a compressed archive, an encrypted payload, or text in a legacy encoding such as Latin-1 or Shift-JIS, none of which this page can decode.

Bytes above 127 that decode to unexpected accented characters are the classic sign of the opposite mistake: Latin-1 data being read as UTF-8, or the reverse.

Some hex is not text on purpose

Hash digests, keys, UUIDs and binary file headers are hex because they are numbers or raw bytes, not because they encode a string. Trying to decode a SHA-256 digest as text will always produce nonsense; if the hex is a hash, compare it as a hash with the hash generator instead. If it is a number, hex to decimal is the page you want.

Related: text to hex for the return trip, binary to text for the same job from bits, and the number base converter.

More developer tools