base64.b32decode() and b16decode() Reject Lowercase by Default (tested)
Base32 and hex encodings only use uppercase letters, so lowercase input is never actually ambiguous -- there's only one letter it could mean. We measured that Python's base64.b32decode() and base64.b16decode() raise an error on lowercase input anyway, by default, which is easy to miss if you're used to bytes.fromhex() accepting lowercase without complaint.
1. Lowercase input raises, even though it's unambiguous
import base64
encoded = base64.b32encode(b"hello world")
print(encoded)
print(base64.b32decode(encoded.lower()))
b'NBSWY3DPEB3W64TMMQ======'
Traceback (most recent call last):
...
binascii.Error: Non-base32 digit found
Measured: lowercasing a valid Base32 string and decoding it raises binascii.Error: Non-base32 digit found. base64.b16decode() does the exact same thing on lowercased hex-like output -- binascii.Error: Non-base16 digit found. Neither function silently tolerates case the way base64.b64decode() tolerates extra characters (see our other base64 guide) -- here it's strict, not lenient, and the strictness is the surprise.
2. casefold=True is the fix, and it's off by default
import base64
encoded = base64.b32encode(b"hello world")
print(base64.b32decode(encoded.lower(), casefold=True))
hexed = base64.b16encode(b"hello world")
print(base64.b16decode(hexed.lower(), casefold=True))
b'hello world'
b'hello world'
Measured: passing casefold=True to either function makes the identical lowercase input decode correctly. Both b32decode() and b16decode() accept this keyword, and both default it to False -- so any code that normalizes case before storing or transmitting a Base32/hex value (or receives it from a source that happens to lowercase it) will crash on decode unless the caller remembers this argument.
3. bytes.fromhex() has no such restriction
import base64, binascii
print(bytes.fromhex("68656c6c6f"))
print(binascii.a2b_hex(b"68656c6c6f"))
print(base64.b16decode(b"68656c6c6f"))
b'hello'
b'hello'
Traceback (most recent call last):
...
binascii.Error: Non-base16 digit found
Measured: both bytes.fromhex() and binascii.a2b_hex() accept lowercase hex digits with no special argument at all. base64.b16decode() is the odd one out among Python's own hex-handling functions -- it's easy to reach for it (since it lives in the same module as b64decode) and get bitten by a case-sensitivity rule none of the equivalent stdlib functions share.
Frequently asked questions
Does base64.b32decode() accept lowercase input?
No, not by default -- we measured it raising binascii.Error('Non-base32 digit found') on a lowercased valid Base32 string. Passing casefold=True fixes it.
Does base64.b16decode() accept lowercase hex digits?
No, not by default -- we measured binascii.Error('Non-base16 digit found') on lowercase hex. This differs from bytes.fromhex() and binascii.a2b_hex(), which both accept lowercase hex with no extra argument.
How do I make base64.b32decode() or b16decode() accept lowercase input?
Pass casefold=True. We confirmed the identical lowercase input that previously raised binascii.Error decodes correctly once casefold=True is set.
Why does base64.b16decode() reject lowercase hex when bytes.fromhex() accepts it?
They're separate implementations with different defaults. We measured both on the same lowercase hex string: bytes.fromhex() and binascii.a2b_hex() both succeeded, while base64.b16decode() raised unless casefold=True was passed.
Is lowercase Base32 or hex actually ambiguous to decode?
No -- both alphabets only define uppercase letters, so a lowercase letter can only mean one thing. We measured that casefold=True resolves it correctly every time; the rejection is a strictness choice, not a real ambiguity.
Written with AI assistance. Measured on 2026-10-04 with Python 3.13.5's built-in base64 module: encoded a known string with base32encode() and base16encode(), lowercased the result, and decoded it with and without casefold=True. Contrasted with bytes.fromhex() and binascii.a2b_hex() on equivalent lowercase hex input. PlainHeaders is our extension; Python's base64 module is built in.