Encoding2026-05-28

Base64 in Python: Encode and Decode Strings and Files

How to Base64 encode and decode in Python with the base64 module — strings, bytes, files, and URL-safe variants — plus the bytes-vs-str gotcha that trips everyone.

base64pythonencodedecodebytes

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:

  1. text.encode("utf-8")b"Hello, World!" (bytes)
  2. base64.b64encode(...)b"SGVsbG8sIFdvcmxkIQ==" (base64 as bytes)
  3. .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

  • base64 works 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/decode for JWT/OAuth; re-add = padding to fix "Incorrect padding".
  • Base64 is not encryption — verify values with the Base64 tool, encrypt real secrets separately.