How to Decode Base64 in Python — Step by Step
Decoding Base64 in Python looks trivial until you hit a padding error or end up with mojibake instead of readable text. This tutorial walks through the correct pattern step by step, including how to handle malformed input and when to stop at bytes instead of decoding to a string.
Step 1: Import the base64 module
No installation needed — base64 is part of the Python standard library.
import base64
Step 2: Decode to bytes with b64decode
base64.b64decode() accepts either a str or bytes input and always returns bytes. This is the one function you need for the actual decoding step.
encoded = "SGVsbG8sIFdvcmxkIQ==" raw_bytes = base64.b64decode(encoded) print(raw_bytes) # → b'Hello, World!'
Step 3: Convert bytes to text (only if it's text)
If the original data was a string, call .decode("utf-8") on the bytes to get readable text back. If the original data was binary (an image, a PDF, a zip file), skip this step and write the bytes straight to a file instead.
# Text data
text = raw_bytes.decode("utf-8")
print(text)
# → Hello, World!
# Binary data — write directly, do NOT call .decode()
with open("output.png", "wb") as f:
f.write(raw_bytes)Handling the "Incorrect padding" error
Base64 requires the encoded string's length to be a multiple of 4, with = used to pad the final group. If you receive a Base64 string from an API or a JWT segment with padding stripped, b64decode raises binascii.Error. Pad it back manually before decoding:
import base64
def safe_b64decode(s: str) -> bytes:
# Add back any missing '=' padding
padding_needed = -len(s) % 4
s += "=" * padding_needed
return base64.b64decode(s)
# Works even if padding was stripped (common in JWTs)
safe_b64decode("SGVsbG8")
# → b'Hello'Validating Base64 before decoding
Use the validate=True flag to make Python reject strings containing characters outside the Base64 alphabet, instead of silently ignoring them.
import base64
import binascii
def try_decode(s: str):
try:
return base64.b64decode(s, validate=True)
except (binascii.Error, ValueError) as e:
print(f"Invalid Base64: {e}")
return None
try_decode("not valid base64!!") # → prints error, returns None
try_decode("SGVsbG8=") # → b'Hello'Common pitfalls checklist
- Decoding a URL-safe Base64 string with
b64decodeinstead ofurlsafe_b64decode— the-and_characters won't decode correctly. - Calling
.decode("utf-8")on binary output like image bytes — this raisesUnicodeDecodeError. - Forgetting that Base64 strings from web APIs sometimes have whitespace or newlines injected — strip them first with
s.strip(). - Assuming decoding proves the data is safe — Base64 is not encryption; always validate/sanitize decoded content before using it.
Frequently Asked Questions
Use base64.b64decode(your_string) to get the raw bytes, then call .decode("utf-8") on the result if the original data was text. If the Base64 string is a plain str, Python automatically encodes it to bytes before decoding.
Base64 strings must have a length that is a multiple of 4, using = as padding. This error means the input was truncated or padding was stripped. Fix it by appending the missing = characters before calling b64decode.
Decode to bytes first with b64decode() always. Only call .decode("utf-8") afterward if you know the original data was text, such as JSON or plain strings. For images, PDFs, or other binary files, keep the result as bytes and write it directly to a file.