The Python 3 Base64 Type Model
Python 3 is strict about the difference between str (Unicode text) andbytes (raw binary data). The base64 module operates exclusively on bytes — both input and output. This trips up many developers coming from Python 2 or dynamically typed languages. Here is the mental model:
- Your input is a
str? Encode to bytes first with.encode("utf-8"). - Your input is a file? Open in binary mode with
"rb". - Your input is already bytes? Pass it directly.
- The output is always bytes. To use it as a string (JSON, YAML, env var),
.decode("ascii").
Encoding a String — The Standard Pattern
import base64
text = 'Hello 世界 👋'
# Step 1: str → bytes (using UTF-8)
utf8_bytes = text.encode('utf-8')
print(utf8_bytes) # b'Hello \xe4\xb8\x96\xe7\x95\x8c \xf0\x9f\x91\x8b'
# Step 2: bytes → Base64 bytes
b64_bytes = base64.b64encode(utf8_bytes)
print(b64_bytes) # b'SGVsbG8g5LiW55WMIPCfkYs='
# Step 3: Base64 bytes → str (for storage/transport)
b64_string = b64_bytes.decode('ascii')
print(b64_string) # 'SGVsbG8g5LiW55WMIPCfkYs='
# One-liner:
encoded = base64.b64encode(text.encode('utf-8')).decode('ascii')Encoding a File
import base64
# Small to medium files — read all at once
with open('./image.png', 'rb') as f:
encoded = base64.b64encode(f.read()).decode('ascii')
# Now you can embed the file in JSON, put it in an env var, etc.
print(len(encoded)) # roughly 4/3 the file size
# Very large files — stream to avoid loading everything into memory
with open('./huge.bin', 'rb') as input_file, open('./huge.b64', 'wb') as output_file:
base64.encode(input_file, output_file) # streams block by block
# Create a data URL for embedding an image in HTML
with open('./photo.jpg', 'rb') as f:
b64 = base64.b64encode(f.read()).decode('ascii')
data_url = f'data:image/jpeg;base64,{b64}'URL-Safe Base64 for JWTs and Query Strings
import base64
payload = '{"user_id": 42, "role": "admin"}'
bytes_in = payload.encode('utf-8')
# Standard Base64 (uses + and /)
std = base64.b64encode(bytes_in).decode('ascii')
print(std) # 'eyJ1c2VyX2lkIjogNDIsICJyb2xlIjogImFkbWluIn0='
# URL-safe Base64 (uses - and _)
urlsafe = base64.urlsafe_b64encode(bytes_in).decode('ascii')
print(urlsafe) # 'eyJ1c2VyX2lkIjogNDIsICJyb2xlIjogImFkbWluIn0='
# JWT-style (strip padding)
def b64url_encode(data: bytes) -> str:
return base64.urlsafe_b64encode(data).rstrip(b'=').decode('ascii')
def b64url_decode(s: str) -> bytes:
# Add padding back
padding = 4 - len(s) % 4
if padding != 4:
s += '=' * padding
return base64.urlsafe_b64decode(s)Encoding a Dict / JSON Object
import base64
import json
data = {
'user_id': 42,
'email': '[email protected]',
'roles': ['admin', 'editor'],
'joined': '2026-01-15'
}
# Serialize → UTF-8 bytes → Base64 → string
encoded = base64.b64encode(
json.dumps(data, separators=(',', ':')).encode('utf-8')
).decode('ascii')
print(encoded)
# Round trip
decoded_dict = json.loads(base64.b64decode(encoded).decode('utf-8'))
assert decoded_dict == dataBuilding an HTTP Basic Auth Header in Python
import base64
import requests
def basic_auth_header(user: str, password: str) -> dict:
creds = f'{user}:{password}'.encode('utf-8')
token = base64.b64encode(creds).decode('ascii')
return {'Authorization': f'Basic {token}'}
# Use it
headers = basic_auth_header('admin', 'secret123')
response = requests.get('https://api.example.com/protected', headers=headers)Common Pitfalls in Python Base64 Code
- TypeError: a bytes-like object is required, not str — You passed a string to b64encode. Add
.encode("utf-8")before the call. - Output looks like
b'SGVsbG8='— That's the bytes representation. Call.decode("ascii")to get a plain string. - Opening a binary file in text mode —
open(path, "r")fails on non-UTF-8 bytes with UnicodeDecodeError. Use"rb"for binary files. - Padding mismatch on decode — If you stripped
=characters before storing the Base64, add them back before decoding:s += "=" * (-len(s) % 4). - Using b64encode when URL-safe is required — JWTs and URL query params need
urlsafe_b64encode. Standard Base64 has+and/which get percent-encoded or misinterpreted.
Command Line Alternative
If you just need a one-off encode from the shell without writing a Python script:
# From the terminal (Python one-liner)
python3 -c "import base64; print(base64.b64encode('Hello'.encode()).decode())"
# Or use the built-in base64 command directly:
echo -n "Hello" | base64Key Facts
- Module:
- base64 (Python standard library — no pip install)
- Standard function:
- base64.b64encode(data)
- URL-safe function:
- base64.urlsafe_b64encode(data)
- Input type:
- bytes (never str — encode with .encode('utf-8') first)
- Output type:
- bytes (decode with .decode('ascii') to get a string)
- Streaming variant:
- base64.encode(input_file, output_file) for large files
Related Base64 Tools
- Base64 Encode Online — general-purpose browser encoder
- Base64 Encode String — cross-language string encoding guide
- Text to Base64 Converter — plain text conversion
- Base64 Encode in JavaScript — JavaScript equivalent
- Base64 Decode — reverse the encoding
- JWT Debugger — inspect JWT tokens