base64.b32encode / b32decode
Base32 survives case changes and avoids look-alike characters, which is why TOTP secrets and other human-typed codes use it. Python is strict by default: lowercase and missing padding are errors until you opt in.
Demo
import base64 data = 'hello'.encode() (base64.b32encode(data), base64.b32hexencode(data))
Base32 writes 5 bytes as 8 characters, so 2 bytes ("hi") need 4 characters plus 4 = signs. The decoder checks the length first: anything that is not a multiple of 8 — including unpadded input and input containing spaces — is "Incorrect padding" before a single character is looked at. Lowercase letters are "Non-base32 digit found" unless casefold=True, and so are 0, 1, 8 and 9, which the alphabet leaves out on purpose.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| s | bytes-like (encode) · bytes-like | ASCII str (decode) | yes | Data to encode, or Base32 text to decode. The decoded length must be a multiple of 8, = included. |
| casefold | bool | no (False) | Decode only: accept lowercase letters (the input is uppercased first). |
| map01 | bytes | str | no (None) | b32decode only: allow the digits 0 and 1 by mapping 0 to O and 1 to this letter ('L' or 'I'). Must be exactly 1 character. |
Return value
bytes — Encode: uppercase Base32 as ASCII bytes, padded with = to a multiple of 8. Decode: the original bytes.
Common patterns
import base64 def totp_key(secret): s = secret.replace(' ', '').upper() return base64.b32decode(s + '=' * (-len(s) % 8))
import base64, secrets secret = base64.b32encode(secrets.token_bytes(20)).decode('ascii')
import base64 key = base64.b32hexencode(raw_id).rstrip(b'=').decode('ascii')
Examples
Pitfalls
import base64 base64.b32decode('MFRGG')
import base64 s = 'MFRGG' base64.b32decode(s + '=' * (-len(s) % 8))
import base64 base64.b32decode('mfrgg===')
import base64 base64.b32decode('mfrgg===', casefold=True)
import base64 base64.b32decode('D1IMOR3F')
import base64 base64.b32hexdecode('D1IMOR3F')
When to use
- Codes people read aloud or type: TOTP secrets, license keys, backup codes
- Case-insensitive file systems and DNS labels (Base32hex keeps sort order)
- Compact machine-to-machine data → Base64 (Base32 output is 20% longer)
- Hex is wanted → b16encode or bytes.hex()
Notes
FAQ
Pass casefold=True: base64.b32decode(s, casefold=True). Without it, lowercase letters raise "Non-base32 digit found".