1926 words
10 minutes
Python Base64 Module - Complete Guide

🔐 Python Base64 Module - Complete Guide#

Base64 Encoding


📚 Table of Contents#

  1. What is Base64?
  2. Why Use Base64?
  3. Basic Encoding
  4. Basic Decoding
  5. URL-Safe Base64
  6. Base32 Encoding
  7. Base16 (Hex) Encoding
  8. Base85 Encoding
  9. Encoding Files
  10. Encoding Images
  11. Data URLs
  12. Working with JSON
  13. Security Considerations
  14. Common Use Cases
  15. Practical Projects

1. What is Base64?#

Base64 Concept

Base64 is an encoding scheme that converts binary data into ASCII text.

How It Works#

  • Takes 3 bytes (24 bits) of data
  • Splits into 4 groups of 6 bits each
  • Maps each 6-bit group to a character (A-Z, a-z, 0-9, +, /)

Base64 Character Set#

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

Example#

Text: "Hi"
Binary: 01001000 01101001
Base64: SGk=

2. Why Use Base64?#

Common Uses#

Use CaseDescription
Email attachmentsMIME encoding
Embedding imagesData URLs in HTML
API data transferJSON/XML payloads
Storing binary in textDatabases, configs
Basic obfuscationHide readable text
AuthenticationHTTP Basic Auth

Pros and Cons#

Pros:

  • ✅ Text-safe (no special characters)
  • ✅ Works everywhere
  • ✅ Reversible

Cons:

  • ❌ ~33% size increase
  • ❌ NOT encryption (easily decoded)

3. Basic Encoding#

Import the Module#

import base64

Encode String#

import base64
# Original text
text = "Hello, World!"
# Encode (string → bytes → base64 bytes → base64 string)
encoded_bytes = base64.b64encode(text.encode('utf-8'))
encoded_string = encoded_bytes.decode('utf-8')
print(f"Original: {text}")
print(f"Encoded: {encoded_string}")
# Output:
# Original: Hello, World!
# Encoded: SGVsbG8sIFdvcmxkIQ==

Simple One-Liner#

import base64
# Encode
encoded = base64.b64encode(b"Hello").decode()
print(encoded) # SGVsbG8=
# Alternative with string
text = "Hello, World!"
encoded = base64.b64encode(text.encode()).decode()
print(encoded) # SGVsbG8sIFdvcmxkIQ==

Encode Bytes Directly#

import base64
# Binary data
data = bytes([0x48, 0x65, 0x6c, 0x6c, 0x6f]) # "Hello" in bytes
encoded = base64.b64encode(data)
print(encoded) # b'SGVsbG8='

4. Basic Decoding#

Decode Base64 String#

import base64
# Base64 encoded string
encoded = "SGVsbG8sIFdvcmxkIQ=="
# Decode (base64 string → bytes → string)
decoded_bytes = base64.b64decode(encoded)
decoded_string = decoded_bytes.decode('utf-8')
print(f"Encoded: {encoded}")
print(f"Decoded: {decoded_string}")
# Output:
# Encoded: SGVsbG8sIFdvcmxkIQ==
# Decoded: Hello, World!

Simple One-Liner#

import base64
# Decode
decoded = base64.b64decode("SGVsbG8sIFdvcmxkIQ==").decode()
print(decoded) # Hello, World!

Handle Errors#

import base64
def safe_decode(encoded_string):
try:
decoded = base64.b64decode(encoded_string).decode('utf-8')
return decoded
except Exception as e:
return f"Error: {e}"
# Test
print(safe_decode("SGVsbG8=")) # Hello
print(safe_decode("Invalid!!!")) # Error: ...

5. URL-Safe Base64#

Standard Base64 uses + and / which are not URL-safe. URL-safe Base64 replaces them with - and _.

Encode URL-Safe#

import base64
text = "Hello?World+Test"
# Standard Base64
standard = base64.b64encode(text.encode()).decode()
print(f"Standard: {standard}")
# URL-Safe Base64
url_safe = base64.urlsafe_b64encode(text.encode()).decode()
print(f"URL-Safe: {url_safe}")
# Output:
# Standard: SGVsbG8/V29ybGQrVGVzdA==
# URL-Safe: SGVsbG8_V29ybGQrVGVzdA==

Decode URL-Safe#

