Developer Guide

Hex vs Base64: When Developers Should Use Each

Hex and Base64 both turn binary into printable text. They solve different problems. Teams that treat them as synonyms create oversized payloads, unreadable logs, or APIs that nobody can debug.

This article compares the two encodings the way you actually choose them in product work: size, readability, ecosystem defaults, and failure modes. Convert hex samples with Hex to String / String to Hex while you decide.

Side-by-side

HexBase64
Alphabet0-9A-FA-Za-z0-9+/ (+ padding =)
Size vs raw bytes~2×~4/3 ≈ 1.33×
Byte alignment in textExcellent (2 chars = 1 byte)Poor (4 chars = 3 bytes)
Debugging by eyeStrongWeak
Typical homesdumps, digests, colors, opcodesJSON, email, data URLs, many HTTP APIs

What hex is optimized for

Hex keeps a direct map to bytes. When you see FF D8 FF, you can talk about those three bytes without mental gymnastics. That is why hex dominates:

SHA-256 digest (hex):
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

People compare hex digests visually. Doing the same with Base64 is possible but uncommon in release notes.

What Base64 is optimized for

Base64 packs more binary into fewer characters and stays inside a safe ASCII subset for protocols that dislike raw bytes. Use it when:

Base64 is a transport encoding. It is not smaller than the original binary file on disk—only smaller than hex text.

Decision guide

  1. Need to debug or document bytes? → hex.
  2. Need compact text inside JSON/HTTP? → Base64.
  3. Need a human-compared fingerprint? → hex (usually lowercase).
  4. Already stuck with one format in a standard? → follow the standard; do not dual-encode.

Anti-patterns

Worked example: same 5 bytes

Bytes:  48 65 6c 6c 6f   ("Hello")
Hex:    48656c6c6f
Base64: SGVsbG8=

For five bytes, Base64 wins on size. For a 64-byte hash shown on a status page, hex usually wins on familiarity.

Language footnotes

Deep dives: Python hex methods · PHP hex guide.

Migration tips if you picked wrong once

If an API already ships hex and you want Base64 (or the reverse), convert at the boundary—do not change historical rows in place without a version field.

  1. Add a encoding field (hex | base64) or bump an API version.
  2. Accept both during a transition window.
  3. Emit only the new form after clients upgrade.
  4. Keep raw binary in storage when you control the database; encode only on the wire.
import base64

def hex_to_b64(h: str) -> str:
    return base64.b64encode(bytes.fromhex(h)).decode("ascii")

def b64_to_hex(s: str) -> str:
    return base64.b64decode(s).hex()

FAQ

Can I convert hex to Base64 without knowing the original file?
Yes: hex → bytes → Base64. You are changing representation, not meaning.

Which should JWT use?
JWT uses Base64url. Do not replace it with hex unless you control a private token format.

Is hex safer than Base64?
No. Safety comes from cryptography and access control, not from the printable encoding.

Related: odd-length pitfalls · file magic numbers · hex overview.