Inputs

Base64 in a nutshell

Base64 encodes binary data using 64 printable characters (A-Z, a-z, 0-9, plus + and /) so it can travel through text-only channels โ€” email headers, JSON, URLs, HTTP headers. Every 3 bytes of input become 4 characters of output, so encoded data is roughly 33% larger than the original.

Standard vs URL-safe

  • Standard uses + and /, padded with = to a multiple of 4. Works for email and most APIs.
  • URL-safe (RFC 4648) swaps +โ†’- and /โ†’_ so the string is safe in URLs and filenames. Padding is usually omitted. Used in JWT, OAuth, and modern web APIs.

Common uses

  • Email attachments (MIME)
  • Embedding small images in CSS/HTML (data: URIs)
  • Encoding binary tokens, API keys, signatures
  • HTTP Basic Auth (username:password is base64-encoded)
Important

Base64 is encoding, not encryption. Anyone can decode it instantly. Don't use base64 to "hide" sensitive data.

What Base64 is actually doing

Base64 encoding takes arbitrary binary data โ€” an image, a certificate, a private key, a compressed archive, whatever โ€” and represents it as a string of 64 specific ASCII characters that survive being pasted into text-only systems. It doesn't encrypt anything. It doesn't compress anything. It just translates bytes into a form that email systems, JSON documents, HTTP headers, and other text-oriented formats can carry without corruption.

The core operation is turning every 3 bytes of input (24 bits) into 4 output characters (6 bits each). Those 4 characters are drawn from a fixed alphabet: A-Z, a-z, 0-9, plus two symbols. In standard Base64 those symbols are + and /, plus = as a padding character to round the output length to a multiple of 4. The URL-safe variant substitutes - and _ for + and / because forward slashes and plus signs have meaning in URLs and cause parsing bugs when they appear unescaped in Base64 values embedded in query strings.

The trade-off is size. Base64 output is roughly 33% larger than the original binary โ€” every 3 bytes becomes 4 characters. That's an acceptable cost for making binary data transportable through text-only channels, but it's the reason you don't Base64 things you don't have to.

Where I actually deal with Base64

Reading certificate files

TLS certificates and their associated private keys are stored in PEM format, which is Base64-encoded binary wrapped between BEGIN and END markers. When I open a .pem or .crt file, I see something like MIIDazCCAlOgAwIBAgIUJ... for hundreds of lines. That's Base64. The underlying binary is a DER-encoded X.509 certificate, but nobody looks at DER directly โ€” the PEM wrapping is what tools like openssl and web servers actually consume.

When I need to inspect what's inside a certificate โ€” the subject, issuer, expiration date, SANs, signature algorithm โ€” I run it through openssl x509 -in cert.pem -text -noout, which decodes the Base64 back to DER and then parses the ASN.1 structure into human-readable form. The SSL/TLS Cert Inspector tool on this site does the same thing for any HTTPS site's certificate, no openssl required.

Data URIs in HTML and CSS

An image can be embedded directly in an HTML page as a data URI: <img src="data:image/png;base64,iVBORw0K...">. This trades a larger HTML document for one fewer HTTP request. It's useful for tiny icons, email templates where external images might be blocked, and single-file HTML documents that need to be self-contained. I use it occasionally for logos in reports that need to be emailed as a single attachment.

The size penalty makes data URIs a bad choice for large images. A 10 KB PNG becomes about 13.3 KB of Base64, which then gets transmitted every time the HTML is loaded (unlike a real image file which the browser can cache separately). For anything bigger than a small icon, external image files are almost always the better choice.

Email attachments

MIME email uses Base64 to encode binary attachments so they survive being carried through the historically text-only SMTP protocol. Modern SMTP servers all support 8-bit clean transfer, so this isn't strictly required anymore, but the standard hasn't changed and Base64 remains the safe default. When you look at the raw source of an email with an attachment, that giant block of gibberish characters in the middle is Base64-encoded binary.

Because Base64 is line-wrapped in MIME (traditionally to 76 characters per line), you sometimes see attachments rejected because the encoding has been corrupted in transit โ€” a mail relay unfolded the lines wrong, or a system stripped whitespace it thought was insignificant. If an attachment arrives corrupted, checking the raw source for Base64 formatting issues is one of the first troubleshooting steps.

JSON Web Tokens

A JWT is three Base64-encoded parts joined by dots: a header, a payload, and a signature. The header and payload are JSON documents; the signature is binary. Base64URL is used (not standard Base64) because JWTs are meant to be safe in URLs and cookies. If you paste a JWT into the JWT Decoder, it splits the token on the dots, Base64URL-decodes each part, and shows you the readable JSON โ€” no signature verification, just the decode step, so you can see what claims a token is carrying.

