Encode and Decode Base64 Data in Python

Learn how to use Python's base64 module to encode binary data as text and decode Base64 strings back to bytes.

6 min read

The base64 module in the Python standard library encodes binary data into ASCII text and decodes it back. Base64 is used whenever binary data needs to travel through text-only channels: embedding images in HTML or CSS, attaching files to JSON payloads, storing binary data in text-based databases, and encoding credentials in HTTP headers.

pythonpython
import base64
 
data = b"Hello, Python!"
encoded = base64.b64encode(data)
decoded = base64.b64decode(encoded)
 
print(encoded)  # b'SGVsbG8sIFB5dGhvbiE='
print(decoded)  # b'Hello, Python!'

b64encode() takes bytes and returns bytes. The output is about 33% larger than the input because every 3 bytes of binary data become 4 Base64 characters. The trailing = is padding added when the input length is not a multiple of 3.

Encoding strings

Most data that needs Base64 encoding starts out as text, like a config value or a credential pair, rather than raw bytes. Base64 works with bytes, not strings, so convert strings to bytes first.

pythonpython
import base64
 
text = "user@example.com:api_key_12345"
encoded = base64.b64encode(text.encode()).decode()
print(encoded)  # dXNlckBleGFtcGxlLmNvbTphcGlfa2V5XzEyMzQ1

text.encode() converts the string to UTF-8 bytes. base64.b64encode() encodes those bytes as Base64 bytes. .decode() converts the Base64 bytes back to a string for display or insertion into text protocols.

Decoding back to original data

Decoding reverses the process: Base64 text to bytes, then optionally to a string.

pythonpython
import base64
 
encoded = "dXNlckBleGFtcGxlLmNvbTphcGlfa2V5XzEyMzQ1"
decoded_bytes = base64.b64decode(encoded)
decoded_text = decoded_bytes.decode()
print(decoded_text)  # user@example.com:api_key_12345

base64.b64decode() accepts both bytes and strings. The result is always bytes. Call .decode() on the result if the original data was a string.

URL-safe Base64

Standard Base64 uses + and /, which have special meanings in URLs. The URL-safe variant replaces them with - and _, though it still adds the same = padding by default.

pythonpython
import base64
 
data = b"\xfa\xce\xb0\x0c\x1a\x2b\x3c"
standard = base64.b64encode(data)
urlsafe = base64.urlsafe_b64encode(data)
 
print(standard)  # b'+s6wDBorPA=='
print(urlsafe)   # b'-s6wDBorPA=='

The + becomes - and / becomes _. Use URL-safe encoding for tokens in URLs, query parameters, and filenames.

For the secrets module, use secrets.token_urlsafe() to generate URL-safe tokens directly without working with Base64 yourself.

Encoding and decoding large data

Base64 encoding works incrementally, like hashing. For large files or streams, use incremental encoding with base64.encode() and base64.decode() from the base64 module's codecs interface, or process data in chunks.

For simple file encoding:

pythonpython
import base64
 
with open("image.png", "rb") as file:
    image_bytes = file.read()
 
encoded = base64.b64encode(image_bytes).decode()
print(f"data:image/png;base64,{encoded[:50]}...")  # data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...

For very large files, read and encode in chunks to manage memory, though the standard b64encode works fine for files up to a few hundred megabytes.

When to use Base64

Base64 is encoding, not encryption. It transforms data into a portable text representation but provides no security. Anyone who sees the Base64 output can decode it back to the original data.

Common uses for Base64:

  • Embedding binary data (images, fonts) inside HTML, CSS, or JSON.
  • Encoding credentials for HTTP Basic Authentication headers.
  • Storing binary data in text-only database columns.
  • Transmitting binary payloads through text-based protocols.
  • Creating compact text representations of small binary values.

Do not use Base64 for:

  • Encrypting sensitive data (use proper encryption libraries).
  • Compressing data (Base64 makes it larger, not smaller).
  • Hashing data (use hashlib).
  • Generating secure tokens (use the secrets module).

Standard vs URL-safe comparison

Featureb64encodeurlsafe_b64encode
Character setA-Z, a-z, 0-9, +, /A-Z, a-z, 0-9, -, _
Padding= (1 or 2)= (1 or 2, by default)
URL-safeNo (needs percent-encoding)Yes
Filename-safeNoYes

Always use URL-safe Base64 when the output appears in a URL, a query parameter, or a filename.

Practical example: embedding an image in HTML

Convert a small image to a data URI for inline HTML embedding.

pythonpython
import base64
from pathlib import Path
 
def image_data_uri(filepath):
    ext = Path(filepath).suffix.lower().lstrip(".")
    mime_types = {"png": "image/png", "jpg": "image/jpeg", "gif": "image/gif", "svg": "image/svg+xml"}
    mime = mime_types.get(ext, "application/octet-stream")
 
    with open(filepath, "rb") as file:
        encoded = base64.b64encode(file.read()).decode()
 
    return f"data:{mime};base64,{encoded}"

Calling the function on a PNG file produces a single long string starting with the correct MIME type, which is why only the first 80 characters are printed here:

pythonpython
uri = image_data_uri("icon.png")
print(uri[:80] + "...")

The real string continues for many more characters, but the truncated prefix is enough to confirm the MIME type and encoding were applied correctly:

texttext
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...

The data URI can be used directly as the src attribute of an HTML img tag. This avoids a separate HTTP request for the image but increases the HTML file size.

Common mistakes

Treating Base64 as encryption. Base64 is reversible without a key. Never use it to protect sensitive data. Anyone who sees the encoded string can recover the original data with b64decode.

Forgetting to decode the output of b64encode. b64encode() returns bytes. If you need a string (for JSON, URLs, or HTML), call .decode() on the result.

Using standard Base64 in URLs. The + and / characters require percent-encoding in URLs. Use urlsafe_b64encode() for any value that appears in a URL or filename.

Adding the wrong padding back. When you strip = padding from URL-safe Base64 and later need to decode, pass the string directly to urlsafe_b64decode. It handles the missing padding automatically.

Rune AI

Rune AI

Key Insights

  • Use base64.b64encode(data) to encode bytes as a Base64 byte string.
  • Use base64.b64decode(encoded) to decode a Base64 string back to bytes.
  • Use base64.urlsafe_b64encode() for URL and filename-safe output.
  • Base64 output is about 33% larger than the original binary data.
  • Base64 is encoding, not encryption; it provides no confidentiality.
  • Always work with bytes; encode strings to bytes before Base64 encoding.
RunePowered by Rune AI

Frequently Asked Questions

Why does Base64 encoding make data larger?

Base64 encodes every 3 bytes of binary data as 4 ASCII characters. This results in roughly a 33% size increase. The tradeoff is that the output uses only printable ASCII characters, making it safe for text-based protocols like email, JSON, and URLs.

What is the difference between standard Base64 and URL-safe Base64?

Standard Base64 uses `+` and `/` as two of its 64 characters. URL-safe Base64 replaces `+` with `-` and `/` with `_`. Python's `urlsafe_b64encode` still adds `=` padding by default; strip it yourself if your application needs padding-free output. This makes the result safe to include in URLs and filenames without percent-encoding.

Can Base64 be used for encryption?

No. Base64 is encoding, not encryption. It transforms data into a different representation, but anyone can decode it without a key. Base64 provides no confidentiality. Use proper encryption libraries for securing data.

Conclusion

The base64 module handles the most common binary-to-text encoding needs in Python. Use base64.b64encode() and base64.b64decode() for standard Base64, and base64.urlsafe_b64encode() when the output goes into a URL. Remember that Base64 is encoding, not encryption; it adds no security to your data.