ToolPal
Close-up of scrabble tiles spelling 'Binary' surrounded by scattered letters on a wooden background.

Base64 Encoding Demystified: Why Every API Uses It and How to Decode Anything

📷 Markus Winkler / Pexels

Base64 Encoding Demystified: Why Every API Uses It and How to Decode Anything

JWTs, data URIs, email attachments — Base64 is everywhere. Learn what it actually does, why it exists, and when (not) to use it.

DBy Daniel ParkMarch 14, 20269 min read

What is Base64 Encoding?

Base64 is a binary-to-text encoding scheme that represents binary data in an ASCII string format. It converts binary data into a set of 64 characters (A-Z, a-z, 0-9, +, /) that can be safely transmitted over text-based protocols.

The name "Base64" comes from the fact that it uses exactly 64 different ASCII characters to represent data. This is a deliberate design choice: 64 is a power of 2 (2^6), which makes the conversion between binary and Base64 straightforward and efficient.

You run into Base64 constantly in web development, whether you realize it or not. Every time you see a long string of seemingly random letters and numbers ending with one or two = signs, there is a good chance it is Base64.

Why Use Base64?

The core problem Base64 solves is simple: many systems and protocols were designed to handle text, not raw binary data. Sending a JPEG image through an email protocol that expects ASCII text would corrupt the data because certain byte values have special meanings in text protocols (think control characters, null bytes, or values above 127).

Base64 gets around this by converting everything into safe, printable ASCII characters.

  • Email attachments: MIME uses Base64 to encode binary files in emails
  • Data URIs: Embed images directly in HTML/CSS without extra HTTP requests
  • API authentication: HTTP Basic Auth encodes credentials in Base64
  • JWT tokens: JSON Web Tokens use Base64URL encoding for header and payload
  • Configuration files: Safely store binary data (certificates, keys) in text files like YAML or JSON
  • Database storage: Store small binary blobs in text-based databases or fields
  • URL parameters: Pass binary data through URL query strings safely

How Base64 Works

The encoding process is straightforward once you break it down:

  1. Take the binary data (e.g., text converted to ASCII bytes)
  2. Split into groups of 6 bits (instead of the usual 8)
  3. Map each 6-bit group to one of 64 characters
  4. Add padding (=) if the data doesn't divide evenly into 3-byte groups

The Base64 Alphabet

The standard Base64 alphabet consists of:

  • A-Z (indices 0-25)
  • a-z (indices 26-51)
  • 0-9 (indices 52-61)
  • + (index 62)
  • / (index 63)
  • = for padding

Step-by-Step Example

Let's encode the text Hi manually:

Step 1: Convert to ASCII bytes H = 72, i = 105

Step 2: Convert to binary 72 = 01001000, 105 = 01101001

Step 3: Concatenate all bits 01001000 01101001

Step 4: Regroup into 6-bit chunks 010010 000110 1001xx

Since we only have 16 bits but need groups of 6, the last group is padded with zeros: 010010 000110 100100

Step 5: Map each 6-bit value to the Base64 alphabet

  • 010010 = 18 = S
  • 000110 = 6 = G
  • 100100 = 36 = k

Step 6: Add padding Since the original input was 2 bytes (not a multiple of 3), we add one = padding character.

Result: SGk=

Understanding Padding

Padding is one of the parts of Base64that trips people up. Here is the rule:

  • If the input length is divisible by 3: no padding
  • If there is 1 byte remaining: add ==
  • If there are 2 bytes remaining: add =

For example:

  • A (1 byte) → QQ==
  • AB (2 bytes) → QUI=
  • ABC (3 bytes) → QUJD (no padding)

Common Use Cases with Real Examples

Embedding Images in HTML (Data URIs)

One of the most practical uses of Base64 is embedding small images directly in HTML or CSS. This eliminates an extra HTTP request, which can be useful for tiny icons or decorative elements.

<img src="data:image/png;base64,iVBORw0KGgo..." />
.icon {
  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxu...");
}

When to use this: For images under 2-3 KB (like small icons or 1x1 pixel tracking images), embedding as Base64 can actually improve performance by saving a network round trip. For anything larger, the 33% size increase and lack of caching makes it a bad trade-off.

HTTP Basic Authentication

When a server requires Basic Auth, your client concatenates the username and password with a colon and Base64-encodes the result:

username:password → dXNlcm5hbWU6cGFzc3dvcmQ=

The request header then looks like:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

This is just encoding, not encryption. Anyone who intercepts this header can decode the credentials instantly. That is why Basic Auth should only be used over HTTPS.

Storing Binary Data in JSON

JSON does not support binary data natively. If you need to include a file, image, or any binary payload in a JSON document, Base64 is the standard approach:

{
  "file": "SGVsbG8gV29ybGQ=",
  "filename": "hello.txt",
  "mimetype": "text/plain"
}

This pattern shows up frequently in REST APIs that need to accept file uploads via JSON request bodies rather than multipart form data.

JWT Tokens

JSON Web Tokens use a variant called Base64URL encoding (replacing + with - and / with _, and stripping padding). A JWT has three Base64URL-encoded parts separated by dots:

eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiam9obiJ9.abc123signature

