DEV Community

楊東霖
楊東霖

Posted on • Originally published at devplaybook.cc

Base64 Encode Decode Explained: Developer Guide with Real Use Cases

Base64 is one of the most misunderstood tools in a developer's toolkit. It looks like encryption but provides zero security. It bloats data by 33% yet appears everywhere from JWTs to email attachments. Developers reach for it instinctively, sometimes when they should not.

This guide explains exactly what Base64 is, how it works, where you should use it, and where you absolutely should not. For quick encoding tasks, use our free Base64 Encoder/Decoder to convert text and binary data instantly.

What Is Base64?

Base64 is an encoding scheme that converts arbitrary binary data into a string of 64 printable ASCII characters. Those characters are: A-Z (26), a-z (26), 0-9 (10), + and / (2), with = used for padding — totaling 64.

The name "Base64" comes from the 64-character alphabet, the same way "Base10" describes our decimal system.

Key fact: Base64 is an encoding, not encryption. The original data can be decoded by anyone. It provides no confidentiality.

How Base64 Encoding Works

Base64 works in 3-byte chunks. Every 3 bytes of input (24 bits) become 4 Base64 characters (6 bits each):

Input:    M        a        n
Binary:   01001101 01100001 01101110
Groups:   010011 010110 000101 101110
Base64:   T      W      F      u    → "TWFu"
Enter fullscreen mode Exit fullscreen mode

When input length is not divisible by 3, padding characters (=) are added:

"Ma" → 2 bytes → 3 Base64 chars + 1 padding → "TWE="
"M"  → 1 byte  → 2 Base64 chars + 2 padding → "TQ=="
Enter fullscreen mode Exit fullscreen mode

Size overhead: Every 3 bytes become 4 characters, so Base64 output is always 4/3 (~33%) larger than the input.

Base64 vs Base64URL

Standard Base64 uses + and / characters, which have special meaning in URLs. Base64URL replaces these:

Standard Base64 Base64URL
+ -
/ _
= (padding) (often omitted)

JWTs use Base64URL. URLs and file names require Base64URL. When you see a token with - and _ instead of + and /, it's Base64URL-encoded.

How to Encode and Decode in JavaScript

Browser

// Encode string to Base64
const encoded = btoa('Hello, World!');
console.log(encoded); // 'SGVsbG8sIFdvcmxkIQ=='

// Decode Base64 to string
const decoded = atob('SGVsbG8sIFdvcmxkIQ==');
console.log(decoded); // 'Hello, World!'

// Unicode strings (btoa only handles Latin-1)
const encodeUnicode = (str) =>
  btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
    (_, p1) => String.fromCharCode('0x' + p1)));

