Base64 Encoding & Decoding in Python

Python's standard library includes a base64 module with everything you need. The key thing to know: the module works with bytes, not strings — you need to encode/decode strings explicitly.

Basic Usage

import base64

# Encode: pass bytes, get bytes back
encoded = base64.b64encode(b"Hello, world!")
print(encoded)         # b'SGVsbG8sIHdvcmxkIQ=='
print(encoded.decode()) # 'SGVsbG8sIHdvcmxkIQ=='  (as string)

# Decode: pass bytes or string, get bytes back
decoded = base64.b64decode("SGVsbG8sIHdvcmxkIQ==")
print(decoded)         # b'Hello, world!'
print(decoded.decode()) # 'Hello, world!'  (as string)

Key pattern: str → .encode() → b64encode() → .decode() → str. Always encode your string to bytes before Base64-encoding, and decode the bytes result back to a string afterward.

Encoding Strings (Unicode-safe)

import base64

def encode_base64(text: str) -> str:
    """Encode a Unicode string to Base64."""
    return base64.b64encode(text.encode("utf-8")).decode("ascii")

def decode_base64(b64: str) -> str:
    """Decode a Base64 string back to Unicode text."""
    return base64.b64decode(b64).decode("utf-8")

print(encode_base64("Hello 🌍"))  # "SGVsbG8g8J+MjQ=="
print(decode_base64("SGVsbG8g8J+MjQ=="))  # "Hello 🌍"

URL-Safe Base64

Python's base64 module has dedicated functions for URL-safe Base64 (replaces + with - and / with _):

import base64

# URL-safe encode (with padding)
encoded = base64.urlsafe_b64encode(b"Hello, world!")
print(encoded)  # b'SGVsbG8sIHdvcmxkIQ=='

# URL-safe decode
decoded = base64.urlsafe_b64decode(encoded)
print(decoded)  # b'Hello, world!'

# Without padding (common for JWTs, tokens)
def urlsafe_b64encode_nopad(data: bytes) -> str:
    return base64.urlsafe_b64encode(data).rstrip(b"=").decode("ascii")

def urlsafe_b64decode_nopad(s: str) -> bytes:
    # Restore padding
    s += "=" * (4 - len(s) % 4)
    return base64.urlsafe_b64decode(s)

Encoding Files

import base64

# Encode a file to Base64 string
with open("image.png", "rb") as f:
    encoded = base64.b64encode(f.read()).decode("ascii")
print(encoded[:80] + "...")  # iVBORw0KGgoAAAANSUhEUgAA...

# Decode Base64 back to file
with open("output.png", "wb") as f:
    f.write(base64.b64decode(encoded))

For large files, use base64.encodebytes() which inserts newlines every 76 characters (MIME-compliant):

import base64

with open("large_file.pdf", "rb") as f:
    # MIME-style with line breaks (for email attachments)
    mime_encoded = base64.encodebytes(f.read()).decode("ascii")

# Decode MIME-style (handles embedded newlines)
decoded = base64.decodebytes(mime_encoded.encode("ascii"))

Encoding to Data URI (for HTML/CSS)

import base64, mimetypes

def file_to_data_uri(filepath: str) -> str:
    mime_type, _ = mimetypes.guess_type(filepath)
    if not mime_type:
        mime_type = "application/octet-stream"
    with open(filepath, "rb") as f:
        encoded = base64.b64encode(f.read()).decode("ascii")
    return f"data:{mime_type};base64,{encoded}"

# Usage
uri = file_to_data_uri("logo.png")
print(uri[:60])  # data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...

Common Pitfalls

Passing a str instead of bytes to b64encode

base64.b64encode("Hello")  # ❌ TypeError: a bytes-like object is required
base64.b64encode(b"Hello") # ✓ correct

Forgetting to strip whitespace before decoding

If your Base64 string came from a file or network response it may have newlines. b64decode() accepts a validate=False default that silently ignores invalid characters, or you can strip manually:

import base64, re

def safe_b64decode(s: str) -> bytes:
    # Remove whitespace
    s = re.sub(r"\s+", "", s)
    # Restore padding if stripped
    s += "=" * (4 - len(s) % 4)
    return base64.b64decode(s)

Validating Base64 input

import base64

def is_valid_base64(s: str) -> bool:
    try:
        base64.b64decode(s, validate=True)
        return True
    except Exception:
        return False

Test your Python Base64 output

Paste the encoded string from your Python script into base64.dev to verify it decodes correctly.

Open base64.dev →