Last updated
What Is Base32 Encoding?
Base32 is a binary-to-text encoding scheme that represents arbitrary binary data using a 32-character alphabet.
The standard RFC 4648 alphabet consists of the 26 uppercase letters A–Z plus the digits 2–7.
Every 5 bits of input are mapped to one Base32 character, so 8 Base32 characters encode exactly 5 bytes.
Padding characters (=) are appended to make the output length a multiple of 8.
The most common use case is encoding binary data in contexts where only alphanumeric characters are safe — for example, TOTP secret keys in two-factor authentication apps like Google Authenticator. When you scan a QR code to set up 2FA, the underlying secret is a Base32 string.
Base32 vs Base64: When to Use Which
| Property | Base32 | Base64 |
|---|---|---|
| Alphabet size | 32 chars (A–Z, 2–7) | 64 chars (A–Z, a–z, 0–9, +/) |
| Case sensitive | No — uppercase only | Yes |
| Output overhead | ~60% larger than input | ~33% larger than input |
| URL safe | Yes (no special chars) | Needs variant (-_ instead of +/) |
| Human readable | Better (no 0/O confusion) | Harder to read aloud |
| Common use | TOTP secrets, DNS labels | Email attachments, JWTs, images |
Choose Base32 when the encoded string will be typed by humans (e.g., backup codes, secret keys) or used in case-insensitive contexts like DNS. Choose Base64 when storage efficiency matters more.
How the Encoding Works
The algorithm groups input bytes into 5-bit chunks and maps each chunk to a character in the alphabet.
For the string Hello (5 bytes = 40 bits = 8 Base32 chars):
H e l l o
01001000 01100101 01101100 01101100 01101111
Split into 5-bit groups:
01001 00001 10010 10110 11000 11011 00011 01111
Map to alphabet (A=0, B=1, ... 2=26, 7=31):
J B S W Y 3 D P
Result: JBSWY3DP (no padding needed — 40 bits / 5 = 8 chars exactly)
JavaScript Implementation
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
function base32Encode(str) {
const bytes = new TextEncoder().encode(str);
let bits = '';
for (const b of bytes) bits += b.toString(2).padStart(8, '0');
let out = '';
for (let i = 0; i < bits.length; i += 5)
out += ALPHABET[parseInt(bits.slice(i, i + 5).padEnd(5, '0'), 2)];
while (out.length % 8) out += '=';
return out;
}
function base32Decode(str) {
str = str.replace(/=/g, '').toUpperCase();
let bits = '';
for (const c of str) {
const idx = ALPHABET.indexOf(c);
if (idx === -1) throw new Error('Invalid Base32 char: ' + c);
bits += idx.toString(2).padStart(5, '0');
}
const bytes = [];
for (let i = 0; i + 8 <= bits.length; i += 8)
bytes.push(parseInt(bits.slice(i, i + 8), 2));
return new TextDecoder().decode(new Uint8Array(bytes));
}
console.log(base32Encode('Hello')); // → JBSWY3DP
console.log(base32Decode('JBSWY3DP')); // → Hello
Common Use Cases
- TOTP / 2FA secrets: RFC 6238 specifies Base32 for encoding HMAC keys in authenticator apps.
- DNS labels: Base32 is used in DNSSEC and some DNS-based protocols because DNS is case-insensitive.
- Onion addresses: Tor v3 .onion addresses are Base32-encoded public key hashes.
- File checksums: Some tools encode SHA hashes in Base32 for shorter, typeable strings.