Base64 is the most-misused pseudo-security operation I’ve seen. A backend dev proudly announces “I Base64-encrypted this token”; the frontend dev nods politely, then reverses it in one line.

This article exists so that next time you read “Base64 encrypted” you can immediately say—this is not encryption.

30-second overview

  • Base64 is encoding, not encryption. It maps binary data to 64 printable characters. Anyone who sees the string can reverse it to the original bytes.
  • One line to reverse: Buffer.from(str, ‘base64’).toString() in Node.js, atob(str) in the browser. Done.
  • Its real job: lets binary data ride text-only channels—JSON, email bodies, URL query strings.
  • Not for hiding passwords, tokens, or API keys. For those you need actual encryption: AES, libsodium, age, GPG.

5 real-world scenarios where Base64 is wrong

Scenario 1: “Encrypting” passwords in config files

db_password=cm9vdC1wYXNzLXdvcmQ=

Believe it or not, that string decodes to root-pass-word.

Why teams fall for it: Config files are the most-leaked asset in any repo. Base64 looks like it added a password, but anyone with the file reverses it in 5 seconds.

The fix: use SOPS, age, Vault, or at minimum AES-GCM. Base64 is masking, not encryption.

Scenario 2: JWT “encrypting” the payload

eyJhbG…lKxw

The middle blob is usually Base64URL. Drop it into any online JWT decoder—user ID, expiry, scopes are all right there.

Why teams fall for it: JWT signatures trick people into thinking “invisible = secure”. The payload is never encrypted; that’s explicit in the JWT spec—signed, not encrypted. If you want the payload encrypted, use JWE.

Scenario 3: “Encrypting” your API key in docs

Authorization: Basic YWRtaW46cGFzc3dvcmQ=

That decodes to admin:password.

Why teams fall for it: Authorization: Basic … shows up in tutorials everywhere; newcomers copy it without realizing the blob after Basic is just base64-encoded username:password in plaintext.

Scenario 4: “Hiding” sensitive IDs in URLs

/users/details?token=MTIzNDU2Nzg5MDEyMzQ1Ng==

Wrap an internal ID in Base64, drop it in a URL, hope no one guesses the underlying primary key.

Why teams fall for it: This is obscurity through encoding. Base64 strings look like hash / ciphertext, but IDs are usually sequential integers, and Base64 just adds a layer of guessing, not security. Someone walking IDs in order walks the encoded form in order too.

Scenario 5: Pasting “encrypted” code snippets in Slack or email

Someone pastes: decrypt this before prod, the secret is base64 encoded Reply: what? Sender: me, the original was secret_api_key_here_in_plain

I swear on failed projects this scenario exists.

Why teams fall for it: Assuming Base64 dodges search, copy, screenshot, or OCR. It doesn’t—Base64 strings look distinctive and are exactly what automated traffic-audit tools look for.

4 counterintuitive facts about Base64

Fact 1: Base64 strings are 33% longer than the original

Encoding grows the data. 3 bytes become 4 Base64 characters, so aGVsbG8= is longer than hello. If you’re calling your encoding “encryption” and complaining the output is longer, you picked the wrong tool.

Fact 2: Base64 is not a hash

Hashes are one-way (theoretically irreversible), Base64 is two-way (fully reversible). They’re different tools for different jobs. Anyone using Base64 to “hash” passwords and store them in a database stored no hash at all—any attacker decodes them directly.

Fact 3: Base64 is not compression

It’s just a character set swap. No data is removed. aGVsbG8= always takes ≥ the bytes of hello + padding.

Fact 4: The browser btoa only supports Latin-1

Calling btoa(‘你好’) throws InvalidCharacterError because btoa only encodes code points 0–255. That’s why our Text Encoder tool goes TextEncoder().encode() then btoa then TextDecoder().decode(), so it’s UTF-8 safe end-to-end.

  1. Protecting passwords / tokens / API keys: use real encryption. AES-256-GCM, libsodium (crypto_secretbox_easy), age, GPG—pick one, never Base64.
  2. Stuffing binary into JSON or URLs: use Base64, that’s its job. Our Text Encoder tool’s Base64 tab defaults to the UTF-8-safe chain, decode aGVsbG8= and see hello.
  3. URL-safe binary transport: use Base64URL (- and _ in place of + and /, no padding). Pairs with JWT.
  4. Embedding images in HTML/CSS: use data:image/…;base64,… — but the HTML is +33% larger and can’t be CDN-cached, so use sparingly.
  5. Teaching newcomers Base64: emphasize this is a moving truck, not a vault. Trucks move furniture from A to B and any mover can see the contents; vaults (Fort Knox) are what you want for actual confidentiality.

Base64 is, by spec, a character encoding scheme (RFC 4648)—just a transport. Writing hello then مرحبا then hello again is pure movement with no security meaning. If you need security, you need real cryptographic primitives.

Try our Text Encoder tool, switch to the Base64 tab, paste any string and encode/decode instantly—see the encoding-vs-encryption difference in a second. If you want to compare against hashes (HMAC, SHA-256), see our crypto-tools.