HandyTools Hub

← All guides

What Base64 Actually Is: Why an Image Turns Into a String of Characters

2026-08-06

If you’ve ever viewed the source of a web page, you’ve probably seen an <img> tag whose src isn’t a file path but a long run of letters, digits, plus signs, and slashes — often starting with iVBORw0KGgo and sometimes ending in =. That’s Base64: an image “translated” into plain text. Why would anyone do that, and how is the string produced? This article answers both questions from the ground up.

The root problem: text channels, binary data

Everything on a computer is bytes — 8 bits each, values 0 to 255. But many transport systems were designed for text. Early email (SMTP) only guaranteed 7-bit ASCII would survive the trip, and formats like JSON, XML, and URLs all reserve characters that can’t appear raw. Drop arbitrary binary bytes into those channels and the data gets mangled or truncated somewhere along the way.

Base64’s answer is simple: represent any binary data using only 64 printable characters that every text system passes through untouched. Once encoded, an image, a certificate, or a cryptographic key can ride inside a text protocol without fear.

The 64-character alphabet

The standard alphabet (RFC 4648) is:

Index rangeCharacters
0–25AZ
26–51az
52–6109
62+
63/

Each character stands for one value from 0 to 63 — exactly 6 bits of information (2⁶ = 64). That single fact is the key to everything else about Base64: every character carries six bits of the original data.

The encoding process: 3 bytes become 4 characters

A byte is 8 bits; a Base64 character carries 6. The least common multiple of 8 and 6 is 24, so encoding works in groups of 3 bytes (24 bits), which are split into four 6-bit chunks, and each chunk is looked up in the alphabet to produce one character. Hence “3 bytes become 4 characters.”

Let’s run the string Man through the whole pipeline (the classic RFC 4648 example):

  1. The ASCII codes for M, a, n are 77, 97, 110.
  2. Concatenated as binary: 01001101 01100001 01101110 — 24 bits.
  3. Split into 6-bit chunks: 010011, 010110, 000101, 101110.
  4. As decimals: 19, 22, 5, 46.
  5. Looked up in the alphabet: 19→T, 22→W, 5→F, 46→u.

So Man encodes to TWFu. Paste it into a Base64 encoder/decoder and you’ll get exactly that. Decoding is the mirror image: map each character back to 6 bits, concatenate, and re-split into 8-bit bytes.

Why the size grows by about 33%

The arithmetic is one line: 3 bytes of input become 4 characters of output, and each character costs one byte of text, so 3 bytes become 4 bytes. Four-thirds is roughly 1.333 — a 33% overhead, always. A 300 KB image turns into about 400 KB of Base64 text.

That’s the main reason inlining large images as Base64 is discouraged: beyond the bloat, the browser must download the entire HTML document before it can even start decoding, losing both parallel loading and separate caching. Inline Base64 makes sense for tiny assets — icons and placeholders of a few kilobytes.

= is padding, not data

Input length isn’t always a multiple of 3. With one byte left over (8 bits), you can form two 6-bit chunks (12 bits, the last four zero-filled), producing two characters followed by ==. With two bytes left over, you get three characters followed by one =. So a Base64 string ends in zero, one, or two = characters — never more.

Two quick examples: M (1 byte) encodes to TQ==, and Ma (2 bytes) encodes to TWE=. The = is purely a placeholder telling the decoder “the final group was short.” Note that some systems strip padding entirely — JWTs do — which is a common cause of “why won’t this Base64 decode”: you have to add the = characters back yourself.

The URL-safe variant

The standard alphabet’s + and / have special meanings in URLs (+ is interpreted as a space in query strings), so raw Base64 can’t go into a link safely. RFC 4648 therefore also defines Base64url: - replaces +, _ replaces /, and trailing = is usually omitted. JSON Web Tokens use it — each of the three segments in an eyJhbGci... token is Base64url.

Practical tip: if a Base64 string fails to decode, check whether it contains - or _. If so, it’s the URL-safe variant — swap those two characters back before decoding.

Base64 is not encryption — and not compression either

This is the misconception that matters most. Base64 is an encoding, not encryption: the scheme is public, anyone can reverse it in milliseconds, and there is no key. “Encrypting” a password or API key with Base64 before storing it is equivalent to storing it in plain text — the first thing an attacker does with a suspicious =-terminated string is decode it.

It also doesn’t compress anything; as computed above, it makes data a third larger. Recognizing Base64 is easy: the length is a multiple of 4, and every character falls in A-Za-z0-9+/ plus optional trailing =. To settle it by hand, drop the suspect string into an encoder/decoder — if it’s Base64, the original content appears immediately.

data URIs: the classic use case

Base64’s most visible habitat is the data URI, with the format:

data:[<media type>][;base64],<data>

Inlining a small PNG icon straight into HTML looks like this:

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

And the same trick works in CSS:

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

The win is one fewer HTTP request: the image arrives with the HTML or CSS itself, which is worthwhile for small, frequently-used assets. The costs are the ones already covered — 33% more bytes, and no independent browser caching. The common rule of thumb is to only inline assets under a few kilobytes. The conversion itself is trivial: an image to Base64 converter takes an uploaded image and hands you the complete data URI, prefix data:image/png;base64, and all.

Beyond data URIs, Base64 shows up everywhere: email attachments (MIME), binary fields in APIs (certificates, signatures, thumbnails), Kubernetes Secrets, and the JWTs mentioned earlier. Once you understand the “3 bytes become 4 characters” core, that long string of characters is no longer mysterious — you know exactly what it’s doing there, and how to turn it back into the original yourself.