If you've spent any time in web development, you've seen Base64. It shows up in HTML as those enormous data:image/png;base64,iVBOR... strings. It's in every JWT token. It's how email attachments travel through SMTP. It's in HTTP Basic Auth headers.

Most people know what it looks like. Fewer know why it exists or when they should actually use it themselves.

The Problem Base64 Solves§

Computers store everything as binary — zeros and ones. But many of the systems that transport data were designed decades ago, with the assumption that the data would be readable ASCII text. Email protocols. XML. JSON. HTTP headers. Early versions of these systems couldn't safely handle arbitrary binary bytes.

The problem is that raw binary data contains bytes that have special meaning in text systems: null bytes that terminate strings in C-based code, control characters that trigger protocol commands, bytes that don't have any valid ASCII representation at all. If you tried to shove a JPEG file directly into an email body or a JSON field, you'd corrupt the data or break the protocol.

Base64 solves this by re-encoding arbitrary binary data using only 64 characters that exist in every text encoding system: uppercase letters, lowercase letters, digits, plus (+), and forward slash (/). If you can represent all binary data using only these 64 characters, you can safely transmit it through any text-based system.

The = sign appears as padding, which we'll get to.

The Mechanics§

Base64 works by processing input data three bytes (24 bits) at a time:

  1. Take 3 bytes of input
  2. Split the 24 bits into four groups of 6 bits each
  3. Use each 6-bit value (which ranges from 0–63) as an index into the Base64 alphabet

Since 2^6 = 64, and the alphabet has exactly 64 characters, each 6-bit chunk maps to exactly one character. That's the whole trick.

Let's trace through "Man":

M = 01001101
a = 01100001
n = 01101110

Combined bits: 010011 010110 000101 101110
Base64 indices: 19 22 5 46
Base64 chars: T W F u

So "Man" encodes to "TWFu". You can verify this in any Base64 decoder.

The size overhead: Every 3 bytes of input becomes 4 characters of output. That's a 4/3 ratio — Base64 makes data about 33% larger than the original. This is an unavoidable consequence of the encoding.

Padding: The input data isn't always a perfect multiple of 3 bytes. When there are leftover bytes:

  • 1 remaining byte → encode as 2 Base64 chars + ==
  • 2 remaining bytes → encode as 3 Base64 chars + =

The = padding tells the decoder how many bytes are in the last group.

The Base64url Variant§

The standard Base64 alphabet uses + and / for its 62nd and 63rd characters. These have special meaning in URLs — + means a space, / is a path separator. If you Base64-encode data and put it in a URL, these characters need to be percent-encoded, which gets messy.

Base64url fixes this by replacing + with - and / with _. The result is safe to use in URL path segments and query parameters without any additional encoding.

This variant is used everywhere in modern auth: JWTs use Base64url for their header and payload sections, Google's OAuth implementation uses it, most modern API tokens use it. Whenever you see a Base64-like string that contains hyphens and underscores instead of pluses and slashes, that's Base64url.

Real Use Cases§

Inline Images in HTML and CSS (Data URIs)§

You can embed images directly into HTML without a separate file request using data URIs:

<!-- Normal image — requires HTTP request -->
<img src="/icons/arrow.svg" alt="Arrow">

<!-- Same image, Base64-encoded inline — zero HTTP requests -->
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTEyIDVsMCA3LTcgMCIvPjwvc3ZnPg==" alt="Arrow">

The same technique works in CSS:

.arrow {
 background-image: url("data:image/svg+xml;base64,PHN2ZyB...");
}

When this is a good idea: Small icons (under ~1KB) that appear on every page. Critical above-the-fold images where you want to eliminate the HTTP latency. Icons bundled into a CSS file that's already being loaded.

When this is a bad idea: Anything large. Base64 adds 33% overhead and prevents the image from being cached separately by the browser. A 50KB image becomes a 67KB blob embedded in your HTML, downloaded on every page load, never cached independently. For most images on most sites, separate HTTP requests with browser caching is more efficient.

JWT Tokens§

JSON Web Tokens have three parts separated by dots, each Base64url-encoded:

header.payload.signature

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U

The header and payload decode to plain JSON. Anyone can read them. If you're wondering whether you can decode a JWT without the secret key: yes, absolutely, the header and payload are not encrypted. They're just Base64url-encoded. Only the signature requires the key.

This trips people up: Base64 is encoding, not encryption. It's a reversible transformation anyone can undo. Never put sensitive secrets in a JWT payload and assume they're protected.

HTTP Basic Authentication§

The HTTP Authorization header for Basic auth:

Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

Decode that: dXNlcm5hbWU6cGFzc3dvcmQ=username:password. Completely readable.

Basic auth over plain HTTP is not secure at all. Over HTTPS, the TLS layer protects the credential in transit — but the Base64 encoding itself does nothing for security. Anyone who intercepts the request over HTTP can read the credentials immediately.

Email Attachments§

SMTP and MIME were designed for text. Attachments get Base64-encoded into the email body:

Content-Type: application/pdf; name="report.pdf"
Content-Transfer-Encoding: base64

JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvT3V0...

Your email client decodes this silently. The raw .eml file for any email with attachments is full of Base64 blocks.

Encoding Images in Your Browser§

The NexaTools Base64 Image Encoder converts any image to a data URI, and back, entirely in your browser:

  • Upload an image → get the full data URI string, ready to copy into HTML or CSS
  • Paste a data URI → download the image file

Under the hood, the browser's FileReader API handles the encoding:

function imageToBase64(file) {
 return new Promise((resolve) => {
 const reader = new FileReader();
 reader.onload = (e) => resolve(e.target.result);
 // e.target.result = "data:image/png;base64,iVBOR..."
 reader.readAsDataURL(file);
 });
}

The data: URI format includes the MIME type, which tells the browser how to interpret the data when it's used as an image src or CSS background.

Clearing Up the Common Misconceptions§

"Base64 is encrypted." It is not. Encoding and encryption are different things. Encoding transforms data into another representation. Encryption scrambles data so only authorized parties can read it. Anyone can decode Base64 in seconds with any decoder. It provides zero security.

"Base64 compresses files." The opposite — it makes them 33% larger. If you need to reduce size, compress first (gzip, Brotli, or a lossy format for images), and then Base64-encode the compressed result if you need text transport.

"Base64 only works for images." It works for any binary data — PDFs, fonts, audio files, executables. The data: URI syntax supports any MIME type. The use with images is just the most common in front-end web development.

When to Reach for It§

Use Base64 when you need binary data in a text context: embedding small assets inline, transmitting files through text-only protocols, storing binary data in JSON fields.

Avoid it when size matters, when browser caching would be beneficial, or when you mistakenly think it provides security.

For quick encoding of images, the NexaTools Base64 Image Tool handles it in the browser with no server involvement.