Elton Lab
Lab online Depth 000% Series two · zero uploads

Base64, explained properly.

It turns up in tokens, email, data URLs and config files, and it is misunderstood in most of them. Here is what the encoding does, byte by byte, and what it does not do.

The problem it solves

Computers store everything as bytes, and a byte can hold 256 different values. Plenty of systems, though, were built to carry text and only text: email in its original form, JSON strings, URLs, HTML attributes. Send raw bytes through those and some values get mangled: a byte that happens to equal a newline or a quote mark breaks the container. Base64 exists to make any sequence of bytes survive a trip through a channel that only trusts printable characters.

Six bits at a time

The trick is to change the grouping. Three bytes are 24 bits. Cut those 24 bits into four groups of six, and each group is a number from 0 to 63. Give each of those 64 numbers a printable character, and three bytes become four characters. The alphabet is the capital letters A to Z for 0 to 25, the lowercase letters for 26 to 51, the digits for 52 to 61, and then plus and slash for 62 and 63.

That is the entire encoding. Decoding runs it backwards: look up each character to get six bits, glue the bits together, and cut them into bytes again. There is no key, no secret and nothing lost. It is a change of representation, like writing a number in hexadecimal instead of decimal.

Why the output is a third bigger

Four characters for every three bytes means the encoded form is always 4/3 the size of the input, about 33 percent larger, plus padding. This is the price of using only 64 symbols out of 256. A 30 kilobyte image becomes 40 kilobytes as Base64, which is why embedding images inside HTML as data URLs saves a request but costs bandwidth.

What the equals signs are for

Inputs are not always a multiple of three bytes. If one byte is left over at the end, it makes only eight bits, enough for two characters with four bits to spare; the encoder writes those two characters and then two equals signs to show that the last group was short. Two leftover bytes make three characters and one equals sign. You will therefore see one or two equals signs at the end of a Base64 string and never three, and their only job is to make the length a multiple of four so a strict decoder can check its work. Many decoders, including the one on this site, accept input with the padding missing.

InputBytesBase64
Hi2SGk=
Hey3SGV5
Hey!4SGV5IQ==
Elton Lab9RWx0b24gTGFi

The URL-safe variant

Plus and slash both have meanings inside a URL, and slash is a directory separator in filenames. So a second alphabet swaps them for minus and underscore, and usually drops the padding. It is the same encoding otherwise, and a good decoder accepts both. JSON Web Tokens use the URL-safe form, which is why a token looks like three runs of letters, digits, minus and underscore separated by dots.

Text is bytes first

Base64 encodes bytes, not letters, so text has to be turned into bytes before encoding. The choice of how is called the character encoding, and the sensible choice today is UTF-8. Tools that skip this step and use an old function meant for single-byte text break on anything outside plain ASCII: an accented letter or an emoji either throws an error or comes back as garbage. The encoder here converts to UTF-8 first, which is why Swedish letters and emoji survive the round trip.

What it is not

Base64 is not encryption, and this is the single most expensive misunderstanding in the whole subject. The alphabet is public, the algorithm is public, and anyone holding the string can decode it in a millisecond. A password stored as Base64 is a password stored in plain text with one extra step. A token's payload is readable by everyone who sees the token; the signature at the end proves it has not been altered, not that it is secret.

It is not compression either. The output is bigger than the input, always. And it is not hashing, because hashing throws information away on purpose and cannot be reversed, while Base64 preserves every bit and reverses perfectly.

Where you will meet it

Data URLs embed small images and fonts directly in CSS and HTML. Email attachments travel as Base64 inside MIME, which is why a mail with a five megabyte attachment is nearer seven on the wire. HTTP Basic authentication sends username and password joined by a colon and Base64-encoded, which is only safe over HTTPS. Certificates and keys are stored in PEM files, Base64 between two header lines. And any time a developer needs to put binary in a JSON field, this is how it gets there.

Try it with your own text in the Base64 Encoder / Decoder. It converts as you type, in both directions, without sending anything anywhere.