Base64 is a binary-to-text encoding scheme that converts binary data into a string of printable ASCII characters. The name "Base64" comes from the fact that the encoding uses a set of exactly 64 characters to represent data: the uppercase letters A-Z (26), lowercase letters a-z (26), digits 0-9 (10), and two additional characters, typically + and / (2). A 65th character, =, is used for padding.
The need for Base64 arose from a fundamental problem in computing: many communication protocols and storage formats were designed to handle text, not arbitrary binary data. Email, for instance, was originally built to transmit 7-bit ASCII text. Attempting to send binary data like images, executables, or compressed files through these text-only channels would corrupt the data, because certain byte values have special meanings in text protocols (like null bytes, line-feed characters, or values above 127).
Base64 solves this by transforming any sequence of bytes -- regardless of content -- into a string composed entirely of safe, printable characters. The encoded string can be transmitted through any text-based channel without risk of corruption or misinterpretation. At the receiving end, the Base64 string is decoded back into the original binary data, byte-for-byte identical to the input.
Base64 encoding is defined in RFC 4648, which specifies both the standard Base64 alphabet and the URL-safe variant (Base64URL). Earlier specifications include RFC 2045 (MIME) and RFC 3548, both of which RFC 4648 supersedes.
Today, Base64 is ubiquitous in web development, APIs, authentication protocols, and data interchange formats. Every developer encounters it regularly, whether in JWT tokens, data URIs, email attachments, HTTP headers, Kubernetes secrets, or PEM-encoded certificates.
Understanding the Base64 algorithm is straightforward once you grasp its core idea: convert every 3 bytes (24 bits) of input into 4 characters (6 bits each) of output. Here is the step-by-step process.
The standard Base64 alphabet maps each 6-bit value (0-63) to a specific character:
Value Char Value Char Value Char Value 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 /
Let us walk through encoding the string Man (three ASCII characters: M=77, a=97, n=110):
Step 1: Convert to binary. Each character becomes its 8-bit binary representation:
M = 77 = 01001101
a = 97 = 01100001
n = 110 = 01101110
Step 2: Concatenate into a 24-bit stream.
01001101 01100001 01101110
Step 3: Split into 6-bit groups.
010011 010110 000101 101110
Step 4: Convert each 6-bit group to its decimal value and look up the Base64 character.
010011 = 19 = T
010110 = 22 = W
000101 = 5 = F
101110 = 46 = u
The result: Man encodes to TWFu. Three input bytes become four output characters.
Base64 processes input in groups of 3 bytes. When the input length is not a multiple of 3, padding is required to make the output length a multiple of 4 characters.
One remaining byte (needs 2 padding characters): Consider encoding M (just one byte, 77):
M = 01001101
Split into 6-bit groups (pad remaining bits with zeros):
010011 010000
19 = T
16 = Q
Result: TQ==
The two = signs indicate that only 1 byte of the final 3-byte group was present.
Two remaining bytes (needs 1 padding character): Consider encoding Ma (two bytes, 77 and 97):
M = 01001101
a = 01100001
Concatenated: 01001101 01100001
Split into 6-bit groups (pad with zeros):
010011 010110 000100
19 = T
22 = W
4 = E
Result: TWE=
One = sign indicates that 2 bytes of the final 3-byte group were present. This padding mechanism allows the decoder to know exactly how many original bytes to reconstruct.
Decoding is the reverse: take every 4 Base64 characters, convert each to its 6-bit value, concatenate the bits into a 24-bit stream, and split back into three 8-bit bytes. Padding characters are ignored and tell the decoder how many output bytes to produce from the final group.
Because every 3 input bytes produce 4 output characters, Base64 encoding increases data size by exactly one-third (33.33%). A 3 KB file becomes 4 KB when encoded. A 1 MB image becomes approximately 1.33 MB. This overhead is an important consideration when deciding whether to use Base64 encoding, especially for large files.
Base64 encoding appears in a surprisingly wide range of technologies. Here are the most common scenarios where developers encounter it.
The original and still most widespread use of Base64 is in email. The MIME (Multipurpose Internet Mail Extensions) standard uses Base64 to encode binary attachments -- images, PDFs, ZIP files -- so they can be transmitted through the text-only SMTP protocol. When you attach a file to an email, your mail client Base64-encodes it and includes it in the message body with a Content-Transfer-Encoding: base64 header.
Data URIs allow you to embed file content directly in HTML or CSS, eliminating the need for separate HTTP requests. They are commonly used for small images, icons, and fonts:
<!-- Embedding a small PNG image directly in HTML -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHx
gljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot">
/* Embedding a font in CSS */
@font-face {
font-family: 'CustomFont';
src: url(data:font/woff2;base64,d09GMgABAAAAAAL...) format('woff2');
}
Data URIs are ideal for small assets (under a few KB) where reducing HTTP requests outweighs the 33% size increase. For larger files, separate HTTP requests with proper caching are more efficient.
HTTP Basic Authentication transmits credentials as a Base64-encoded string in the Authorization header. The username and password are joined with a colon and encoded:
# Encoding credentials
username:password --> Base64 --> dXNlcm5hbWU6cGFzc3dvcmQ=
# The HTTP header
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Critical warning: Base64 encoding provides zero security. The credentials above can be decoded by anyone who intercepts the header. HTTP Basic Authentication must always be used over HTTPS to encrypt the entire request in transit.
JWTs consist of three Base64URL-encoded segments separated by dots: the header, payload, and signature. The header and payload are JSON objects encoded with Base64URL so they can be safely included in HTTP headers and URLs:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. # Header (Base64URL)
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ik # Payload (Base64URL)
pvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c # Signature
Note that JWTs use Base64URL encoding (not standard Base64) because tokens frequently appear in URLs and HTTP headers where +, /, and = characters would cause problems.
Kubernetes stores secret values as Base64-encoded strings in YAML manifests. This is not for security (the data is trivially decodable) but to allow binary data to be stored in YAML, which is a text format:
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: YWRtaW4= # "admin"
password: cDRzc3cwcmQ= # "p4ssw0rd"
Kubernetes also supports stringData for plain-text values that are automatically Base64-encoded when stored.
PEM (Privacy Enhanced Mail) format wraps Base64-encoded DER data between header and footer lines. TLS certificates, private keys, and certificate signing requests all commonly use this format:
-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQsw
CQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQL
...
-----END CERTIFICATE-----
JSON and XML are text-based data interchange formats that cannot natively represent binary data. Base64 encoding is the standard approach for embedding binary content (images, files, encrypted data) within these formats. APIs frequently use Base64 to include file uploads or binary responses in JSON payloads.
Standard Base64 encoding uses + and / as the 62nd and 63rd characters in its alphabet, and = for padding. While these characters are perfectly fine for email and general data storage, they cause problems in URLs and filenames:
+ is interpreted as a space in URL query strings/ is the path separator in URLs= separates keys from values in query parametersBase64URL, defined in RFC 4648 Section 5, addresses this by making two substitutions:
| Character | Standard Base64 | Base64URL |
|---|---|---|
| 62nd character | + | - |
| 63rd character | / | _ |
| Padding | = | Typically omitted |
Base64URL is used in JWTs, OAuth tokens, URL-safe identifiers, and anywhere encoded data appears in URLs or filenames. The two encodings are not interchangeable -- decoding a Base64URL string with a standard Base64 decoder (or vice versa) will produce incorrect results if the input contains any of the substituted characters.
Converting between standard Base64 and Base64URL is simple string replacement:
# Base64 to Base64URL:
# 1. Replace '+' with '-'
# 2. Replace '/' with '_'
# 3. Remove trailing '=' padding
# Base64URL to Base64:
# 1. Replace '-' with '+'
# 2. Replace '_' with '/'
# 3. Add '=' padding to make length a multiple of 4
One of the most practical applications of Base64 is encoding binary files -- images, PDFs, fonts, and other non-text data -- for embedding in text-based formats.
Small images (icons, logos, simple graphics) are commonly embedded as data URIs in HTML and CSS. This eliminates HTTP requests and can improve perceived load time for critical above-the-fold content:
<!-- Inline SVG icon as data URI -->
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTEyIDJMMiA3bDEwIDUgMTAtNS0xMC01eiIvPjwvc3ZnPg==" alt="Icon">
/* Background image in CSS */
.icon {
background-image: url(data:image/png;base64,iVBORw0KGgo...);
}
Base64-encoded images make sense when:
Base64-encoded images are a poor choice when:
You can Base64-encode files from the command line on most operating systems:
# Linux / macOS
base64 image.png > image.b64
cat image.png | base64
# Decode back to binary
base64 -d image.b64 > image_decoded.png # Linux
base64 -D image.b64 > image_decoded.png # macOS
# Windows PowerShell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("image.png"))
[IO.File]::WriteAllBytes("decoded.png", [Convert]::FromBase64String($base64String))
Every major programming language provides built-in Base64 encoding and decoding support. Here are examples in four widely used languages.
JavaScript provides different APIs for Base64 depending on the environment:
// Browser: btoa() and atob() for string encoding/decoding
const encoded = btoa('Hello, World!');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="
const decoded = atob('SGVsbG8sIFdvcmxkIQ==');
console.log(decoded); // "Hello, World!"
// Handle Unicode strings (btoa only supports Latin-1)
function encodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(
/%([0-9A-F]{2})/g,
(_, p1) => String.fromCharCode('0x' + p1)
));
}
function decodeUnicode(str) {
return decodeURIComponent(atob(str).split('').map(
c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
).join(''));
}
// Node.js: Buffer API
const buf = Buffer.from('Hello, World!', 'utf-8');
const base64 = buf.toString('base64');
console.log(base64); // "SGVsbG8sIFdvcmxkIQ=="
const original = Buffer.from(base64, 'base64').toString('utf-8');
console.log(original); // "Hello, World!"
// Node.js: Base64URL encoding
const base64url = buf.toString('base64url');
// File encoding in Node.js
const fs = require('fs');
const fileBase64 = fs.readFileSync('image.png').toString('base64');
const dataUri = `data:image/png;base64,${fileBase64}`;
Python's base64 module provides comprehensive encoding and decoding functions:
import base64
# Basic encoding and decoding
encoded = base64.b64encode(b'Hello, World!')
print(encoded) # b'SGVsbG8sIFdvcmxkIQ=='
decoded = base64.b64decode(b'SGVsbG8sIFdvcmxkIQ==')
print(decoded) # b'Hello, World!'
# String encoding (encode to bytes first)
text = 'Hello, World!'
encoded_str = base64.b64encode(text.encode('utf-8')).decode('ascii')
print(encoded_str) # "SGVsbG8sIFdvcmxkIQ=="
# Base64URL encoding
url_encoded = base64.urlsafe_b64encode(b'subjects?query=1+1')
print(url_encoded) # b'c3ViamVjdHM_cXVlcnk9MSsx'
url_decoded = base64.urlsafe_b64decode(url_encoded)
print(url_decoded) # b'subjects?query=1+1'
# Encoding a file
with open('image.png', 'rb') as f:
file_base64 = base64.b64encode(f.read()).decode('ascii')
# Decoding back to a file
with open('output.png', 'wb') as f:
f.write(base64.b64decode(file_base64))
Go's encoding/base64 package provides standard and URL-safe encoders:
package main
import (
"encoding/base64"
"fmt"
"os"
)
func main() {
// Standard Base64 encoding
data := "Hello, World!"
encoded := base64.StdEncoding.EncodeToString([]byte(data))
fmt.Println(encoded) // "SGVsbG8sIFdvcmxkIQ=="
// Decoding
decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
panic(err)
}
fmt.Println(string(decoded)) // "Hello, World!"
// Base64URL encoding (no padding)
urlEncoded := base64.URLEncoding.WithPadding(base64.NoPadding).
EncodeToString([]byte(data))
fmt.Println(urlEncoded)
// RawStdEncoding: standard Base64 without padding
raw := base64.RawStdEncoding.EncodeToString([]byte(data))
fmt.Println(raw) // "SGVsbG8sIFdvcmxkIQ"
// Encoding a file
fileData, _ := os.ReadFile("image.png")
fileBase64 := base64.StdEncoding.EncodeToString(fileData)
fmt.Println(len(fileBase64))
}
Java 8+ includes the java.util.Base64 class with standard, URL-safe, and MIME encoders:
import java.util.Base64;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Base64Example {
public static void main(String[] args) throws Exception {
// Standard encoding
String data = "Hello, World!";
String encoded = Base64.getEncoder()
.encodeToString(data.getBytes("UTF-8"));
System.out.println(encoded); // "SGVsbG8sIFdvcmxkIQ=="
// Decoding
byte[] decodedBytes = Base64.getDecoder().decode(encoded);
String decoded = new String(decodedBytes, "UTF-8");
System.out.println(decoded); // "Hello, World!"
// URL-safe encoding (no padding)
String urlEncoded = Base64.getUrlEncoder()
.withoutPadding()
.encodeToString(data.getBytes("UTF-8"));
System.out.println(urlEncoded);
// MIME encoding (line breaks every 76 characters)
String mimeEncoded = Base64.getMimeEncoder()
.encodeToString(data.getBytes("UTF-8"));
// Encoding a file
byte[] fileBytes = Files.readAllBytes(Paths.get("image.png"));
String fileBase64 = Base64.getEncoder()
.encodeToString(fileBytes);
}
}
This is perhaps the most important section of this entire guide: Base64 is NOT encryption. This misconception is surprisingly common, even among experienced developers, and it leads to serious security vulnerabilities.
Base64 encoding is a fully reversible, deterministic transformation with no secret key involved. Anyone who sees a Base64 string can decode it instantly using any of thousands of free tools or a single line of code. There is no secret, no password, no key -- the "algorithm" is public and trivial to reverse.
# This is NOT security:
echo "my-secret-password" | base64
# Output: bXktc2VjcmV0LXBhc3N3b3Jk
# Anyone can decode it:
echo "bXktc2VjcmV0LXBhc3N3b3Jk" | base64 -d
# Output: my-secret-password
Here are common security anti-patterns involving Base64:
If your goal is to protect data confidentiality, use proper cryptographic tools:
Base64 can be used alongside encryption -- for example, encrypting data with AES and then Base64-encoding the ciphertext for safe transport in a JSON payload. But the security comes from the encryption, not the encoding.
While Base64 encoding is computationally inexpensive, its impact on data size and transfer efficiency deserves careful consideration in performance-sensitive applications.
The 33% size increase from Base64 encoding is its primary performance cost. Here is how this scales:
| Original Size | Base64 Size | Overhead |
|---|---|---|
| 1 KB | 1.33 KB | +0.33 KB |
| 10 KB | 13.3 KB | +3.3 KB |
| 100 KB | 133 KB | +33 KB |
| 1 MB | 1.33 MB | +0.33 MB |
| 10 MB | 13.3 MB | +3.3 MB |
Base64-encoded images embedded in HTML or CSS have several performance implications:
When Base64-encoded data is served over HTTP with gzip or Brotli compression, the effective size overhead is reduced. Base64 text compresses reasonably well because it uses a limited character set. However, this only helps with transfer size -- the browser still has to decode the full Base64 string.
Base64 encoding and decoding are fast operations -- on modern hardware, encoding throughput exceeds several GB/s. For most applications, the CPU cost of Base64 is negligible. However, in high-throughput systems processing millions of encoding operations per second, it can become measurable. SIMD-optimized implementations are available for performance-critical use cases.
Follow these guidelines to use Base64 encoding effectively and avoid common pitfalls.
Use standard Base64 when the encoded data will be stored or transmitted in a context that handles +, /, and = safely (email, JSON values, database fields). Use Base64URL when the encoded data will appear in URLs, query parameters, filenames, HTTP headers, or tokens like JWTs.
The 33% size overhead makes Base64 unsuitable for large files. For file uploads, use multipart form data. For file storage, use binary-native formats. For serving images on the web, use optimized image formats (WebP, AVIF) served as separate resources with caching headers.
Data URIs are best for small, critical assets -- tiny icons, simple SVGs, or placeholder images. As a rule of thumb, consider using data URIs only for assets under 2-4 KB (before encoding). For anything larger, the caching benefits of separate files outweigh the HTTP request savings.
Base64 operates on bytes, not characters. When encoding text strings, always explicitly specify the character encoding (usually UTF-8) before Base64-encoding. In JavaScript, btoa() only handles Latin-1 characters -- use the TextEncoder API or the Unicode-safe wrapper functions shown earlier for strings containing non-ASCII characters.
Always validate and handle errors when decoding Base64 input, especially from untrusted sources. Invalid characters, incorrect padding, or truncated strings will cause decoding failures. Implement proper error handling rather than letting exceptions propagate:
// JavaScript
function safeBase64Decode(str) {
try {
return atob(str);
} catch (e) {
console.error('Invalid Base64 input:', e.message);
return null;
}
}
# Python
import base64
import binascii
def safe_b64decode(data):
try:
return base64.b64decode(data, validate=True)
except (binascii.Error, ValueError) as e:
print(f"Invalid Base64 input: {e}")
return None
This bears repeating: Base64 is an encoding, not encryption. It provides no confidentiality, no integrity, and no authentication. If you need to protect data, use proper cryptographic tools. Base64 should only be used for its intended purpose: representing binary data as text.
Some Base64 implementations insert line breaks (typically every 76 characters, per the MIME standard). Others produce a continuous string with no line breaks. Be aware of which behavior your encoder uses and which your decoder expects. Mismatched line-break handling is a common source of decoding errors.
When accepting Base64 input from users or external sources, strip all whitespace (spaces, newlines, tabs) before decoding. Base64 data is often copied from multi-line displays or formatted documents that introduce line breaks.
Our free Base64 Encoder/Decoder tool makes it easy to encode and decode Base64 data directly in your browser. No data is sent to any server -- all processing happens locally on your machine.
Paste any text or upload a file, and instantly get the Base64-encoded output. The tool supports both standard Base64 and Base64URL encoding, with options for including or omitting padding characters.
Paste a Base64 string and see the decoded output immediately. The tool automatically detects whether the input uses standard Base64 or Base64URL encoding. Invalid characters are highlighted, and clear error messages help you fix malformed input.
Stop writing throwaway scripts to encode and decode Base64. Use our free tool to convert text and files to Base64 (and back) right in your browser -- with zero data sent to any server.
Try the Base64 Encoder/Decoder NowLearn JWT structure, claims, signing algorithms, and how to decode and verify tokens for secure authentication.
Master JSON syntax, formatting best practices, validation techniques, and common parsing errors.
Master Kubernetes YAML from Deployments and Services to advanced scheduling and security contexts.