base64.b16encode / b16decode
RFC 4648 Base16 is hex in uppercase. The decoder rejects lowercase (unless casefold=True), spaces and an odd number of digits — bytes.fromhex is the forgiving alternative.
Common call
base64.b16encode(data) · base64.b16decode(text, casefold=True)
Returns
bytes — b'6869' / b'hi'
Replaces
binascii.hexlify(data).upper()
Watch out
Lowercase hex fails without casefold=True — and bytes.hex() produces lowercase
base64.b16decode(ss — Data to encode, or hex text to decode (only 0–9 A–F, even length).type: bytes-like (encode) · bytes-like | ASCII str (decode) · required, casefoldcasefold — Decode only: accept lowercase a–f.type: bool · default: False=False)
→ bytes
Demo
Live evaluation
b16encode next to bytes.hex(): same digits, different case and type.
Try:
Inputs
textstrany text
Code
import base64 data = 'Hello'.encode() (base64.b16encode(data), data.hex())
Result
(b'48656C6C6F', '48656c6c6f')
b16decode checks the characters first and the length second: lowercase and spaces give "Non-base16 digit found", while "486" passes the character check and then fails in binascii with "Odd-length string". casefold=True uppercases the input before checking, so it fixes lowercase but not spaces.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| s | bytes-like (encode) · bytes-like | ASCII str (decode) | yes | Data to encode, or hex text to decode (only 0–9 A–F, even length). |
| casefold | bool | no (False) | Decode only: accept lowercase a–f. |
Return value
bytes — Encode: uppercase hex digits as ASCII bytes. Decode: the original bytes.
Common patterns
Hex of a hash, uppercase
hexdigest() is lowercase; b16encode gives the uppercase form some APIs want.
import base64, hashlib base64.b16encode(hashlib.sha256(data).digest()).decode('ascii')
Lenient hex parsing
bytes.fromhex accepts either case and whitespace between bytes.
raw = bytes.fromhex('48 65 6c 6c 6f')
Examples
1. Encode
import base64
base64.b16encode(b'\x00\xffhi')
Returns
b'00FF6869'2. bytes.hex is lowercase
b'\x00\xffhi'.hex()
Returns
'00ff6869'3. Decode
import base64
base64.b16decode('48656C6C6F')
Returns
b'Hello'4. Lowercase rejected
import base64
base64.b16decode('48656c6c6f')
Returns
binascii.Error: Non-base16 digit found5. casefold=True
import base64
base64.b16decode('48656c6c6f', casefold=True)
Returns
b'Hello'6. Odd length
import base64
base64.b16decode('486')
Returns
binascii.Error: Odd-length stringPitfalls
1. Decoding the output of bytes.hex()
hex() and hexdigest() are lowercase; b16decode wants uppercase by default.
b16decode(hex())
import base64 base64.b16decode(b'\xca\xfe'.hex())
binascii.Error: Non-base16 digit found
casefold=True
import base64 base64.b16decode(b'\xca\xfe'.hex(), casefold=True)
b'\xca\xfe'
2. Spaced hex dumps
Spaces are not Base16 digits. bytes.fromhex skips whitespace between byte pairs.
b16decode
import base64 base64.b16decode('DE AD BE EF')
binascii.Error: Non-base16 digit found
bytes.fromhex
bytes.fromhex('DE AD BE EF')
b'\xde\xad\xbe\xef'
When to use
Use it
- Protocols that specify RFC 4648 Base16 (uppercase)
- Strict validation of hex input
Reach for something else
- Everyday hex → bytes.hex() and bytes.fromhex() need no import
- Compact output → Base64 adds a third to the size, hex doubles it
Notes
CPython impl
b16encode = binascii.hexlify(s).upper(); b16decode checks re.search(b"[^0-9A-F]") and then calls binascii.unhexlify
Exceptions
binascii.Error: "Non-base16 digit found" (character check) or "Odd-length string" (from unhexlify)
FAQ
The case and the type: b16encode returns uppercase bytes (b"6869"), bytes.hex() returns a lowercase str ("6869"). The digits are the same.