Base64 vs hex
Hex costs exactly 2 characters per byte; Base64 costs about 1.33. That single ratio explains where each one survives — and size is not always the constraint that decides.
By the Withuse team · Updated
The measurement
bytes hex base64 16B 32 chars 2.000× 24 chars 1.500× 32B 64 chars 2.000× 44 chars 1.375× 100B 200 chars 2.000× 136 chars 1.360× 1000B 2000 chars 2.000× 1336 chars 1.336×
Hex never deviates from 2.000, because its 16-character alphabet carries exactly 4 bits per character and a byte is exactly two of them. Base64 approaches 1.333 from above: its 64-character alphabet carries 6 bits, so three bytes map to four characters, and short inputs pay a little extra for padding. The advantage settles at roughly a third saved.
Why hex has not been displaced
The things encoded as hex are mostly short. A SHA-256 digest is 32 bytes; the difference between 64 and 44 characters is not worth a conversion step. What hex offers in exchange is a fixed mapping: byte n is always at character positions 2n and 2n+1. You can slice a hex string at known offsets, compare halves, or read a prefix, and none of that works cleanly in Base64 where byte boundaries fall inside characters.
Hex is also case-insensitive and uses only characters that are safe everywhere — no plus, slash or equals to escape, no URL-safe variant to get wrong. When a value passes through shells, filenames, URLs and log formats, that matters more than a third of a short string.
Choosing
| Use case | Encoding | Why |
|---|---|---|
| Checksums, hashes, commits | hex | ecosystem convention; short enough that size is moot |
| Binary inside JSON | base64 | paid per request; nobody reads it by eye |
| Values in URLs | base64url | compact and URL-safe without escaping |
| Data URIs | base64 | the format specifies it |
| Anything a human transcribes | base32 | case-insensitive, fewer confusable characters |
The one real exception to "hex for digests" is when the digest travels somewhere size is charged on every request. HTTP Subresource Integrity uses Base64 for exactly that reason: the hash sits in an attribute on every page load.
Neither is compression, and neither is encryption
Both encodings make data larger than the raw bytes — Base64 just less so. Reaching for Base64 to save space against raw binary is backwards; it exists to let binary survive text-only channels intact. And, as with any encoding, there is no key involved: anyone holding the output recovers the input in one step. The full argument is in the tool page.
Beyond the two
Base32 costs 1.6 characters per byte — worse than Base64 — but its alphabet is case-insensitive and avoids confusable characters, which is why TOTP secrets use it: someone may have to type it. Base58 goes further and removes zero, capital O, capital I and lowercase l entirely, which is how cryptocurrency addresses reduce transcription errors. Both trade compactness for human safety. Base64 stays the default when only machines will read the value.
Frequently asked questions
Is Base64 smaller than hex?
Yes, by about a third. Hex uses a 16-character alphabet, so each character carries 4 bits and every byte costs exactly 2 characters — a ratio that never varies. Base64 uses 64 characters, carrying 6 bits each, so 3 bytes become 4 characters, a ratio of roughly 1.333. We measured both across several sizes: 1,000 bytes produced 2,000 hex characters against 1,336 in Base64. Short inputs sit slightly above the asymptotic ratio because of padding — 16 bytes gave 1.5 rather than 1.333 — but the advantage holds everywhere and grows toward a stable third as the payload gets larger, because the padding overhead is fixed while the data is not.
Why is hex still used if Base64 is more compact?
Because size is rarely the binding constraint for the things hex encodes. A SHA-256 digest, a git commit, a MAC address or a colour value is short enough that saving a third of very little saves nothing meaningful. What hex gives instead is a fixed, predictable mapping: two characters per byte, so you can index into the string, split it at known offsets and read it aloud without ambiguity. Its alphabet is also case-insensitive and free of characters that need escaping anywhere, which Base64's plus, slash and equals are not. Byte n always sits at character positions 2n and 2n+1, a fixed mapping Base64 cannot offer because its byte boundaries fall inside characters.
Which should I use for a checksum or hash?
Hex, in almost every case, because that is what the ecosystem expects. Tools such as sha256sum, git and every database function emit hex, so a Base64 digest immediately requires conversion at the boundary and invites mismatches when one side forgets. Hex also compares cleanly in logs and diffs, since it is fixed-width and case-insensitive. The exception is when the digest travels somewhere the size genuinely matters — a URL, a header, or a field repeated across millions of records — and both sides agree on the encoding, which is why HTTP Subresource Integrity uses Base64 rather than hex — that digest sits in an attribute downloaded on every page load.
Which should I use for binary data in JSON?
Base64, and specifically base64url if the value may end up in a URL. JSON has no binary type, so the choice is between two text encodings, and here the size difference is paid on every request — a third smaller matters when a payload carries an image, a certificate or an encrypted blob. Hex would work but wastes bandwidth for no benefit, since nobody reads a 50-kilobyte value by eye. Remember that neither is compression and neither is encryption: Base64 makes the payload larger than the raw bytes, just less so than hex. If size genuinely matters, compress before encoding rather than expecting the encoding to help, since gzip on already-encoded text recovers far less than it would on the raw bytes.
Are there other encodings worth knowing?
Base32 and Base58 both exist for specific reasons. Base32 uses a 32-character alphabet, so it is bulkier than Base64 at 1.6 characters per byte, but it is case-insensitive and avoids easily confused characters, which is why it appears in TOTP secrets and in systems where a human might transcribe the value. Base58 drops the visually ambiguous characters — zero, capital O, capital I, lowercase l — and is used in cryptocurrency addresses for the same reason. Both trade compactness for transcription safety. Base64 remains the default when a machine, not a person, will read the value, which covers almost everything that travels over a network rather than across a room.
References
Convert a value with the Base64 encoder and decoder. More tools at withuse.io/tools.