import base64
encoded = "SGVsbG8_V29ybGQrVGVzdA=="
decoded = base64.urlsafe_b64decode(encoded).decode()
print(decoded) # Hello?World+Test

Comparison#

CharacterStandardURL-Safe
Plus+-
Slash/_
Padding==

6. Base32 Encoding#

Base32 uses only uppercase letters A-Z and digits 2-7. Useful when case-insensitive encoding is needed.

Encode Base32#

import base64
text = "Hello"
# Encode
encoded = base64.b32encode(text.encode()).decode()
print(f"Base32: {encoded}") # JBSWY3DP
# Decode
decoded = base64.b32decode(encoded).decode()
print(f"Decoded: {decoded}") # Hello

Base32 Character Set#

ABCDEFGHIJKLMNOPQRSTUVWXYZ234567

Use Cases#

  • TOTP/HOTP tokens (Google Authenticator)
  • File systems that aren’t case-sensitive
  • Human-readable codes

7. Base16 (Hex) Encoding#

Base16 is essentially hexadecimal encoding.

Encode/Decode Hex#

import base64
text = "Hello"
# Encode to hex
hex_encoded = base64.b16encode(text.encode()).decode()
print(f"Hex: {hex_encoded}") # 48656C6C6F
# Decode from hex
decoded = base64.b16decode(hex_encoded).decode()
print(f"Decoded: {decoded}") # Hello

Alternative: Built-in hex()#

# Using bytes method
text = "Hello"
# Encode
hex_str = text.encode().hex()
print(hex_str) # 48656c6c6f
# Decode
decoded = bytes.fromhex(hex_str).decode()
print(decoded) # Hello

8. Base85 Encoding#

Base85 is more efficient than Base64 (only ~25% size increase vs ~33%).

ASCII85 Encoding#

import base64
text = "Hello, World!"
# Encode
encoded = base64.a85encode(text.encode()).decode()
print(f"ASCII85: {encoded}")
# Decode
decoded = base64.a85decode(encoded).decode()
print(f"Decoded: {decoded}")

Base85 Encoding#

import base64
text = "Hello, World!"
# Encode
encoded = base64.b85encode(text.encode()).decode()
print(f"Base85: {encoded}")
# Decode
decoded = base64.b85decode(encoded).decode()
print(f"Decoded: {decoded}")

Comparison#

EncodingSize IncreaseCharacters
Base64~33%64
Base85~25%85
Base32~60%32
Base16100%16

9. Encoding Files#

Encode File to Base64#

import base64
def encode_file(filepath):
"""Read file and return Base64 encoded string"""
with open(filepath, "rb") as f:
data = f.read()
encoded = base64.b64encode(data).decode()
return encoded
# Usage
encoded_content = encode_file("document.pdf")
print(encoded_content[:100]) # First 100 chars
# Save encoded to file
with open("document.b64", "w") as f:
f.write(encoded_content)

Decode Base64 to File#

import base64
def decode_file(encoded_string, output_path):
"""Decode Base64 string and save to file"""
decoded = base64.b64decode(encoded_string)
with open(output_path, "wb") as f:
f.write(decoded)
# Usage
with open("document.b64", "r") as f:
encoded_content = f.read()
decode_file(encoded_content, "restored_document.pdf")

Encode Large Files (Streaming)#

import base64
def encode_file_streaming(input_path, output_path):
"""Encode large file in chunks"""
with open(input_path, "rb") as fin:
with open(output_path, "wb") as fout:
while True:
# Read in chunks of 57 bytes (produces 76 Base64 chars)
chunk = fin.read(57)
if not chunk:
break
encoded = base64.b64encode(chunk)
fout.write(encoded)
fout.write(b"\n") # Add newline for readability
encode_file_streaming("large_file.zip", "large_file.b64")

10. Encoding Images#

Encode Image to Base64#

import base64
def image_to_base64(image_path):
"""Convert image to Base64 string"""
with open(image_path, "rb") as f:
data = f.read()
return base64.b64encode(data).decode()
# Usage
image_b64 = image_to_base64("photo.jpg")
print(f"Length: {len(image_b64)} characters")
print(f"Preview: {image_b64[:50]}...")

Decode Base64 to Image#

