Base64 is not encryption, and the confusion is expensive
Base64 hides nothing. It exists to move binary data through text-only channels. Treating it as protection is a recurring cause of credential leaks.
Base64 output looks like a secret. It is a dense block of letters and digits, often ending in one or two equals signs, and it bears no resemblance to whatever went in. That appearance is the entire source of a misconception that turns up in code review after code review: the belief that Base64-encoding something protects it.
It does not. Base64 is a public, reversible, key-free transformation. Decoding it requires no secret, because there is no secret. Anyone holding the string can recover the original in the time it takes to paste it into a decoder.
What it is actually for
Base64 solves a transport problem that predates the web. Plenty of channels — email headers, URLs, JSON string values, XML attributes, HTTP headers — accept only a restricted set of text characters. Binary data contains bytes that those channels either reject or silently mangle: null bytes, control characters, whatever the local newline convention decides to rewrite.
Base64 takes arbitrary bytes and re-expresses them using 64 characters that survive every text channel intact: A–Z, a–z, 0–9, plus two extras. It reads three bytes at a time and emits four characters, which is why the output is about 33% larger than the input, and why the padding = appears when the input length is not a multiple of three.
That is the whole job: make binary data survive a text-only pipe. It is an envelope, not a lock.
Where the confusion causes damage
Credentials in configuration
A database password Base64-encoded in a config file, or committed to a repository, is a plaintext password with an extra step. Kubernetes Secrets are the canonical example: their values are Base64-encoded, which leads a steady stream of teams to assume they are encrypted at rest. They are not, by default. Anyone with read access to the secret has the credential.
JWTs read as opaque tokens
A JSON Web Token is three Base64url-encoded segments separated by dots. The signature makes the token tamper-evident — you cannot change the claims without invalidating it. It does nothing to make the token private. The payload is readable by anyone holding the token, which our JWT decoder demonstrates in one paste.
The practical consequence: never put anything in a JWT payload that the bearer should not read. Internal user IDs are fine. Email addresses are a judgement call. Roles that reveal your authorisation model, internal hostnames, or anything resembling personal data are a mistake, because the token sits in browser storage and travels through logs.
"Obfuscated" strings in client-side code
An API key Base64-encoded in a JavaScript bundle is an API key published on the internet. Automated scanners look for exactly this pattern, and they find it faster than a human would. The same goes for scripts and payloads: encoding does not defeat inspection, and security tooling decodes it as a matter of routine.
What to use instead
Once you separate the goals, the choices are straightforward:
- To move binary through a text channel: Base64. This is what it is for, and it is the right tool.
- To keep something secret: encryption — AES-GCM for data you must read back, with a key you manage properly. A secrets manager exists so that you are not inventing this.
- To verify something without storing it: a hash. One-way by design.
- To store a password: a slow, salted password hash — bcrypt, scrypt or Argon2. Never a plain SHA-256, and never anything reversible.
A note on Base64url
Standard Base64 uses + and /, both of which have meaning inside a URL, and its = padding needs escaping in a query string. Base64url swaps those for - and _ and usually drops the padding. It is the variant JWTs use.
The two are not interchangeable, and mixing them is a common source of "invalid token" errors that look mysterious until you notice a - where a + should be. A decoder that handles both, as ours does, saves a certain amount of confusion.
The rule
If a transformation requires no key, it provides no confidentiality. Base64 requires no key. It is a way of writing bytes down, and it is a good one — but it belongs in the same mental category as hexadecimal, not the same one as encryption.