メインコンテンツへ移動

How Does Base64 Work

Base64 converts binary data into text so it can travel through channels that only handle characters. RFC 4648 defines the mechanism: every 3 bytes — 24 bits — become 4 characters from a 64-symbol alphabet, with = padding when the bytes do not divide evenly. It grows data by about a third and is an encoding, not encryption.

端末内で処理

以下の解説は英語のみでご覧いただけます。

How Does Base64 Work explained

Email systems of the 1980s moved 7-bit text and nothing else; HTTP headers, JSON fields, URLs and log files are text-only territories in practice. Raw binary — an image, a signature, a cryptographic key — corrupts the moment such a channel meets it. Base64 is the standard bridge: a fully reversible way to spell arbitrary bytes using nothing but 64 safe printable characters.

You have read Base64 all day without noticing it: every JWT is three Base64url segments, every data: URI embedded in CSS, every MIME email attachment. The scheme is specified in RFC 4648 — which consolidated the earlier Base-64 definitions into one document — and it is small enough to compute by hand. This guide does exactly that, one 24-bit group at a time.

Three things confuse everyone at first: why 3 bytes become 4 characters, what the = signs are for, and why there are two alphabets. Each gets its own section below, along with the honest limits — the size penalty, the whitespace disagreements between decoders, and the persistent mistake of treating a reversible encoding as security.

Reading beats describing here — paste any string into the Base64 decoder and watch the bytes it hides; it decodes locally, so tokens and keys stay in your tab.

The most famous Base64 consumer is the token format; the JWT structure guide shows how a JWT's three segments ride on the URL-safe alphabet defined below.

The mechanism: 3 bytes in, 4 characters out

Take any binary data and slice it into groups of 3 bytes — 24 bits. Split each group into four 6-bit chunks. Each chunk is a number from 0 to 63, and the RFC 4648 alphabet maps those numbers onto characters: A–Z for 0–25, a–z for 26–51, 0–9 for 52–61, then + and / for 62 and 63. Six bits is the sweet spot because 2⁶ = 64 is exactly the size of an alphabet that every character-only channel can carry without complaint.

The classic worked example is the RFC's own test vector, the word Man — three bytes, no padding needed:

Byte by byte

M   0x4D   01001101
a   0x61   01100001
n   0x6E   01101110

joined:    010011 010110 000101 101110
indexes:      19     22      5      46

Character by character

19→T   22→W   5→F   46→u

"Man"  →  TWFu
"Ma"   →  TWE=
"M"    →  TQ==

Padding: what the = signs mean

Six-bit chunks only reassemble into bytes in whole groups of four. When the input length is not a multiple of 3, the final group comes up short: 2 remaining bytes produce three characters plus one = sign, and 1 remaining byte produces two characters plus ==. Padding restores the length so a decoder can compute the exact byte count without guessing — and = is the only character outside the 64-symbol alphabet that may appear in the output.

Padding is length metadata, not security or compression. RFC 4648 permits unpadded variants when both sides agree — the Base64url of JWTs notably drops the = entirely, because the dots delimit segments and each segment's length tells the decoder everything it needs.

Input bytesOutput charactersPaddingExample
3 (any multiple of 3)4 per 3 bytesnone"Man" → TWFu
23one ="Ma" → TWE=
12two =="M" → TQ==
1216none"Hello, world" → SGVsbG8sIHdvcmxk

The two alphabets: standard and URL-safe

The standard alphabet uses + and / — harmless in email, hostile in URLs, where + decodes as a space and / as a path separator. RFC 4648 §5 therefore defines Base64url, replacing + with - and / with _: characters that need no percent-encoding inside URLs and no quoting inside filenames or cookies. The two dialects are otherwise identical — same 6-bit chunks, same padding rules.

That is the practical trap: the dialects differ in only two characters, so a token pasted with the wrong alphabet fails two characters in — or worse, decodes to different bytes if it happens to contain + or /. Well-behaved decoders accept either form and tell you which they saw; strict ones refuse mixed alphabets outright rather than guess.

ValuesStandardURL-safe
0–25A–ZA–Z
26–51a–za–z
52–610–90–9
62+-
63/_

Same bytes, two dialects

bytes:    0xFB 0xEF 0xBE

standard:  ++++
url-safe:  ----

Where the dialects bite

in a URL query, ++++ arrives as four spaces
(plus-to-space rule) — ---- arrives intact.
This is why tokens use the URL-safe alphabet.

