FormatterHQ

Hex to String

Decode hexadecimal bytes into readable text. Paste hex in almost any notation — spaced, prefixed, colon-separated — and get the UTF-8 string back.

Loading tool…
Ready.

How to use the Hex to String

  1. Type or paste into the Hex box, or click Sample. You can also drop a text file on either box, or load one into the Hex box with its Open file button.
  2. The Text box updates live as you type. It works both ways — edit the Text side to convert back, or click ⇄ Swap to exchange the sides.
  3. Byte format and Case in the options bar above the editors only affect the reverse direction — the Hex output you get when you type in the Text box.
  4. Use Copy or Download on either box to take the result, or Clear to start again.

Hex to string decoder

The hex to string converter turns pairs of hexadecimal digits back into bytes and reads those bytes as UTF-8 text. It is the reverse of String to Hex and is useful for reading values from packet captures, database dumps, firmware, hex editors and debug logs.

Flexible input

The parser strips the usual decorations before decoding, so you can paste hex straight from where you found it:

  • Plain: 48656c6c6f
  • Spaced or on several lines: 48 65 6c 6c 6f
  • Prefixed: 0x48 0x65 or \x48\x65
  • Separated by commas, colons, semicolons or hyphens: 48:65:6c or 48-65-6C
  • Upper or lower case, or a mix.

If the number of digits is odd, a leading 0 is assumed. Any other character that is not a hex digit produces a clear error rather than garbage.

Example

Input:

48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 20 e2 9c 93

Output:

Hello, World! ✓

When the output looks wrong

  • Replacement characters (�). The bytes are not valid UTF-8. They might be binary data (an image, a compressed stream, a hash) or text in another encoding such as Latin-1 or UTF-16. For example c3 28 is an invalid UTF-8 sequence and decodes to �(.
  • Every other character is empty. Lots of 00 bytes between letters usually means UTF-16 text, which is not supported here.
  • Numbers instead of letters. If the hex represents a number (such as 0x1F4 = 500) rather than text, use the Hex to Decimal converter.

Hex strings copied from network tools often include offsets and an ASCII column, as in a classic hex dump. Remove those columns before pasting, or the offset digits will be decoded as extra bytes.

Reading multi-byte UTF-8 by hand

The first hex digit of each byte tells you how UTF-8 groups them. Bytes from 00 to 7F are single ASCII characters. A byte starting with C or D opens a two-byte character, E a three-byte one and F0–F4 a four-byte one, and every following byte must be between 80 and BF.

e2 9c 93
11100010 10011100 10010011   lead byte + 2 continuation bytes
    0010   011100   010011   payload bits
= 0x2713 = ✓ (CHECK MARK)

That rule explains the c3 28 case above: c3 promises one more byte, but 28 is an ordinary "(" rather than a continuation byte, so the decoder emits a replacement character and carries on.

Hex to string in code

Python: bytes.fromhex('48656c6c6f').decode('utf-8'). Node.js: Buffer.from('48656c6c6f', 'hex').toString('utf8'). Shell: echo 48656c6c6f | xxd -r -p. MySQL: SELECT CONVERT(UNHEX('48656c6c6f') USING utf8mb4). Note that most of these expect plain hex without separators or prefixes, which is exactly what this tool removes for you.

Hex is not a cipher

Hex-encoded strings sometimes appear in configuration files or URLs and look secret. They are not: hex is a direct, reversible representation of bytes. If a “hex password” decodes to readable text, treat it as plain text.

The decoding is done locally in your browser.

Hex to string in Python

bytes.fromhex() converts hex digits to bytes and .decode("utf-8") turns them into text. fromhex() skips whitespace between bytes, but anything else raises ValueError: non-hexadecimal number found: 0x prefixes, \x escapes, colons and commas all have to be stripped first, and the digit count must be even. The helper below removes those decorations with one regular expression and uses errors="replace" so that invalid UTF-8 shows as � instead of raising.

import re

hex_text = "48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21 20 e2 9c 93"
print(bytes.fromhex(hex_text).decode("utf-8"))

def hex_to_string(value):
    digits = re.sub(r"0x|\\x|[\s,:;-]", "", value)
    return bytes.fromhex(digits).decode("utf-8", errors="replace")

print(hex_to_string("0x48 0x65 0x6C 0x6C 0x6F"))
print(hex_to_string("48:65:6c:6c:6f"))
print(hex_to_string(r"\x48\x65\x6c\x6c\x6f"))

All four calls print the same text as the decoder above, which accepts the same input styles; to go the other way, use String to Hex.

Frequently asked questions

How do I convert hex to text?
Paste the hex digits into the Hex box and the text appears alongside. Each pair of digits is one byte, and the bytes are decoded as UTF-8 text.
Can I paste hex with 0x prefixes?
Yes. 0x and \x prefixes, spaces, commas, colons, semicolons and hyphens are all removed before decoding.
Why do I get � characters?
The bytes are not valid UTF-8 text. They may be binary data or text in another encoding.
What is the difference between Hex to String and Hex to UTF-8?
They decode the same way. Hex to UTF-8 focuses on multi-byte characters from other scripts, while Hex to String is the general-purpose decoder.

Last updated October 3, 2026

Related tools