import base64
def base64_to_image(b64_string, output_path):
"""Convert Base64 string back to image"""
data = base64.b64decode(b64_string)
with open(output_path, "wb") as f:
f.write(data)
# Usage
base64_to_image(image_b64, "restored_photo.jpg")

With PIL/Pillow#

import base64
from PIL import Image
import io
# Image to Base64
def pil_to_base64(image):
buffer = io.BytesIO()
image.save(buffer, format="PNG")
return base64.b64encode(buffer.getvalue()).decode()
# Base64 to Image
def base64_to_pil(b64_string):
data = base64.b64decode(b64_string)
return Image.open(io.BytesIO(data))
# Usage
img = Image.open("photo.png")
b64 = pil_to_base64(img)
restored_img = base64_to_pil(b64)
restored_img.show()

11. Data URLs#

Data URLs embed data directly in HTML/CSS.

Format#

data:[<mediatype>][;base64],<data>

Create Image Data URL#

import base64
def image_to_data_url(image_path):
"""Create data URL from image"""
# Determine MIME type
extension = image_path.split(".")[-1].lower()
mime_types = {
"jpg": "image/jpeg",
"jpeg": "image/jpeg",
"png": "image/png",
"gif": "image/gif",
"svg": "image/svg+xml",
"webp": "image/webp"
}
mime_type = mime_types.get(extension, "application/octet-stream")
# Encode image
with open(image_path, "rb") as f:
data = base64.b64encode(f.read()).decode()
return f"data:{mime_type};base64,{data}"
# Usage
data_url = image_to_data_url("logo.png")
print(data_url)
# Use in HTML
html = f'<img src="{data_url}" alt="Logo">'

Common Data URL Types#

# Text
text_url = f"data:text/plain;base64,{base64.b64encode(b'Hello').decode()}"
# HTML
html_content = "<h1>Hello</h1>"
html_url = f"data:text/html;base64,{base64.b64encode(html_content.encode()).decode()}"
# JSON
import json
json_data = {"name": "Ahmed", "age": 25}
json_url = f"data:application/json;base64,{base64.b64encode(json.dumps(json_data).encode()).decode()}"
# PDF
with open("doc.pdf", "rb") as f:
pdf_url = f"data:application/pdf;base64,{base64.b64encode(f.read()).decode()}"

12. Working with JSON#

Encode JSON Data#

import base64
import json
# Data to encode
data = {
"name": "Ahmed",
"age": 25,
"skills": ["Python", "Hacking"],
"active": True
}
# Convert to JSON string, then Base64
json_string = json.dumps(data)
encoded = base64.b64encode(json_string.encode()).decode()
print(f"JSON: {json_string}")
print(f"Base64: {encoded}")

Decode JSON Data#

import base64
import json
encoded = "eyJuYW1lIjogIkFobWVkIiwgImFnZSI6IDI1fQ=="
# Decode Base64, then parse JSON
json_string = base64.b64decode(encoded).decode()
data = json.loads(json_string)
print(f"Name: {data['name']}")
print(f"Age: {data['age']}")

Nested Encoding#

import base64
import json
# Sometimes APIs use Base64-encoded JSON in JSON
payload = {
"type": "message",
"data": base64.b64encode(json.dumps({
"text": "Hello",
"timestamp": 1234567890
}).encode()).decode()
}
# To read it:
inner_data = json.loads(base64.b64decode(payload["data"]).decode())
print(inner_data) # {'text': 'Hello', 'timestamp': 1234567890}

13. Security Considerations#

⚠️ Base64 is NOT Encryption!#

import base64
# This is NOT secure!
password = "secret123"
encoded = base64.b64encode(password.encode()).decode()
print(f"Encoded: {encoded}") # c2VjcmV0MTIz
# Anyone can decode it!
decoded = base64.b64decode(encoded).decode()
print(f"Decoded: {decoded}") # secret123

When to Use#

✅ Use For❌ Don’t Use For
Data transportPassword storage
Embedding dataEncryption
Text-safe encodingHiding secrets
Binary in textSecurity

Proper Encryption Example#

import base64
from cryptography.fernet import Fernet # pip install cryptography
# Generate key (store this securely!)
key = Fernet.generate_key()
cipher = Fernet(key)
# Encrypt
message = "Secret message"
encrypted = cipher.encrypt(message.encode())
print(f"Encrypted: {encrypted}")
# Decrypt
decrypted = cipher.decrypt(encrypted).decode()
print(f"Decrypted: {decrypted}")

