Base64 Encoding Explained: What It Is and When to Use It

Understand what Base64 encoding is, how it works, and why it's used in emails, data URLs, and web APIs.

You're debugging an API integration at 10pm. The request body looks fine, the auth header is set, but every call returns a 401. You paste the Authorization header into a decoder and realize: someone encoded the credentials twice. The token was already Base64, and your code Base64'd it again. Classic.

That moment — staring at dXNlcjpwYXNzd29yZA== and not immediately knowing what it says — is why Base64 is worth understanding properly, not just "oh, it's some encoding thing."

The problem it solves

Back in the early days of the internet, a lot of infrastructure was built around the assumption that data would be plain ASCII text. Email servers, terminal protocols, certain database drivers — they expected 7-bit characters, no null bytes, no arbitrary binary garbage.

Then people wanted to send images via email, or embed a small icon directly in a CSS file, or transmit a cryptographic key as part of a JSON payload. Binary data through a text-only channel causes corruption: bytes above 127 get stripped or mangled, null bytes terminate strings early, line endings get rewritten.

Base64 fixes this by taking any binary blob and expressing it using only 64 "safe" ASCII characters: A-Z, a-z, 0-9, +, /, and = for padding. These characters survive intact through every text-based system built since the 1970s.

How the encoding actually works

The core idea is simple: take 3 bytes (24 bits) of input, split them into four 6-bit chunks, and map each chunk to one of 64 characters.

3 bytes input 01001101 01100001 01101110 split into 4 × 6-bit 010011 | 010110 | 000101 | 101110 4 chars output T W F u 3 bytes → 4 characters (+33% size) 6-bit value Decimal Char 010011 19 T 010110 22 W 000101 5 F

So "Man" in ASCII becomes "TWFu" in Base64. Every 3 bytes of input produce exactly 4 characters of output, which is why Base64 output is always roughly 33% larger than the original.

When the input length isn't divisible by 3, Base64 adds padding: one = if one byte was left over, two == if two bytes were left. That trailing == you often see isn't meaningful data — it's just alignment.

Where you'll actually run into it

HTTP Basic Authentication is probably the most common encounter. When your curl command sends -u user:password, the client Base64-encodes user:password and puts it in an Authorization: Basic ... header. The first time you decode one of those in production logs and realize the credentials are just sitting there readable, it's a bit unsettling. That's intentional to mention here: Base64 is not encryption, and we'll come back to that.

Data URLs let you embed files directly in HTML or CSS. That <img src="data:image/png;base64,iVBOR..."> thing — the browser decodes the Base64 back to raw bytes and renders the image. Useful for small icons and favicons in single-file HTML documents, or when you want to reduce HTTP requests in an email template.

JSON payloads carrying binary data show up constantly in file upload APIs, webhook signatures, and cryptographic responses. JSON has no native binary type, so the only real option for sending a PDF or a public key through a JSON API is to Base64-encode it. You'll see this in AWS SDK responses, stripe webhook signatures, and email APIs like SendGrid.

JWT tokens use a variant called Base64URL. A typical JWT looks like three Base64URL-encoded sections joined by dots: header.payload.signature. The header and payload are just JSON objects — you can decode them in your browser's console right now with atob(part.replace(/-/g,'+').replace(/_/,'/')). The only secret part is the signature.

Base64URL vs standard Base64

Standard Base64 uses + and /. In a URL, those characters mean something: + is often treated as a space, and / is a path separator. So anything meant to live in a URL — JWT tokens, OAuth state parameters, API keys in query strings — uses Base64URL instead, which swaps + for - and / for _. Padding is also usually stripped.

This trips people up when copy-pasting tokens. If your Base64 decoder is throwing errors on a JWT payload, try replacing - with + and _ with / first.

The security thing, said plainly

Base64 is not encryption. It's not obfuscation. It's barely even inconvenient. Anyone with two seconds and a search engine can decode dXNlcjpwYXNzd29yZA== into user:password.

The reason HTTP Basic Auth is only acceptable over HTTPS is that the Base64 encoding offers zero protection — it's just formatting. Same with embedding API keys in a config file as Base64: if someone gets read access to the file, they have the key.

Every few months someone discovers that a "secret" in their codebase is "encoded" in Base64 and files a security report. Save yourself the trouble: if data needs to be secret, use actual encryption or a secrets manager, not encoding.

A quick mental model for when to use it

Use Base64 when you need to move binary data through a channel that only accepts text, and you're not trying to hide the data. Email attachments, API payloads, embedding small images in HTML, configuration values that happen to be byte arrays — all fine. The 33% size overhead is the main cost to be aware of.

Don't use Base64 as a substitute for encryption, and don't use it to store large binary files in databases or APIs where a proper binary or file storage type exists.


Need to encode or decode Base64 without installing anything? Try the free Base64 Encoder/Decoder — runs entirely in your browser, no data leaves your machine.