Hex to text, plain and predictable
Hex to text decoding takes a stream of hexadecimal digits, strips every 0x prefix and every whitespace character, and reads the remaining digits two at a time. Each two-digit pair is parsed with parseInt(pair, 16) and passed to String.fromCharCode to produce the matching character. So 48 65 6c 6c 6f decodes to Hello, and 0x48 0x65 decodes the same as 4865 after the prefixes and spaces strip away.
Whitespace is normalised before the split, so spaces, tabs, newlines and carriage returns all behave the same. The case of the hex digits does not matter: 4865, 4865, 4865 and 48 65 all decode to He. If the digit count after stripping is odd, the final pair gets only one digit and decodes to a low code point (so a stray digit produces a stray character). If a pair contains a non-hex character, the output panel shows [invalid hex] instead of partial text.
The decoder always reads pairs of two digits, regardless of how the source separated chunks. That matches the most common encoding (one byte per character, ASCII or Latin-1). If your hex stream uses four-digit chunks for a UTF-16 code unit, split each chunk into two pairs first, or feed the whole stream in and trust that String.fromCharCode handles each byte as a separate character. For the inverse direction, see text to hex.
How to use convert hex to text
- 1Paste a hexadecimal stream into the input panel on the left.
- 2The decoded text appears in the output panel on the right as you type.
- 3Click Copy in the output header to copy the result.
- 4Click Download to save the result as a plain-text file.
- 5If the output reads
[invalid hex], check that every chunk contains only hex digits.
Keyboard shortcuts
Drive TextResult without touching the mouse.
| Shortcut | Action |
|---|---|
| Ctrl F | Open the find & replace panel inside the input Plus |
| Ctrl Z | Undo the last input change |
| Ctrl Shift Z | Redo |
| Ctrl Shift Enter | Toggle fullscreen focus on the editor Plus |
| Esc | Close find & replace, or exit fullscreen |
| Ctrl K | Open the command palette to jump to any tool Plus |
| Ctrl S | Save current workflow draft Plus |
| Ctrl P | Run a saved workflow Plus |
What this tool actually does
Whitespace and prefix stripping
Every 0x prefix is removed before the parse. Every whitespace character (space, tab, newline, carriage return) is removed too. So 0x48 0x65 and 4865 and 48 65 all decode to the same two characters.
Two-digit pair decoding
After stripping, the remaining digits are read two at a time. Each pair parses with parseInt(pair, 16) and feeds String.fromCharCode. So 48 becomes char code 72, which is H. Pairs decode independently, with no shared state across the stream.
Case-insensitive hex digits
Upper and lower case hex digits are treated identically. 4865, 4865, 4865, and 48 65 all decode to He. The strip uses 0x matching with the case-insensitive flag, so 0X48 works too.
Invalid input shows a clear marker
If a pair contains a character that is not a hex digit (a stray g, a comma, a letter), the parse fails and the output panel shows [invalid hex] instead of partial text. Fix the source and the output refreshes on the next keystroke.
Runs entirely in your browser
No upload, no server-side processing, no log of what you pasted. The decode runs on every keystroke via a single JavaScript pass. Long streams of a few hundred kilobytes still decode in under a second on a desktop browser.
Worked example
Five two-digit pairs decode to the five characters of Hello via String.fromCharCode.
48 65 6c 6c 6f
Hello
Settings reference
| Behaviour | Effect on output |
|---|---|
| Whitespace stripping | Every space, tab, newline and carriage return is removed before the parse. |
0x prefix stripping |
Case-insensitive. Removed before the parse so 0x48 and 48 behave identically. |
| Pair width | Always two digits per character. Wider chunks split into pairs. |
| Case sensitivity | Upper and lower case hex digits decode identically. |
| Empty input | Emits an empty string. |
| Invalid pair | Output shows [invalid hex]; no partial text is emitted. |
| Odd digit count | The final pair has only one digit and decodes to a low code point, which usually produces a stray character. |
FAQ
Does it accept 0x-prefixed input?
0x (or 0X) prefix before parsing, regardless of where it appears in the stream. So 0x48 0x65 decodes the same as 4865. The strip is case-insensitive.What chunk width does the decoder use?
0048 for H), the decoder still reads it as two two-digit pairs, which produces \x00H. For ASCII or Latin-1 streams, two-digit pairs are exactly right.Why does the output read [invalid hex]?
Is the hex sent anywhere?
How do I go the other way?
0x prefix, two-digit padding and inter-chunk spacing.