14. Common Use Cases#

HTTP Basic Authentication#

import base64
import requests
def basic_auth(username, password):
"""Create Basic Auth header"""
credentials = f"{username}:{password}"
encoded = base64.b64encode(credentials.encode()).decode()
return f"Basic {encoded}"
# Usage
headers = {
"Authorization": basic_auth("admin", "secret123")
}
# Makes: Authorization: Basic YWRtaW46c2VjcmV0MTIz
response = requests.get("https://api.example.com", headers=headers)

Email Attachments (MIME)#

import base64
from email.mime.base import MIMEBase
from email import encoders
def create_attachment(filepath):
"""Create email attachment"""
with open(filepath, "rb") as f:
data = f.read()
# Encode for email
encoded = base64.b64encode(data).decode()
# Split into lines of 76 characters (MIME standard)
lines = [encoded[i:i+76] for i in range(0, len(encoded), 76)]
return "\n".join(lines)
attachment_data = create_attachment("document.pdf")

JWT Tokens (Without Signature Verification)#

import base64
import json
def decode_jwt_payload(token):
"""Extract payload from JWT (don't use for security!)"""
parts = token.split(".")
if len(parts) != 3:
raise ValueError("Invalid JWT format")
# Payload is the second part (with padding fix)
payload_b64 = parts[1]
# Add padding if needed
padding = 4 - len(payload_b64) % 4
if padding != 4:
payload_b64 += "=" * padding
payload_json = base64.urlsafe_b64decode(payload_b64).decode()
return json.loads(payload_json)
# Example JWT
token = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiQWhtZWQiLCJyb2xlIjoiYWRtaW4ifQ.signature"
payload = decode_jwt_payload(token)
print(payload) # {'name': 'Ahmed', 'role': 'admin'}

Obfuscation (Not Security!)#

import base64
def simple_obfuscate(text, layers=3):
"""Multiple Base64 encoding layers (NOT SECURE!)"""
result = text.encode()
for _ in range(layers):
result = base64.b64encode(result)
return result.decode()
def simple_deobfuscate(encoded, layers=3):
"""Reverse multiple Base64 encoding"""
result = encoded.encode()
for _ in range(layers):
result = base64.b64decode(result)
return result.decode()
# Usage
original = "Secret Message"
obfuscated = simple_obfuscate(original)
print(f"Obfuscated: {obfuscated}")
restored = simple_deobfuscate(obfuscated)
print(f"Restored: {restored}")

15. Practical Projects#

Project 1: Image to HTML Converter#

import base64
import os
def create_html_with_images(folder_path, output_html):
"""Create HTML page with embedded images"""
html = """<!DOCTYPE html>
<html>
<head>
<title>Image Gallery</title>
<style>
body { font-family: Arial; padding: 20px; background: #222; }
.gallery { display: flex; flex-wrap: wrap; gap: 10px; }
.gallery img { max-width: 300px; border-radius: 10px; }
</style>
</head>
<body>
<h1 style="color: white;">Image Gallery</h1>
<div class="gallery">
"""
for filename in os.listdir(folder_path):
if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif')):
filepath = os.path.join(folder_path, filename)
# Determine MIME type
ext = filename.split('.')[-1].lower()
mime = f"image/{'jpeg' if ext == 'jpg' else ext}"
# Encode image
with open(filepath, "rb") as f:
b64 = base64.b64encode(f.read()).decode()
html += f' <img src="data:{mime};base64,{b64}" alt="{filename}">\n'
html += """ </div>
</body>
</html>"""
with open(output_html, "w") as f:
f.write(html)
print(f"Created: {output_html}")
# Usage
# create_html_with_images("./images", "gallery.html")

Project 2: Base64 Encoder/Decoder CLI#

