Base64 Encoding/Decoding: When and How to Use It

By Taylor Feb 22, 2026 11 min read

Base64 encoding is everywhere in modern web development, yet most developers use it without fully understanding what it does or why it exists. It shows up in data URIs, API authentication headers, email attachments, JWT tokens, and embedded images. Understanding Base64 means understanding a fundamental building block of how data moves across the internet.

This guide explains what Base64 encoding is at the byte level, walks through the encoding algorithm step by step, covers every common use case with code examples in JavaScript and Python, and explains when you should -- and should not -- use it.

Table of Contents
  1. What Is Base64?
  2. How Base64 Encoding Works
  3. The Base64 Alphabet
  4. Padding with = Signs
  5. Base64 Variants (Standard vs. URL-safe)
  6. Common Use Cases
  7. Base64 in JavaScript
  8. Base64 in Python
  9. Base64 on the Command Line
  10. Data URIs Explained
  11. Size Overhead and Performance
  12. When NOT to Use Base64

1. What Is Base64?

Base64 is a binary-to-text encoding scheme that represents binary data as a string of printable ASCII characters. It takes arbitrary binary data (bytes with values 0-255) and converts it to a string using only 64 characters that are safe to transmit through any text-based system.

The name "Base64" comes from the fact that it uses a 64-character alphabet. Compare this to other number systems: Base10 (decimal) uses 10 digits, Base16 (hexadecimal) uses 16 characters, and Base64 uses 64 characters.

The key insight: Base64 is not encryption. It does not protect or hide data. It simply re-encodes data into a format that is safe to transmit through channels that might otherwise corrupt binary data (like email, URLs, JSON strings, or HTML attributes).

2. How Base64 Encoding Works

The encoding process converts every 3 bytes (24 bits) of input into 4 Base64 characters (6 bits each). Here is the process step by step.

Input text Hi!
ASCII bytes 72   105   33
Binary 01001000   01101001   00100001
6-bit groups 010010   000110   100100   100001
Index values 18   6   36   33
Base64 chars SGkh

The algorithm works as follows:

  1. Convert input to bytes. For text, use the UTF-8 encoding. For binary files, the bytes are already there.
  2. Group bytes into 3-byte chunks. Each chunk contains 24 bits of data.
  3. Split each 24-bit chunk into four 6-bit groups. 6 bits can represent values 0-63, which maps perfectly to our 64-character alphabet.
  4. Map each 6-bit value to a Base64 character using the alphabet lookup table.
  5. Handle padding if the input length is not divisible by 3.

3. The Base64 Alphabet

The standard Base64 alphabet (RFC 4648) uses these 64 characters:

Index  Char    Index  Char    Index  Char    Index  Char
  0     A       16     Q       32     g       48     w
  1     B       17     R       33     h       49     x
  2     C       18     S       34     i       50     y
  3     D       19     T       35     j       51     z
  4     E       20     U       36     k       52     0
  5     F       21     V       37     l       53     1
  6     G       22     W       38     m       54     2
  7     H       23     X       39     n       55     3
  8     I       24     Y       40     o       56     4
  9     J       25     Z       41     p       57     5
 10     K       26     a       42     q       58     6
 11     L       27     b       43     r       59     7
 12     M       28     c       44     s       60     8
 13     N       29     d       45     t       61     9
 14     O       30     e       46     u       62     +
 15     P       31     f       47     v       63     /

Characters 62 and 63 (+ and /) are the ones that differ in Base64url encoding, where they are replaced with - and _ respectively. This is important because + and / have special meaning in URLs.

4. Padding with = Signs

When the input length is not a multiple of 3, the last chunk has fewer than 3 bytes. Base64 pads the output with = characters to make it a multiple of 4.

Input: "A"   (1 byte)   -> QQ==   (2 padding chars)
Input: "AB"  (2 bytes)  -> QUI=   (1 padding char)
Input: "ABC" (3 bytes)  -> QUJD   (no padding)

The padding tells the decoder exactly how many bytes of actual data the last group contains. Without padding, the decoder could not distinguish between inputs that happened to end with zero bits and genuine trailing zeros.

Note: Some implementations (especially Base64url used in JWTs) omit the padding. The decoder can infer the padding from the string length: if length % 4 == 2, add "=="; if length % 4 == 3, add "=".

5. Base64 Variants

There are several Base64 variants, each designed for a specific context.

Standard vs. URL-safe comparison
Standard: "Hello+World/Test=="
URL-safe: "Hello-World_Test"

The URL-safe variant is critical for JWTs and URL parameters
because + and / have special meanings in URLs.

6. Common Use Cases

Data URIs (Embedding Images in HTML/CSS)

Data URIs let you embed small images directly in your HTML or CSS, eliminating an HTTP request. The format is data:[mediatype];base64,[data].

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUh..." alt="Embedded image">

.icon {
  background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxu...');
}

HTTP Basic Authentication

The HTTP Authorization header uses Base64 to encode the username:password pair.

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

// "dXNlcm5hbWU6cGFzc3dvcmQ=" decodes to "username:password"

JWT Tokens

JWTs use Base64url encoding for the header and payload. See our JWT Explained guide for the full breakdown.

Email Attachments (MIME)

Email was designed for text, not binary data. MIME encoding uses Base64 to safely embed binary attachments in text-based email messages.

Embedding Binary Data in JSON

JSON does not support binary data directly. To include an image, PDF, or any binary file in a JSON payload, Base64-encode it as a string.

