What Is Base64 Encoding?
Base64 is a way of writing any binary data, whether that is an image, a PDF or an encryption key, using only 64 safe printable text characters. It exists because large parts of our infrastructure were built to carry text rather than raw bytes, and it survives because those parts never went away. If you have ever seen a wall of characters like SGVsbG8gd29ybGQh in a URL, an email source or an API token, you have met it.
The problem it solves
Raw binary uses all 256 possible byte values. Text-based channels do not tolerate all 256. Email systems historically mangled anything outside 7-bit ASCII, JSON strings cannot contain arbitrary bytes, HTTP headers are text, and a control character like a null byte can terminate a string or break a protocol outright. Base64 steps around all of that by re-expressing the same bytes using characters that every text system agrees on: A–Z, a–z, 0–9, + and /. Sixty-four symbols, which is where the name comes from.
How it works: 3 bytes in, 4 characters out
The mechanism is pure regrouping. Three bytes are 24 bits. Base64 slices those 24 bits into four 6-bit chunks, and since 6 bits hold values 0 to 63, each chunk indexes one character in the 64-character alphabet. Every 3 bytes of input become exactly 4 characters of output. When the input length isn’t a multiple of three, the final group gets padded and the encoder appends one or two = signs. That trailing = on so many Base64 strings means nothing more than “the last group was short.”
A worked example: encoding “Hi!”
The string Hi! is three bytes, so it encodes with no padding at all:
Text: H i !
Bytes: 72 105 33
Bits: 01001000 01101001 00100001
Regroup 24 bits into four 6-bit chunks:
010010 000110 100100 100001
Decimal: 18 6 36 33
Alphabet: S G k h
Result: "Hi!" -> "SGkh"That is the whole algorithm. No keys, no secrets, no arithmetic beyond regrouping bits, and decoding runs the same table backwards. Verify it in the Base64 Encoder/Decoder: type Hi! and watch SGkh appear.
Where you’ll meet it
Data URIs embed files directly in HTML or CSS, so src="data:image/png;base64,iVBORw0K..." puts a whole image inside the markup. JWTs, the tokens behind most modern login sessions, are three Base64-encoded segments joined by dots; paste one into the JWT Decoder and the header and payload pop out as plain JSON. Email attachments ride inside MIME messages as Base64, which is why a raw email source looks like character soup. And HTTP Basic auth sends username:password Base64-encoded in the Authorization header.
Base64 is not encryption
This gets its own section because it is the most common and most dangerous misconception about the format. Encoding and encryption answer different questions. Encoding asks how to represent data so it survives the channel. Encryption asks how to keep data secret from anyone without the key. Base64 has no key. Anyone who sees a Base64 string can decode it instantly with one line of code or any online tool, because the “secret,” the alphabet table, is published in the spec.
Which brings back that Basic auth header. It is the password, readable by anything that sees the request, and that is why Basic auth is only acceptable over HTTPS. The payload of a JWT is readable by anyone holding the token; the signature stops tampering, not reading. If you find yourself Base64-encoding an API key “for security” before dropping it in a config file or a URL, stop. You have obscured it from human eyes for roughly four seconds and protected it from exactly no one. Secrets need real encryption or a secrets manager.
The 33% tax, and when not to use Base64
Turning 3 bytes into 4 characters means Base64 output is always about 33% larger than its input, so a 3 MB image becomes 4 MB of text. For small payloads that is a fair price for compatibility. For large ones it stacks up: inlining big images as data URIs bloats your HTML, defeats browser caching (the “file” re-downloads with every page view), and adds decode work on top.
So the working rule is that Base64 is for smuggling binary through a text-only channel, never for storage and never for anything a plain URL and a normal binary transfer could handle. Databases have blob columns. HTTP carries binary natively. Use them.
The base64url variant
Two characters of the standard alphabet are landmines in URLs: + means a space in query strings, and / is a path separator. The base64url variant defined in RFC 4648 swaps them, putting - in place of + and _ in place of /, and it usually drops the = padding, which also needs escaping in URLs.
JWTs use base64url. That is why a naive standard-Base64 decode of a token segment sometimes fails on a stray - or _, and why checking for those two characters is the first move when a decoder rejects a string that looks perfectly valid.