import base64
import argparse
import sys
def main():
parser = argparse.ArgumentParser(description="Base64 Encoder/Decoder")
parser.add_argument("action", choices=["encode", "decode"], help="Action to perform")
parser.add_argument("-t", "--text", help="Text to encode/decode")
parser.add_argument("-f", "--file", help="File to encode/decode")
parser.add_argument("-o", "--output", help="Output file")
parser.add_argument("-u", "--urlsafe", action="store_true", help="Use URL-safe Base64")
args = parser.parse_args()
# Get input data
if args.text:
data = args.text.encode() if args.action == "encode" else args.text
elif args.file:
mode = "rb" if args.action == "encode" else "r"
with open(args.file, mode) as f:
data = f.read() if args.action == "encode" else f.read()
else:
print("Provide --text or --file")
sys.exit(1)
# Process
if args.action == "encode":
if args.urlsafe:
result = base64.urlsafe_b64encode(data).decode()
else:
result = base64.b64encode(data).decode()
else:
if args.urlsafe:
result = base64.urlsafe_b64decode(data)
else:
result = base64.b64decode(data)
if isinstance(result, bytes):
result = result.decode()
# Output
if args.output:
mode = "w" if isinstance(result, str) else "wb"
with open(args.output, mode) as f:
f.write(result)
print(f"Saved to: {args.output}")
else:
print(result)
if __name__ == "__main__":
main()
# Usage:
# python base64_tool.py encode -t "Hello World"
# python base64_tool.py decode -t "SGVsbG8gV29ybGQ="
# python base64_tool.py encode -f image.png -o image.b64
# python base64_tool.py decode -f image.b64 -o restored.png

Project 3: Simple Data Steganography#

import base64
def hide_in_spaces(cover_text, secret_message):
"""Hide message in whitespace (tabs vs spaces)"""
# Encode secret to binary
secret_b64 = base64.b64encode(secret_message.encode()).decode()
binary = ''.join(format(ord(c), '08b') for c in secret_b64)
# Add length header
length_bin = format(len(binary), '016b')
binary = length_bin + binary
# Replace spaces based on binary
result = []
bin_index = 0
for char in cover_text:
if char == ' ' and bin_index < len(binary):
# 0 = space, 1 = tab
result.append('\t' if binary[bin_index] == '1' else ' ')
bin_index += 1
else:
result.append(char)
return ''.join(result)
def extract_from_spaces(stego_text):
"""Extract hidden message from whitespace"""
# Extract binary from spaces/tabs
binary = ''
for char in stego_text:
if char in ' \t':
binary += '1' if char == '\t' else '0'
# Get length
length = int(binary[:16], 2)
data_binary = binary[16:16+length]
# Convert binary to characters
chars = [chr(int(data_binary[i:i+8], 2)) for i in range(0, len(data_binary), 8)]
secret_b64 = ''.join(chars)
# Decode Base64
return base64.b64decode(secret_b64).decode()
# Usage
cover = "This is a normal looking text with many spaces for hiding data"
secret = "Secret!"
stego = hide_in_spaces(cover, secret)
print(f"Stego text: {repr(stego)}")
extracted = extract_from_spaces(stego)
print(f"Extracted: {extracted}")

Project 4: QR Code Generator with Base64#

import base64
import qrcode # pip install qrcode[pil]
import io
def data_to_qr(data, output_path="qr.png"):
"""Convert data to QR code"""
# Encode data
encoded = base64.b64encode(data.encode()).decode()
# Generate QR code
qr = qrcode.QRCode(version=1, box_size=10, border=5)
qr.add_data(encoded)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
img.save(output_path)
print(f"QR code saved: {output_path}")
return output_path
def qr_to_data(qr_image_path):
"""Read QR code and decode data"""
from pyzbar.pyzbar import decode # pip install pyzbar
from PIL import Image
img = Image.open(qr_image_path)
decoded = decode(img)
if decoded:
encoded = decoded[0].data.decode()
return base64.b64decode(encoded).decode()
return None
# Usage
# data_to_qr("Secret message in QR code!")
# message = qr_to_data("qr.png")
# print(message)

🎯 Quick Reference#

FunctionDescription
b64encode(data)Encode to Base64
b64decode(data)Decode from Base64
urlsafe_b64encode()URL-safe encoding
urlsafe_b64decode()URL-safe decoding
b32encode()Base32 encoding
b32decode()Base32 decoding
b16encode()Hex encoding
b16decode()Hex decoding
a85encode()ASCII85 encoding
b85encode()Base85 encoding

🎉 You’ve Mastered Base64!#

Now you can:

  • Encode/decode any data
  • Work with files and images
  • Create data URLs
  • Understand common use cases
  • Build practical tools

Remember: Base64 is encoding, NOT encryption!


Created by cat0x01 🥷🏻