Developer Guide

Convert Hex to String in Python: Which Method to Use

Converting hex like 48656C6C6F to text in Python is a bytes problem first: parse hex pairs into a bytes object, then .decode() with the right encoding (usually UTF-8).

This page is the method chooser. For edge cases of one API, see bytes.fromhex() deep dive and binascii.unhexlify(). Try results in the browser with Hex to String.

Recommended default: bytes.fromhex()

def hex_to_text(hex_str: str, encoding: str = "utf-8") -> str:
    return bytes.fromhex(hex_str).decode(encoding)

print(hex_to_text("48656C6C6F20576F726C64"))  # Hello World
print(hex_to_text("48 65 6C 6C 6F"))           # spaces ignored

Use this in new Python 3 code. It is readable, fast (C implementation), and ignores ASCII whitespace between digits.

When to use binascii.unhexlify()

import binascii

def hex_to_text_strict(hex_str: str, encoding: str = "utf-8") -> str:
    clean = "".join(hex_str.split())  # unhexlify does not skip spaces
    return binascii.unhexlify(clean).decode(encoding)

Prefer this when you already depend on binascii, or when you want strict “no surprises” behavior and will sanitize input yourself. Details: unhexlify guide.

Optional: codecs.decode(..., "hex")

import codecs

text = codecs.decode("48656C6C6F", "hex").decode("utf-8")

Useful if your codebase already routes everything through codecs. Otherwise bytes.fromhex is clearer.

Manual loop (teaching / custom validation)

def hex_to_text_manual(hex_str: str, encoding: str = "utf-8") -> str:
    h = "".join(hex_str.split())
    if len(h) % 2:
        raise ValueError("hex length must be even")
    data = bytes(int(h[i:i+2], 16) for i in range(0, len(h), 2))
    return data.decode(encoding)

Good for learning and for injecting custom rules. Slower than the C helpers — not the production default.

Quick comparison

MethodWhitespaceBest for
bytes.fromhexIgnoredDefault Python 3
binascii.unhexlifyMust stripLegacy / strict pipelines
codecs.decode(..., "hex")Must stripCodecs-centric code
Manual int(..., 16)Your choiceTeaching / custom checks

Shared rules that matter more than the API name

def safe_hex_to_text(hex_str: str, encoding: str = "utf-8") -> str:
    if not hex_str or not hex_str.strip():
        return ""
    try:
        return bytes.fromhex(hex_str).decode(encoding)
    except ValueError as exc:
        raise ValueError(f"invalid hex: {exc}") from exc

Opposite direction: Python string to hex. Conceptual background: What is hexadecimal encoding?.