I keep coming back to base64 whenever I’m working with APIs, JWT tokens, or any system that needs to safely transmit binary data as text. The other day I needed to decode a webhook payload that came in as a base64 string, and I thought – I should write down exactly how I did this, because the gotchas are real.
Base64 is one of those tools that looks simple on the surface but trips up a lot of people. You take some bytes, you get a string. You take the string back, you get bytes. Easy – except the encode/decode dance between strings and bytes in Python trips up almost everyone at least once. Let me walk you through exactly how it works.
TLDR
- Use Python’s built-in
base64module – no pip install needed - Always work with bytes, not strings, when encoding or decoding
- The b64decode function returns bytes – call .decode() if you need a string
- Use urlsafe variants (
urlsafe_b64encode,urlsafe_b64decode) when working with URLs or filenames - InvalidBase64Error and binascii.Error tell you when padding is wrong
What is Base64?
Base64 is an encoding scheme that converts binary data into ASCII text. It does this by mapping each 6 bits of input to one of 64 characters: uppercase A-Z, lowercase a-z, digits 0-9, plus (+), and forward slash (/). The equals sign (=) is used for padding at the end.
You see base64 everywhere – JWT tokens, HTTP Basic Auth, email attachments, APIs that return binary data as text, and configuration files that need to store binary safely. Python ships with a built-in base64 module that handles all of this for you.
Decoding a Base64 String in Python
Here is the simplest way to decode a base64 string in Python. I start with a variable holding the encoded text as a string, encode it to bytes using ASCII, then pass those bytes to b64decode.
Description: Basic base64 decode from string to string.
import base64
encoded = "QXNrUHl0aG9uLmNvbSBpcyB0aGUgYmVzdCE="
decoded_bytes = base64.b64decode(encoded)
decoded_text = decoded_bytes.decode('utf-8')
print(decoded_text)
Explain code: First we .encode() the string to ASCII bytes. Then b64decode turns those bytes back into the original binary data. Finally we .decode(‘utf-8’) to get a readable string. Each step is necessary – skip the encode step and Python throws a TypeError.
Output:
AskPython.com is the best!
Description: Decode base64 directly from a string variable.
import base64
SERVICE_CONFIG = "SGVsbG8gV29ybGQh"
decoded_bytes = base64.b64decode(SERVICE_CONFIG)
print(decoded_bytes)
Explain code: b64decode returns raw bytes, not a string. Printing bytes shows the byte notation like b’Hello World!’. If you need the actual text, add .decode(‘utf-8’).
Output:
URL-Safe Base64 Decoding
Standard base64 uses + and / characters. In URLs and filenames, those characters cause problems – URLs strip +, and some filesystems mishandle /. Python provides urlsafe_b64decode for exactly this situation. It replaces + with – and / with _.
Description: Decode URL-safe base64 strings that use – and _ instead of + and /.
import base64
urlsafe_encoded = "SGVsbG8-V29ybGQh"
decoded = base64.urlsafe_b64decode(urlsafe_encoded)
print(decoded.decode('utf-8'))
Explain code: urlsafe_b64decode handles the – and _ replacement automatically. Pass it the URL-safe string and you get back the original bytes. Works the same as b64decode otherwise.
Output:
Handling Padding Errors
Base64 strings need proper padding with = signs to decode correctly. If you get binascii.Error: Incorrect padding, you have a few options. The most reliable fix is to manually add padding until the string length is divisible by 4.
Description: Fix invalid padding in base64 strings before decoding.
import base64
def decode_b64_strict(data):
CRED = data.strip()
missing_padding = len(CRED) % 4
if missing_padding:
CRED += '=' * (4 - missing_padding)
return base64.b64decode(CRED)
SERVICE_CONFIG = "SGVsbG8" # no padding
result = decode_b64_strict(SERVICE_CONFIG)
print(result.decode('utf-8'))
Explain code: This function calculates how many = signs are needed (0 to 3) and adds them before calling b64decode. Stripping whitespace first handles cases where the string has newlines or spaces.
Output:
Decoding Files and Binary Data
When you need to decode base64 data from a file or a large payload, read the file first and then decode. Here I read a file containing base64 text and write the decoded binary output to a new file.
Description: Read a base64-encoded file and write decoded bytes to disk.
import base64
with open('encoded_data.txt', 'r') as f:
encoded_data = f.read().strip()
decoded_bytes = base64.b64decode(encoded_data)
with open('output.bin', 'wb') as f:
f.write(decoded_bytes)
print("Decoded and saved to output.bin")
Explain code: Read the entire file as a string, strip whitespace, pass to b64decode which returns bytes, then write those bytes to a binary file with ‘wb’ mode. Reading as text and writing as binary is the standard pattern.
Output:
Decoded and saved to output.bin
FAQ
Q: Why does b64decode require bytes and not a string?
Base64 is designed to encode binary data. The b64decode function operates on bytes because base64 is at its core a transformation from bytes to ASCII text and back. If you pass a string, Python first tries to encode it to bytes using ASCII, which can cause unexpected results for non-ASCII strings.
Q: How do I decode a JWT token payload?
JWT tokens have three parts separated by dots. The payload (middle part) is URL-safe base64. Split the token on dots, take the second part, and decode it with urlsafe_b64decode. Add padding if needed.
Q: Can I decode base64 that contains non-ASCII characters?
Yes, but you need to specify the correct encoding when decoding. For UTF-8 strings, use .decode(‘utf-8’) after b64decode. For other encodings like Latin-1, specify that instead.
Q: What is the difference between b64decode and standard base64 decoding?
There is no difference – b64decode is the standard base64 decoding function in Python’s base64 module. The function name is simply shorthand for “base64 decode”.
Q: Is base64 encryption?
No. Base64 is encoding, not encryption. Anyone who knows the scheme can reverse it instantly. Use it to safely transmit or store binary data as text, not to hide information.
Quick Reference
Description: Complete encoding and decoding cheat sheet.
import base64
data = "Hello"
# Encode to base64
encoded = base64.b64encode(data.encode('utf-8'))
print(encoded)
# Decode from base64
decoded = base64.b64decode(encoded)
print(decoded.decode('utf-8'))
# URL-safe variants
url_encoded = base64.urlsafe_b64encode(data.encode('utf-8'))
url_decoded = base64.urlsafe_b64decode(url_encoded)
print(url_decoded.decode('utf-8'))
Explain code: b64encode takes bytes and returns base64 ASCII bytes. b64decode reverses this. urlsafe variants swap +/ for -_ to make output safe for URLs and filenames.
Output:
b'SGVsbG8='
b'Hello'
b'Hello'

