What Is Base64 Encoding? How It Works and When to Use It
What Is Base64 Encoding?
Base64 is an encoding scheme that converts binary data into ASCII strings. As the name suggests, it uses 64 printable characters (A-Z, a-z, 0-9, +, /) plus a padding character (=) to represent any binary data in text form.
While "encoding" might sound like encryption, Base64 is not encryption. Anyone can easily decode (restore) the original data — it's simply a way to change the representation of data.
How Encoding Works
Let's walk through the Base64 encoding process step by step.
The Conversion Flow
- Treat the input data as a byte sequence (8-bit units)
- Split the byte sequence into 6-bit units
- Map each 6-bit value to its corresponding character using the conversion table
- Add padding (
=) so the output length is a multiple of 4
The Conversion Table
A 6-bit value can represent 64 different values (0–63). Each maps to the following characters:
| Value Range | Characters | Count |
|---|---|---|
| 0–25 | A–Z | 26 |
| 26–51 | a–z | 26 |
| 52–61 | 0–9 | 10 |
| 62 | + | 1 |
| 63 | / | 1 |
That's 64 characters total, plus the padding character = for a total of 65 characters.
Example: Encoding "ABC"
Let's trace the process of encoding the string "ABC" to Base64.
Step 1: Convert to ASCII codes
A = 65 = 01000001
B = 66 = 01000010
C = 67 = 01000011
Step 2: Concatenate the 8-bit sequences and split into 6-bit units
8-bit: 01000001 01000010 01000011
6-bit: 010000 | 010100 | 001001 | 000011
Step 3: Map to characters using the conversion table
010000 = 16 → Q
010100 = 20 → U
001001 = 9 → J
000011 = 3 → D
Result: ABC → QUJD
How Padding Works
When the input byte count is not a multiple of 3, the 6-bit splitting produces a remainder. In this case, missing bits are filled with zeros, and = characters are added so the output is a multiple of 4 characters.
| Input Bytes | Padding | Example |
|---|---|---|
| Multiple of 3 | None | ABC → QUJD |
| Remainder of 1 | == |
A → QQ== |
| Remainder of 2 | = |
AB → QUI= |
Data Size Increase
In Base64 encoding, 3 bytes of input produce 4 characters of output. This means the encoded data is approximately 33% larger (exactly 4/3×) than the original.
Original: 3 bytes → Base64: 4 characters (4 bytes)
Increase: (4 - 3) / 3 ≈ 33%
This is a trade-off that should always be considered when using Base64.
Common Use Cases
Email Attachments (MIME)
The email protocol (SMTP) was originally designed to handle only 7-bit ASCII text. To attach binary files like images and PDFs to emails, the MIME (Multipurpose Internet Mail Extensions) standard adopted Base64 encoding.
Content-Type: image/png
Content-Transfer-Encoding: base64
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ
AAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5E
rkJggg==
Data URIs
Base64 is used to embed images directly in HTML or CSS. This allows small icons and inline images to be displayed without additional HTTP requests, reducing the total request count.
<!-- Embedding a small icon as a Data URI -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUh..." alt="Icon">
/* Background image embedding in CSS */
.icon {
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...");
}
However, Data URIs have several caveats:
- Base64 encoding increases data size by approximately 33%
- Browser caching doesn't apply (since it's part of the HTML file)
- Not suitable for large images (best limited to a few KB or less)
JWT (JSON Web Token)
JWTs, widely used as authentication tokens, use Base64URL encoding (discussed below). A JWT consists of three parts joined by dots (.).
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlRhbmFrYSJ9.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
The contents of each part:
| Part | Content | Decoded Example |
|---|---|---|
| Header | Algorithm info | {"alg": "HS256", "typ": "JWT"} |
| Payload | User data, etc. | {"sub": "1234567890", "name": "Tanaka"} |
| Signature | Tamper detection | (binary data) |
Binary Data in API Responses
Base64 encoding is also used to include binary data (images, files, etc.) in JSON API responses.
{
"fileName": "report.pdf",
"mimeType": "application/pdf",
"content": "JVBERi0xLjQKMSAwIG9iago8PA..."
}
Base64 Variants
Beyond standard Base64, there are variants for specific use cases.
Base64URL
A variant designed for use in URLs and filenames, replacing + with - and / with _. Used in JWTs and URL parameters. The padding = may also be omitted.
| Standard Base64 | Base64URL |
|---|---|
+ |
- |
/ |
_ |
= (padding) |
May be omitted |
MIME Base64
A variant for email transmission that inserts line breaks (CRLF) every 76 characters.
Pros and Cons
Pros
- Safely transmits binary data over text-based protocols
- Composed entirely of ASCII characters, eliminating the risk of character encoding issues
- Allows embedding binary data in text formats like JSON and XML
- Encoding and decoding are fast and easy to implement
Cons
- Data size increases by approximately 33%
- Incurs (minor) processing overhead for encoding and decoding
- Inefficient for transferring large amounts of binary data
- Not human-readable (you can't determine the content by looking at it)
Security Considerations
Let's address common misconceptions and security concerns about Base64.
Base64 Is Not Encryption
The most important point: Base64 is not encryption. Encoded data can be decoded by anyone. Simply Base64-encoding passwords, API keys, or other sensitive information does not constitute a security measure.
// This is NOT a security measure
const encoded = btoa("my-secret-password");
// "bXktc2VjcmV0LXBhc3N3b3Jk" → anyone can decode this
To protect sensitive information, use proper encryption algorithms like AES.
JWT Payloads Are Readable
The payload portion of a JWT is only Base64URL-encoded, not encrypted. This means anyone who obtains the token can read the payload contents. JWT signatures are for tamper detection, not for content confidentiality.
If you need to include sensitive data in a JWT, use JWE (JSON Web Encryption) to encrypt the payload.
Input Validation
When decoding Base64 data received from external sources, don't forget to validate the input. The Base64 string may be malformed, or the decoded data may contain unexpected content.
function safeBase64Decode(input) {
// Validate Base64 string format
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(input)) {
throw new Error("Invalid Base64 string");
}
return atob(input);
}
Implementation in Programming Languages
Here's how to perform Base64 encoding and decoding in major languages.
JavaScript (Browser / Node.js)
// Browser environment
const encoded = btoa("Hello, World!"); // Encode
const decoded = atob("SGVsbG8sIFdvcmxkIQ=="); // Decode
// Node.js environment
const buf = Buffer.from("Hello, World!");
const encoded = buf.toString("base64");
const decoded = Buffer.from(encoded, "base64").toString("utf-8");
Python
import base64
encoded = base64.b64encode(b"Hello, World!").decode("utf-8")
decoded = base64.b64decode(encoded).decode("utf-8")
Conclusion
Base64 is a simple yet practical encoding scheme for converting binary data to text form. It is used in many areas of web development, including email attachments, Data URIs, JWTs, and API responses. Understanding the trade-off of approximately 33% size increase is key to using it appropriately. And most importantly, always remember that Base64 is not encryption.
