Security FIELD NOTES · 5 MIN READ
Beyond Base64: ASCII85 and Base32 Explained
How Base32 and Ascii85 work: different alphabets and block sizes for the same job, 60% vs 25% overhead, and when each encoding beats Base64.
Base64 gets all the fame, but it shares its job with two quieter siblings: Base32, the slow-and-steady encoding built for human eyes and error-prone channels, and Ascii85, the space-saver used inside PDFs and git patches. All three solve the same problem — carrying raw bytes through a channel that only accepts text — and all three are fully reversible. They differ in alphabet, in block size, and in how much bigger they make your data.
One job, three alphabets
Every base-N encoding does the same trick: treat your bytes as one long stream of bits, chop the stream into fixed-size groups, and print each group's value as one character from an alphabet of exactly N safe symbols. The alphabet is chosen to survive whatever the channel does to text. Base64 uses A-Z, a-z, 0-9, + and / — 64 characters that every text protocol passes through untouched (see How Base64 Encoding Works for the full walkthrough). Base32 and Ascii85 simply pick different alphabets and different group sizes, and those two choices drive everything else.
Base32: five bits at a time
Base32 slices the bitstream into groups of 5 bits, each indexing one of 32 characters: A-Z followed by the digits 2-7. Encoding C (byte 01000011) means padding the bits out to a multiple of five, then splitting:
C = 01000011 → pad to 10 bits: 0100001100
split into fives: 01000 | 01100
8 | 12
I | M → "IM======"
Eight bits of input per five-bit output character means every byte costs 8/5 = 1.6 characters: a 60% overhead, versus Base64's 33%. Output is padded with = up to a multiple of 8 characters, which is why short inputs bristle with equals signs. What justifies the cost? The alphabet is deliberately boring: single case only, so uppercase/lowercase mangling cannot corrupt anything, and the digits most easily confused with letters — 0, 1, 8 — are simply absent. That makes Base32 the encoding of choice wherever humans copy strings by hand between devices: the setup codes a two-factor app imports, recovery keys, and offline handoffs all lean on it. Decoders typically ignore case and strip whitespace, so a string that survives a phone keyboard and a sticky label still decodes to the exact original bytes.
Ascii85: packing bytes tighter
Ascii85 flips the trade-off: instead of slicing thinner, it packs 4 bytes (32 bits) into 5 characters drawn from 85 consecutive printable ASCII characters, from ! (code 33) to u (code 117). The group is read as one big binary number and written out in base 85, most significant digit first. Encoding Cat — bytes 67, 97, 116, plus a zero-filled fourth byte — gives:
value = 67×16777216 + 97×65536 + 116×256 + 0 = 1130460160
write it in base 85, one digit at a time (digit d → character 33+d):
1130460160 = 21×85⁴ + 55×85³ + 65×85² + 6×85 + 25
characters: 6 X b ' :
emit 4 of 5 (3 real bytes + 1 pad byte) → "6Xb'"
The result 6Xb' is 4 characters for 3 bytes — the same size as Base64 — but the advantage grows with full groups: Ascii85 costs 5 characters per 4 bytes, a 25% overhead, the tightest of the three. Two conveniences round it out: four zero bytes in a row can be written as the single character z, and in the Adobe variant used by PDF and PostScript the whole blob is wrapped in <~ and ~> delimiters. Partial final groups follow a different rule than Base64's: instead of adding = padding, the encoder simply emits one more character than there were leftover bytes and the decoder reconstructs the rest — so Ascii85 output often has no padding at all. If you have ever wondered what the compact letter-soup blocks inside a PDF stream or a git binary patch are, this is them.
Side by side on the same input
The cleanest way to feel the difference is to encode the same text with all three:
input Base64 Base32 Ascii85
"Cat" → Q2F0 (4) INQXI=== (8) 6Xb' (4)
"hello" → aGVsbG8= (8) NBSWY3DP (8) BOu!rDZ (7)
"toolhub"→ dG9vbGh1Yg== ORXW63DIOVRA==== FDl)6BQ[b
(12) (16) (9)
overhead: ~33% 60% 25%
alphabet: A-Za-z0-9+/ A-Z 2-7 ! through u
bit groups: 6 5 32 bits → 5 chars
Same seven bytes of input, three different sizes: 12, 16 and 9 characters. The ordering never changes — Ascii85 is always the most compact, Base32 the least — and the padding styles differ visibly: Base64 tops up to a multiple of 4, Base32 to a multiple of 8, Ascii85 truncates instead of padding.
Choosing the right encoding
The choice is less about math than about the channel. Inside URLs and JSON, Base64 (in its URL-safe -_ variant) is the default because every web stack speaks it. When a human has to transcribe the string — a setup code typed into an authenticator app, a recovery key read aloud over the phone — Base32's case-free, lookalike-free alphabet earns its 60% overhead. When bytes travel inside file formats where every character counts, Ascii85's 25% overhead wins, which is why PDF and PostScript adopted it and git uses it for binary diffs. One rule holds for all three: they are encodings, not encryption. Every alphabet is public, every step is reversible, and encoding data merely makes it transportable, not secret — the same caveat Base64 carries (see How Base64 Encoding Works).
Try it yourself
Type Cat into the Ascii85 Encoder and check you get 6Xb', then feed the same word to the Base32 Encoder for INQXI=== and the Base64 Encoder for Q2F0 — three encodings, one input, three sizes you can now explain. Toggle each tool's options: Base32 lets you drop the padding, Ascii85 lets you wrap the output in <~ ~> delimiters. And to see the bits these encoders slice up, the Hex Encoder shows the raw bytes one hex pair at a time.