Decoding the first part gives you the header: {"alg":"HS256"}. Decoding the second part gives you the payload: {"user":"john"}.

Email Attachments

When you send an email with an attachment, the binary file is Base64-encoded and included in the MIME message body. Your email client does this automatically, but behind the scenes the attachment data looks like a wall of Base64 text, broken into 76-character lines per the MIME specification.

Base64 vs Base64URL

There are actually two common variants of Base64, and mixing them up is a frequent source of bugs:

FeatureStandard Base64Base64URL
Characters 62-63+ and /- and _
PaddingRequired (=)Often omitted
Used inMIME, general encodingURLs, JWTs, filenames

Base64URL exists because +, /, and = all have special meanings in URLs. If you Base64-encode something and drop it into a query parameter, the + gets interpreted as a space, the / breaks the URL path, and = conflicts with key-value syntax.

Base64 vs Encryption

Important: Base64 is not encryption. It's encoding -- anyone can decode it. Never use Base64 alone to protect sensitive data.

I have seen this mistake more times than I can count: developers Base64-encode an API key or password and think it is hidden. It is not. Open any browser's developer tools, paste the string into atob(), and the original value appears instantly.

If you need to protect data, use proper encryption (AES, RSA) or hashing (SHA-256, bcrypt). Base64 is for transport compatibility, not security.

Common Mistakes and Gotchas

1. Forgetting the 33% Size Increase

Every 3 bytes of input become 4 bytes of output. If you Base64-encode a 1 MB image and embed it in your HTML, you are now sending roughly 1.33 MB of data -- and the browser cannot cache that image separately from the page. For large files, this is a significant overhead.

2. Line Length in MIME

The MIME standard requires Base64-encoded data to be wrapped at 76 characters per line. If you are generating emails or MIME messages manually, forgetting the line breaks can cause some email servers to reject or mangle your message.

3. Mixing Up Base64 and Base64URL

Decoding a JWT token with a standard Base64 decoder might fail or produce garbage because of the different character set. Always check which variant you are dealing with.

4. Double Encoding

A surprisingly common bug: encoding data that is already encoded. If you Base64-encode a string and then accidentally Base64-encode it again, the result is valid Base64 but decodes to the first encoded string, not the original data. If your decoded output looks like Base64 itself, you probably double-encoded somewhere.

5. Character Encoding Issues

Base64 encodes raw bytes, not characters. The string "cafe" in UTF-8 is different from "cafe" in ISO-8859-1 if there are accented characters involved. Always be explicit about character encoding before Base64-encoding text.

Working with Base64 in Different Languages

JavaScript (Browser)

// Encode
const encoded = btoa("Hello World");  // "SGVsbG8gV29ybGQ="

// Decode
const decoded = atob("SGVsbG8gV29ybGQ=");  // "Hello World"

Note: btoa and atob only work with ASCII strings. For Unicode text, you need to encode to UTF-8 first:

// Encode Unicode text
const encoded = btoa(unescape(encodeURIComponent("Hello")));

// Decode back
const decoded = decodeURIComponent(escape(atob(encoded)));

Python

import base64

# Encode
encoded = base64.b64encode(b"Hello World").decode()  # "SGVsbG8gV29ybGQ="

# Decode
decoded = base64.b64decode("SGVsbG8gV29ybGQ=").decode()  # "Hello World"

# Base64URL variant
url_encoded = base64.urlsafe_b64encode(b"Hello World").decode()

Command Line

# Encode
echo -n "Hello World" | base64
# SGVsbG8gV29ybGQ=

# Decode
echo "SGVsbG8gV29ybGQ=" | base64 --decode
# Hello World

The -n flag on echo is important -- without it, a trailing newline gets encoded too, giving you a different result.

Performance Considerations

Base64 is fast to encode and decode, but there are situations where performance matters:

  • Large file transfers: The 33% overhead adds up. A 10 MB file becomes about 13.3 MB after encoding. If you are transferring files frequently, use binary protocols or multipart uploads instead.
  • Inline images in CSS: Every page load re-downloads Base64-encoded images embedded in your stylesheet. Small icons (under 2 KB) are fine, but anything bigger should be a separate file that the browser can cache.
  • Database storage: Storing Base64 in a database text column works, but it uses 33% more space than storing raw bytes in a binary/blob column. For large volumes of data, this adds up in storage costs.

When NOT to Use Base64

  • Encrypting sensitive data -- it provides zero security
  • Large files in data URIs -- the size overhead and lack of caching hurt performance
  • When binary transport is available -- if your protocol supports binary data natively (like HTTP multipart, gRPC, or WebSockets in binary mode), there is no reason to add the Base64 overhead
  • Storing large files in databases -- use blob/binary columns instead

Try It Now

Use our free Base64 encoder/decoder to encode or decode Base64 strings instantly! It works entirely in your browser, so your data never leaves your machine.

Frequently Asked Questions

D

About the author

Daniel Park

Senior frontend engineer based in Seoul. Seven years of experience building web applications at Korean SaaS companies, with a focus on developer tooling, web performance, and privacy-first architecture. Open-source contributor to the JavaScript ecosystem and founder of ToolPal.

Learn more

Share this article

XLinkedIn

Related Posts