How to encode text to Base32
- Type or paste text into Input · Text. With Live ticked, the output updates on every keystroke.
- Read the result in Output · Base32 (RFC 4648). Untick Padding (=) under the output to drop the trailing
=signs. - For another variant, open To and pick Base32hex, Crockford Base32 or z-base-32.
- To decode instead, click Base32 (RFC 4648) → Text in the direction toggle. The dedicated Base32 decoder starts in that direction.
- Use Copy output or Download to take the result with you.
The text is turned into bytes as UTF-8 by default. If you need the Base32 of the same text in another encoding, for example Windows-1252 or UTF-16LE, change Charset under the input.
How Base32 works
Base32 reads the input 5 bits at a time and writes one character per 5 bits. Five bytes (40 bits) become exactly eight characters, so the output is 60% larger than the input. A Base64 string of the same data would be 33% larger, which is the price Base32 pays for using only upper-case letters and six digits.
When the input length is not a multiple of 5 bytes, the last group is padded with = up to 8 characters. These are the RFC 4648 test vectors, produced by this tool:
| Input | Base32 | Without padding |
|---|---|---|
f | MY====== | MY |
fo | MZXQ==== | MZXQ |
foo | MZXW6=== | MZXW6 |
foob | MZXW6YQ= | MZXW6YQ |
fooba | MZXW6YTB | MZXW6YTB |
foobar | MZXW6YTBOI====== | MZXW6YTBOI |
Padding carries no data. A decoder can work out the byte count from the number of real characters, which is why many formats drop it.
Base32 variants: RFC 4648, base32hex, Crockford, z-base-32
“Base32” names a family. All four members pack 5 bits per character; they differ in the alphabet and in whether padding is used. The same five bytes, Hello, in each:
| Variant | Alphabet | Hello | Padding | Where you meet it |
|---|---|---|---|---|
| RFC 4648 Base32 | A–Z, 2–7 | JBSWY3DP | = | TOTP/2FA secrets, Tor v3 onion addresses, IPFS CIDv1 (b…, lower case) |
| Base32hex | 0–9, A–V | 91IMOR3F | = | DNSSEC NSEC3 records; encoded strings sort in the same order as the bytes |
| Crockford Base32 | 0–9, A–Z without I L O U | 91JPRV3F | none | IDs that people read out and type |
| z-base-32 | ybndrfg8ejkmcpqxot1uwisza345h769 | jb1sa5dx | none | Human-oriented keys and identifiers |
Base32hex and Crockford look alike, but they are different alphabets: after H they drift apart, so 91IMOR3F and 91JPRV3F are the same bytes. Picking the wrong one decodes without an error and silently gives you different bytes.
The Crockford decoder here is forgiving in the way Crockford intended: it reads I and L as 1, O as 0 and skips hyphens, so 91JP-RV3F still gives Hello. It does not add or check Crockford’s optional check symbol.
Base32 for TOTP and 2FA secrets
Authenticator apps get their secret from an otpauth:// link, usually shown as a QR code:
otpauth://totp/Example:alice@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example
The secret parameter is RFC 4648 Base32 without padding. JBSWY3DPEHPK3PXP is 16 characters, so it holds 10 bytes. RFC 4226 recommends a 160-bit (20-byte) secret, which comes out as 32 Base32 characters. If your secret is stored as Base64 or hex, convert it with Base64 to Base32. Typing the Base64 text into this page encodes its characters, which gives valid Base32 of the wrong bytes, and every code generated from it will be rejected.
A TOTP secret is a key: anyone who has it can generate your codes. This page works on the secret inside your browser tab, and its Content Security Policy blocks the page from making network requests other than Cloudflare’s page-view count.
Base32 on the command line and in Python
GNU coreutils has a base32 command that works like base64:
printf 'Hello' | base32
printf 'JBSWY3DP' | base32 -d
The first line prints JBSWY3DP, the second Hello. Python’s standard library has all three RFC 4648 forms:
import base64
base64.b32encode(b"Hello") # b'JBSWY3DP'
base64.b32hexencode(b"Hello") # b'91IMOR3F'
base64.b32encode(b"Hi").decode().rstrip("=") # 'JBUQ'
More encoding recipes are on the Python page. For decoding, including the padding and lower-case errors Python raises, see the Base32 decoder.
FAQ
Why does Base32 output end with ======?
Base32 works on 5-byte blocks that become 8 characters. When the last block is shorter, RFC 4648 fills the rest of the 8 characters with =, so Hi becomes JBUQ====. Untick Padding (=) if the receiving side wants the bare JBUQ.
Is Base32 case-sensitive?
The RFC 4648 alphabet is upper case, but most decoders accept lower case as well, and this one does. Python is an exception: base64.b32decode rejects lower case unless you pass casefold=True.
Should I use Base32 or Base64?
Use Base64 when only programs read the data: it is shorter (33% overhead against 60%). Use Base32 when people read, type or speak the value, or when it has to survive case-insensitive systems such as DNS names or some file systems.
Which characters does Base32 use?
RFC 4648 Base32 uses A–Z and 2–7, plus = for padding. The digits 0, 1, 8 and 9 are left out, so a string containing them is base32hex, Crockford or not Base32 at all.