{
  "filename": "report.pdf",
  "content": "JVBERi0xLjcKMSAwIG9iago8PCAvVHlwZS...",
  "encoding": "base64"
}

Storing Binary in Text-Only Databases

Some databases and configuration systems (like environment variables) only support text. Base64 lets you store cryptographic keys, certificates, and small binary blobs as text strings.

Encode and Decode Instantly

Base64 Forge handles text, files, and images. Encode, decode, generate data URIs, and convert URL-encoded strings -- all in your browser.

Open Base64 Forge

7. Base64 in JavaScript

Browser: Encoding and decoding strings
// Encode
const encoded = btoa('Hello, World!');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="

// Decode
const decoded = atob('SGVsbG8sIFdvcmxkIQ==');
console.log(decoded); // "Hello, World!"
Browser: Handling Unicode (important!)
// btoa() only handles Latin1 characters. For Unicode:

// Encode Unicode string
function encodeUnicode(str) {
  return btoa(encodeURIComponent(str).replace(
    /%([0-9A-F]{2})/g,
    (_, p1) => String.fromCharCode('0x' + p1)
  ));
}

// Decode Unicode string
function decodeUnicode(str) {
  return decodeURIComponent(atob(str).split('').map(
    c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
  ).join(''));
}

// Modern alternative (TextEncoder/TextDecoder)
function toBase64(str) {
  return btoa(String.fromCharCode(...new TextEncoder().encode(str)));
}

function fromBase64(b64) {
  return new TextDecoder().decode(
    Uint8Array.from(atob(b64), c => c.charCodeAt(0))
  );
}
Node.js: Using Buffer
// Encode
const encoded = Buffer.from('Hello, World!').toString('base64');

// Decode
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');

// Encode a file
const fs = require('fs');
const fileBase64 = fs.readFileSync('image.png').toString('base64');

// Decode to file
fs.writeFileSync('output.png', Buffer.from(fileBase64, 'base64'));
JavaScript: File to Base64 (browser)
function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result.split(',')[1]);
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// Usage with file input
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async (e) => {
  const base64 = await fileToBase64(e.target.files[0]);
  console.log(base64); // The Base64 string without the data URI prefix
});

8. Base64 in Python

Basic encoding and decoding
import base64

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

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

# Unicode strings (encode first to bytes)
text = "Hello, World!"
encoded = base64.b64encode(text.encode('utf-8')).decode('ascii')
URL-safe Base64
import base64

# URL-safe encoding (uses - and _ instead of + and /)
encoded = base64.urlsafe_b64encode(b'Hello+World/Test').decode('ascii')
print(encoded)  # Uses - and _ for URL safety

# URL-safe decoding
decoded = base64.urlsafe_b64decode(encoded).decode('utf-8')
File encoding
import base64

# Encode a file
with open('image.png', 'rb') as f:
    encoded = base64.b64encode(f.read()).decode('ascii')

# Decode to file
with open('output.png', 'wb') as f:
    f.write(base64.b64decode(encoded))

# Generate a data URI
with open('image.png', 'rb') as f:
    data_uri = f'data:image/png;base64,{base64.b64encode(f.read()).decode("ascii")}'

9. Base64 on the Command Line

Linux / macOS
# Encode a string
echo -n "Hello, World!" | base64
# Output: SGVsbG8sIFdvcmxkIQ==

# Decode a string
echo "SGVsbG8sIFdvcmxkIQ==" | base64 --decode
# Output: Hello, World!

# Encode a file
base64 image.png > image.b64

# Decode a file
base64 --decode image.b64 > image.png

# Encode and copy to clipboard (macOS)
echo -n "secret" | base64 | pbcopy
Windows (PowerShell)
# Encode
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("Hello"))

# Decode
[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("SGVsbG8="))

10. Data URIs Explained

A Data URI is a way to embed file content directly in HTML, CSS, or JavaScript, eliminating a separate HTTP request. The format is:

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

Common media types used with data URIs:

When to use data URIs: For small assets under 5KB (icons, small images, fonts with few glyphs). The HTTP request overhead often exceeds the size penalty of Base64 for tiny files.

When NOT to use data URIs: For anything over 10KB. Base64 increases size by 33%, and data URIs cannot be cached separately from the HTML/CSS file that contains them.

11. Size Overhead and Performance

Base64 encoding always increases data size because it represents 3 bytes of data as 4 ASCII characters. The exact overhead is predictable:

Output size = ceil(input_size / 3) * 4

Examples:
  1 byte  input ->  4 chars output  (300% increase)
  3 bytes input ->  4 chars output  (33% increase)
  1 KB    input ->  1.33 KB output  (33% increase)
  1 MB    input ->  1.33 MB output  (33% increase)

The overhead converges to exactly 33.33% for any reasonably sized input. This means a 100KB image becomes 133KB when Base64-encoded. With gzip compression applied on top, the overhead drops to roughly 2-5% because the Base64 alphabet is highly compressible.

In terms of CPU performance, Base64 encoding and decoding are extremely fast operations. They involve only bitwise operations and table lookups -- no complex math. Encoding a 1MB file takes under 1 millisecond on any modern device.

12. When NOT to Use Base64

Base64 is a tool, not a solution to everything. Here are cases where you should avoid it.

Try Base64 Right Now

Base64 Forge supports text encoding, file encoding, data URI generation, and URL encoding. Drag and drop any file to see its Base64 representation instantly.

Open Base64 Forge