const decodeUnicode = (str) =>
  decodeURIComponent(atob(str).split('').map(
    c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join(''));

console.log(encodeUnicode('日本語')); // '5pel5pys6Kqe'
Enter fullscreen mode Exit fullscreen mode

Node.js

// Encode
const encoded = Buffer.from('Hello, World!').toString('base64');
console.log(encoded); // 'SGVsbG8sIFdvcmxkIQ=='

// Decode
const decoded = Buffer.from('SGVsbG8sIFdvcmxkIQ==', 'base64').toString('utf8');
console.log(decoded); // 'Hello, World!'

// Encode a file
const fs = require('fs');
const fileBuffer = fs.readFileSync('./image.png');
const base64Image = fileBuffer.toString('base64');
console.log(`data:image/png;base64,${base64Image}`);

// Base64URL (for JWTs, URLs)
const base64url = (str) => Buffer.from(str).toString('base64url');
const fromBase64url = (str) => Buffer.from(str, 'base64url').toString('utf8');
Enter fullscreen mode Exit fullscreen mode

How to Encode and Decode in Python

import base64

# Encode string
text = "Hello, World!"
encoded = base64.b64encode(text.encode('utf-8'))
print(encoded)           # b'SGVsbG8sIFdvcmxkIQ=='
print(encoded.decode())  # 'SGVsbG8sIFdvcmxkIQ=='

# Decode string
decoded = base64.b64decode('SGVsbG8sIFdvcmxkIQ==').decode('utf-8')
print(decoded)  # 'Hello, World!'

# Encode binary file
with open('image.png', 'rb') as f:
    image_data = f.read()
encoded_image = base64.b64encode(image_data).decode()
data_uri = f"data:image/png;base64,{encoded_image}"

# Base64URL (for JWTs, URL-safe use)
encoded_url = base64.urlsafe_b64encode(text.encode('utf-8'))
decoded_url = base64.urlsafe_b64decode(encoded_url).decode('utf-8')
Enter fullscreen mode Exit fullscreen mode

Real-World Use Cases

1. Data URIs in HTML/CSS

Embed small images directly in HTML or CSS without extra HTTP requests:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==" alt="1x1 red pixel">
Enter fullscreen mode Exit fullscreen mode
.icon {
  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==");
}
Enter fullscreen mode Exit fullscreen mode

Best for: Small icons, loading spinners, critical above-the-fold images. Avoid for large images — the 33% size increase hurts more than the request savings.

2. HTTP Basic Authentication

The Authorization: Basic header encodes username:password as Base64:

const credentials = btoa('alice:supersecret123');
fetch('https://api.example.com/data', {
  headers: {
    'Authorization': `Basic ${credentials}`
  }
});
Enter fullscreen mode Exit fullscreen mode

Important: Basic Auth over plain HTTP is insecure. Always use HTTPS.

3. JWT Tokens

All three JWT parts (header, payload, signature) are Base64URL-encoded:

const [header, payload] = token.split('.');
const decodedPayload = JSON.parse(atob(
  payload.replace(/-/g, '+').replace(/_/g, '/')
));
Enter fullscreen mode Exit fullscreen mode

4. Email Attachments (MIME)

Email protocols (SMTP) were designed for ASCII text. Attachments are Base64-encoded in the MIME envelope:

Content-Type: application/pdf
Content-Transfer-Encoding: base64

JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFIKL0ZpbHRlci9GbGF0ZURlY29k...
Enter fullscreen mode Exit fullscreen mode

5. Storing Binary Data in JSON/XML

APIs that return binary data (like AI-generated images) often Base64-encode it:

import anthropic
import base64

client = anthropic.Anthropic()
response = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "describe this image",
               "images": [{"type": "base64", "media_type": "image/jpeg",
                           "data": base64.b64encode(image_bytes).decode()}]}]
)
Enter fullscreen mode Exit fullscreen mode

6. Environment Variables and Config

Storing binary secrets (private keys, certificates) in environment variables:

# Encode a PEM key for use in an env var
export PRIVATE_KEY=$(base64 -w 0 private_key.pem)

# Decode it in your app
import base64, os
key = base64.b64decode(os.environ['PRIVATE_KEY'])
Enter fullscreen mode Exit fullscreen mode

When NOT to Use Base64

Don't use it for security

Base64 is trivially reversible. Using it to "hide" passwords or sensitive data gives false security:

# THIS IS NOT SECURITY
encoded_password = base64.b64encode(b"my_password")  # Anyone can decode this
Enter fullscreen mode Exit fullscreen mode

Don't use it for large files

A 10MB image becomes ~13.3MB when Base64-encoded. For large binary files, use multipart/form-data upload instead.

Don't use it when binary transfer is already supported

REST APIs with Content-Type: application/octet-stream can send binary data directly. Base64 is only needed when the transport channel is text-only.

Quick Reference

Task JavaScript Python
Encode string btoa(str) base64.b64encode(s.encode())
Decode string atob(str) base64.b64decode(s).decode()
Encode Buffer/bytes buf.toString('base64') already bytes
Base64URL encode buf.toString('base64url') base64.urlsafe_b64encode(s)
Data URI prefix data:image/png;base64, same

Test your encoding interactively with the Base64 Encoder/Decoder — encode text, decode tokens, or convert files right in your browser.


Level Up Your Dev Workflow

Found this useful? Explore DevPlaybook — cheat sheets, tool comparisons, and hands-on guides for modern developers.

🛒 Get the DevToolkit Starter Kit on Gumroad — 40+ browser-based dev tools, source code + deployment guide included.

Top comments (0)