JWT payloads are Base64-encoded but not encrypted. Anyone with a JWT can read what's inside it. The signature is what prevents tampering โ€” modifying the payload invalidates the signature, and any server that checks the signature will reject the modified token. This is a source of confusion for people who assume Base64 provides secrecy. It provides transportability, not confidentiality.

HTTP Basic Authentication

The classic Authorization: Basic dXNlcjpwYXNz HTTP header is Base64-encoded credentials in the form username:password. Anyone who captures the header sees the exact credentials โ€” Base64 offers no security here, only encoding. This is why HTTP Basic Authentication should only ever be used over HTTPS. Over plain HTTP it's the equivalent of shouting your password across a crowded room.

Modern APIs mostly use bearer tokens (OAuth, JWTs, API keys) instead of Basic Auth for anything user-facing. But Basic Auth is still common for machine-to-machine communication where the credentials are known configuration values, and reading the encoded string back to the original username and password is a common troubleshooting step.

Encoding binary in text config files

Sometimes an application needs a binary blob in its configuration file โ€” an SSH key, a certificate, a signing secret. Rather than referencing an external file (which adds a filesystem dependency), the blob can be embedded in the YAML, JSON, or TOML config file as a Base64-encoded string. Kubernetes Secrets do this: the actual secret values are Base64-encoded in the manifest, then decoded when consumed by pods.

Worth noting: Kubernetes Base64-encoding does not encrypt the secret. It just makes binary data storable in YAML. Anyone who can read a Kubernetes Secret manifest can decode the values instantly. Real secret management requires additional tooling (sealed-secrets, external-secrets-operator, Vault, cloud KMS integration).

The URL-safe variant

Standard Base64 uses + and / as two of its characters and = for padding. All three cause problems in URLs:

  • + is interpreted as a space in URL query strings (a legacy of the application/x-www-form-urlencoded encoding).
  • / is the path separator, so it can't appear inside a URL segment without being interpreted structurally.
  • = is used to separate query parameter keys from values, so it can appear ambiguously.

URL-safe Base64 (also called Base64URL, defined in RFC 4648) replaces + with - and / with _, and traditionally omits the trailing = padding. This lets Base64-encoded data appear in URLs, headers, and cookies without needing further URL-encoding.

JWTs use URL-safe Base64. Web APIs that return signed URLs often use URL-safe Base64. Anything that has to be embedded in a URL should use the URL-safe variant.

Common mistakes and gotchas

Encoding and decoding with the wrong variant

If a system encodes with standard Base64 (+, /) and another system tries to decode as URL-safe (-, _), the characters won't match the alphabet and decoding fails or produces garbage. When crossing system boundaries, know which variant is being used and stay consistent.

Assuming decoded output is text

Base64 encodes binary. When you decode, you get bytes back. If those bytes happen to be UTF-8 text, you can display them; if they're binary (an image, a compressed archive, a certificate), decoding to a text field just gives you gibberish. Always know what the underlying content is before displaying the decoded result.

Whitespace inside the encoded string

Base64 strings sometimes contain newlines or spaces (from being formatted for readability, or from being wrapped by an email client). Most decoders tolerate whitespace inside Base64 strings, but not all. If a decode operation fails, stripping whitespace first is worth trying.

Padding differences

Standard Base64 always pads to a multiple of 4 characters with = signs. URL-safe Base64 sometimes drops the padding. Some strict decoders reject unpadded input; others accept it. If decode fails and the input might be URL-safe, try adding = signs to round the length up to a multiple of 4.

Case sensitivity

Base64 is case-sensitive. Uppercase A and lowercase a are different characters representing different values. Systems that fold case (some legacy database columns, some hash lookups) will corrupt Base64 data.

What Base64 is not

Base64 provides no confidentiality. Anyone can decode it. If you Base64-encode a password before sending it, the password is still visible to anyone who intercepts the traffic. Base64 also provides no integrity โ€” a single character flip in a Base64 string produces different bytes on decode, but nothing detects the modification. Anything that needs security has to add encryption (for confidentiality) or a MAC / signature (for integrity) on top.

Base64 also isn't compression. The output is always larger than the input. If size matters, compress the data first (gzip, brotli, zstd) and Base64-encode the compressed output. Doing it the other way around wastes CPU with no size benefit.

Everything runs in your browser

This tool encodes and decodes entirely in JavaScript on your device. Nothing you paste is sent to the server. This matters when you're working with sensitive data โ€” a Base64-encoded private key, a JWT with real claims, a certificate you don't want on public logs. The encoding happens in the browser, the decoded output is displayed in the browser, and there's no round trip to any server. You can verify this by opening the browser's developer tools, going to the Network tab, and watching what happens when you click Encode or Decode. Nothing should transit.