Size: the one-third tax and its fine print

Four characters carry three bytes, so encoded output is always 4/3 of the input — about a 33% increase — before any transport overhead. For concrete anchors: 100 bytes encode to 136 characters, 17 bytes to 24, and the ratio never moves, because it is arithmetic rather than tuning. Padding, line breaks and wrapping add more: MIME caps Base64 lines at 76 characters and requires CRLF breaks between them, which contributes a little extra on large payloads. A data: URI embeds that already-inflated form inside CSS or HTML, which is why inlined images weigh roughly a third more than the binary files they replace.

Nothing reversible shrinks data, and Base64 is no exception — it is a spelling change, not compression. If size matters, compress first and encode the compressed bytes; never the reverse order.

Whitespace, line breaks and decoder disagreements

RFC 4648 is strict: decoders must reject characters outside the alphabet, and the document itself says nothing about requiring line breaks. MIME's Base64 (RFC 2045) expects the opposite — CRLF every 76 characters. Real implementations scatter between the poles: many strip whitespace silently, some insist on it, some reject any newline at all. This is the classic reason a string that 'encodes fine' in one tool fails to decode in another.

The honest interoperability rule: produce standard, padded, unwrapped Base64 unless a specification says otherwise, and build decoders that tolerate the whitespace other tools add — while still refusing any character that is not part of a recognised alphabet, because leniency there is how silent byte corruption begins.

What Base64 is not

Base64 has no key, no rounds of mixing, no secret: anyone can reverse it, and decoders ship in every language's standard library. Treating an encoded payload as protected data is a recurring vulnerability report. The give-aways are public: SGVsbG8= spells Hello, JVBERi0x opens a PDF, /9j/ begins a JPEG, and eyJ begins almost every JSON Web Token — those first characters are simply Base64 for %PDF-, the JPEG magic bytes, and a JSON opening brace.

Use Base64 for what it is: a container-safe spelling of bytes. Put confidentiality in real encryption — TLS in transit, a proper cipher at rest — and keep Base64 as the final step that makes the result printable, nothing more.

Telltale openings

SGVsbG8sIHdvcmxk
JVBERi0xLjQ=
/9j/
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

What they decode to

Hello, world
%PDF-1.4
(bytes FF D8 FF — a JPEG's magic number)
{"alg":"HS256","typ":"JWT"}

Frequently asked questions

Is it safe to paste tokens and keys into a Base64 decoder?

On this site, yes: the decoder runs in your browser and never transmits your input — there is no upload endpoint to leak from. The Network panel shows no requests while you decode, and the site's Content-Security-Policy blocks outbound connections. It matters because Base64 tokens are live credentials, and many random web decoders are far less careful about what happens to them.

Is Base64 encryption?

No — it is an encoding with no key and no secrecy property. Any library, and any attentive human, can reverse it instantly; an encoded password is a visible password. Encryption transforms data so it is unreadable without a key, while Base64 only re-spells bytes so text-only channels can carry them. The two solve different problems and often appear together.

Why does Base64 output end with = signs?

The = is padding that restores length. Output comes in 4-character groups, and when the input was not a multiple of 3 bytes the final group is topped up — one = for two leftover bytes, two for one, never three, because a complete group needs none. The signs carry no data; they tell the decoder the exact byte count.

What is the difference between Base64 and Base64url?

Two characters. Base64url, defined in RFC 4648 §5, replaces + with - and / with _ so output is safe in URLs, filenames and cookies without escaping. Everything else — the 6-bit grouping, the letters and digits, the padding rules — is identical, and formats such as JWTs use the URL-safe variant with padding removed.

Why is Base64 output bigger than its input?

Each output character carries 6 bits while a byte carries 8, so 3 bytes — 24 bits — require 4 characters: a fixed 4/3, or roughly 33% overhead, before padding and line breaks. It is the price of staying printable; no reversible encoding avoids it, which is why raw binary transport wins wherever the channel permits actual bytes.

Can I decode Base64 by hand?

Yes — the design invites it. Write the input's bytes in binary, regroup each 24-bit block into four 6-bit chunks, and read each chunk off the alphabet table: A=0 through Z=25, a=26 through z=51, 0=52 through 9=61, then + and /. The RFC's own example works on paper: Man is 010011 010110 000101 101110, which reads T, W, F, u — TWFu.