Base64 in Python: Encode and Decode Strings and Files
Base64 shows up everywhere in Python work — encoding binary data for JSON, building data URIs, decoding JWT segments, handling API credentials. Python's standard library has a built-in base64 module that handles all of it, but the bytes-vs-string distinction trips up almost everyone the first time.
This guide covers encoding and decoding strings, bytes, and files, plus the URL-safe variant, with the gotchas called out.
The One Rule: Base64 Works on Bytes
The single most important thing to understand: base64 operates on bytes, not str. Every encode/decode call takes bytes in and gives bytes out. If you have a string, you .encode() it to bytes first; to get a readable string back, you .decode() the result.
Skipping this is the source of nearly every TypeError: a bytes-like object is required you'll hit.
Encoding a String
import base64
text = "Hello, World!"
# str → bytes → base64 bytes → str
encoded = base64.b64encode(text.encode("utf-8")).decode("ascii")
print(encoded) # SGVsbG8sIFdvcmxkIQ==
Walking through the chain:
text.encode("utf-8")→b"Hello, World!"(bytes)base64.b64encode(...)→b"SGVsbG8sIFdvcmxkIQ=="(base64 as bytes).decode("ascii")→"SGVsbG8sIFdvcmxkIQ=="(a normal string you can print/store)
Decoding a String
The reverse:
import base64
encoded = "SGVsbG8sIFdvcmxkIQ=="
decoded = base64.b64decode(encoded).decode("utf-8")
print(decoded) # Hello, World!
b64decode accepts either a str or bytes for the input (it's lenient on the way in), and returns bytes. Call .decode("utf-8") to turn those bytes back into text.
To sanity-check a value by hand without running code, paste it into the Base64 Encoder/Decoder — it shows the round-trip instantly and is handy for verifying what your Python produced.
Encoding and Decoding Files
For binary files — images, PDFs, anything — read in binary mode ("rb") and encode the raw bytes:
import base64
# Encode a file to a base64 string
with open("logo.png", "rb") as f:
encoded = base64.b64encode(f.read()).decode("ascii")
# Decode a base64 string back to a file
with open("logo-copy.png", "wb") as f:
f.write(base64.b64decode(encoded))
Note "rb" and "wb" — binary mode is essential. Open the file as text and non-ASCII bytes will corrupt or raise an error. For a quick file round-trip without writing a script, the Base64 File Encoder does the same in the browser.
URL-Safe Base64
Standard Base64 uses + and /, which have special meaning in URLs and filenames. The URL-safe variant swaps them for - and _. This is what JWTs and many OAuth flows use:
import base64
data = b"\xfb\xff\xbf" # bytes that produce + and / in standard base64
print(base64.b64encode(data)) # b'+/+/'
print(base64.urlsafe_b64encode(data)) # b'-_-_'
# Decode URL-safe
base64.urlsafe_b64decode("-_-_")
If you're decoding a JWT payload, use urlsafe_b64decode — and watch the padding (next section). The Base64URL tool handles this variant for quick checks.
The Padding Gotcha
Base64 output length is always a multiple of 4, padded with =. JWTs and some APIs strip the padding to save bytes, which makes Python's decoder raise:
binascii.Error: Incorrect padding
Re-add the padding before decoding:
def b64decode_nopad(s: str) -> bytes:
# add back the missing '=' (0–3 of them)
return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
The expression "=" * (-len(s) % 4) adds exactly the number of = needed to make the length a multiple of 4.
Encoding Credentials (a Common Use)
HTTP Basic Auth encodes username:password in Base64:
import base64
creds = base64.b64encode(b"admin:secret").decode("ascii")
headers = {"Authorization": f"Basic {creds}"}
Remember: Base64 is encoding, not encryption. Anyone can decode it. It's for safe transport of bytes through text channels, never for hiding secrets. For actual confidentiality, encrypt the data — see How to Encrypt a File With a Password. For decoding Base64 on the shell instead of Python, see Base64 Decode on the Command Line.
Quick Reference
base64works on bytes —.encode()your string going in,.decode()the result coming out.- Encode string:
base64.b64encode(text.encode()).decode(). - Decode string:
base64.b64decode(encoded).decode(). - Files: open in binary mode (
"rb"/"wb") and encode/decode the raw bytes. - Use
urlsafe_b64encode/decodefor JWT/OAuth; re-add=padding to fix "Incorrect padding". - Base64 is not encryption — verify values with the Base64 tool, encrypt real secrets separately.