← Back to all articles

Base64 Is Not Encryption: Encoding vs Encryption

EncodingEncryptionBeginner

A common misconception

"Let me Base64 the password so it is safe" — a frequent beginner mistake. Base64 looks like gibberish, but it has nothing to do with encryption: Base64 is encoding, not encryption.

The fundamental difference

  • Encoding exists so data can travel or be stored safely. It is fully reversible and needs no key — anyone can decode it instantly.
  • Encryption exists so people without the key cannot read the data. It depends on a key.
  • Hashing is one-way, used to verify integrity or store password digests.

Base64 maps binary data onto 64 printable characters (A-Z, a-z, 0-9, +, /) so it can travel through text-only channels such as email, URLs and JSON.

Recognize it at a glance

  1. Characters are limited to A-Z, a-z, 0-9, + and /;
  2. Length is a multiple of 4: 3 bytes become 4 characters, roughly +33% in size;
  3. It often ends with = or == padding.

Which one to use

Carrying binary data inside a text protocol (inline images, JWT, attachments)? Use Base64. Need secrecy? Use symmetric encryption such as AES with a random key. Need to verify nothing changed? Use a hash like SHA-256. They are often combined, but never interchangeable.

A practical decision table

GoalUseWhy
Carry binary inside JSON / URL / emailBase64Reversible, keyless — solves transport only
Keep data unreadable to othersSymmetric encryption (AES-GCM)Undecryptable without the key, and tamper-evident
Check whether a file changedHashing (SHA-256)One-way; a single changed bit yields a totally different digest
Store user passwordsbcrypt / Argon2Built-in salt and slow hashing raise brute-force cost

Code examples

// Browser: convert to UTF-8 bytes first, or btoa throws on non-Latin-1
const encoded = btoa(String.fromCharCode(...new TextEncoder().encode('hello')));
const decoded = new TextDecoder().decode(
  Uint8Array.from(atob(encoded), c => c.charCodeAt(0))
);

// Node.js: UTF-8 is native — easiest option
const b64 = Buffer.from('hello', 'utf8').toString('base64');
const back = Buffer.from(b64, 'base64').toString('utf8');

Three common mistakes

  • Treating Base64 as encryption: hiding a password this way is undone by one line of decoding;
  • Calling btoa on non-ASCII text: it only accepts Latin-1 and throws otherwise — encode to bytes first;
  • Inlining large files as Base64: about 33% bigger and it delays first paint — skip it beyond a few KB.

Follow-up questions

Why does JWT use Base64Url? Because + and / get escaped or truncated inside URLs, so JWT swaps them for - and _ and drops the = padding. Does Base64 compress data? No — it grows the payload; it only makes it printable.

Try them: Base64 encoder/decoder, symmetric encryption, hashing

Explaining the distinction to others

The confusion is usually about wording, not understanding. These analogies work well.

  1. Envelope versus safe: Base64 puts a document in a standard envelope anyone can open; encryption locks it in a safe. They solve entirely different problems.
  2. Interchange versus access control: encoding exists so different systems can read the data; encryption exists so the wrong people cannot. Mistaking format conversion for access control is using the tool backwards.
  3. How you verify: to test whether data is merely encoded, try decoding it; to test encryption, check whether you hold a key. This is the most overlooked and most clarifying point.
  4. They combine in practice: real systems encrypt for confidentiality, encode for transport and hash or sign for integrity, each layer doing its own job.

Making it stick in a team

Write "never substitute encoding for encryption" into your conventions, and treat "it looks like gibberish" as a red flag in review rather than proof of safety. Provide a shared encryption utility and key-management process so the right path is the easier path — only then does the rule get followed.

How to document it

Put a comparison table in your docs: purpose, reversibility, key requirement and integrity verification. Keeping those four columns visible catches most misuse during design rather than in a security review, and onboarding should cover it — it is a baseline concept.