env.dev

Base64 Encoding Explained

Understand Base64 encoding end-to-end: how the algorithm maps bytes to 64 characters, when to use it, what padding means, and why it inflates size by 33%.

Last updated:

Base64 is an encoding scheme that converts binary data into a string of 64 printable ASCII characters. It is not encryption — it is purely a way to represent arbitrary bytes as text.

Why does Base64 exist?

Many protocols (email, HTTP headers, URLs, XML) were designed to handle text only. Binary data like images or files cannot be embedded directly. Base64 bridges this gap by representing any byte sequence as printable characters that survive text-safe transport.

How does Base64 encoding work?

Base64 processes input 3 bytes at a time (24 bits) and outputs 4 characters from a 64-character alphabet:

text
A–Z (26)  a–z (26)  0–9 (10)  + /  (2)  = (padding)
─────────────────────────────────────────────────
Input bytes:   M        a        n
Binary:     01001101 01100001 01101110
Split 6-bit: 010011  010110  000101  101110
Base64 idx:    19      22       5      46
Output:         T       W       F      u

How do you encode and decode Base64 from the CLI?

Every major OS, runtime, and crypto toolkit ships a Base64 encoder. The snippets below all encode the bytes hello to aGVsbG8= and back.

macOS / Linux (coreutils)

bash
# Encode (use -n to avoid a trailing newline being encoded)
echo -n 'hello' | base64
# aGVsbG8=

# Decode
echo 'aGVsbG8=' | base64 -d
# hello

OpenSSL

bash
openssl base64 -in input.bin -out input.b64
openssl base64 -d -in input.b64 -out input.bin

Node.js

javascript
Buffer.from('hello').toString('base64');
// 'aGVsbG8='

Buffer.from('aGVsbG8=', 'base64').toString('utf8');
// 'hello'

Python

python
import base64
base64.b64encode(b'hello')          # b'aGVsbG8='
base64.b64decode(b'aGVsbG8=')       # b'hello'

PowerShell

powershell
[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('hello'))
# aGVsbG8=

[Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('aGVsbG8='))
# hello

What does Base64 padding (=) mean?

Input is padded to a multiple of 3 bytes. If 1 byte is left over, 2 = characters are appended. If 2 bytes remain, 1 = is appended. This ensures decoders know the original length.

text
"M"   → "TQ=="  (1 byte → 2 chars + 2 padding)
"Ma"  → "TWE="  (2 bytes → 3 chars + 1 padding)
"Man" → "TWFu"  (3 bytes → 4 chars, no padding)

Where is Base64 used?

Data URIs

Embed images and fonts directly in HTML/CSS without a separate request. Convert files quickly with the Image to Base64 tool.

data:image/png;base64,iVBOR…

Email attachments

MIME encodes binary attachments as Base64 for safe transport over SMTP.

Content-Transfer-Encoding: base64

JWT tokens

JWT header and payload are Base64URL-encoded (a URL-safe variant). See the JWT guide for the full structure.

eyJhbGciOiJIUzI1NiJ9…

API credentials

HTTP Basic Auth encodes username:password as Base64 in the Authorization header. Inspect bearer tokens with the JWT Debugger.

Authorization: Basic dXNlcjpwYXNz

What is the difference between Base64 and Base64URL?

Standard Base64 uses + and /, which are special characters in URLs. Base64URL replaces them with - and _, and omits padding. Used in JWTs, OAuth tokens, and URL-safe identifiers.

VariantChars 62/63Padding
Standard Base64+ /Yes (=)
Base64URL- _No

Why does Base64 add 33 % overhead?

Base64 increases data size by approximately 33%: every 3 bytes become 4 characters. For large binary files, this overhead is worth noting when bandwidth matters.

Common Base64 pitfalls

  • Standard Base64 in URLs. The +, /, and = characters get percent-encoded or break path parsing. Use Base64URL for anything in a URL, query string, or filename.
  • Padding stripped or required. Some libraries (notably JWT decoders) drop trailing =, while strict RFC 4648 decoders reject unpadded input. Re-add padding to a multiple of 4 before decoding when in doubt.
  • Double-encoding. Encoding an already-encoded payload (encode-then-encode) inflates size by 33 % per pass and silently corrupts downstream consumers that decode only once.
  • MIME line wrapping. RFC 2045 wraps Base64 output at 76 characters with \n. Strict decoders that expect a single line (some JWT and crypto libs) will fail until you strip the newlines.
  • 33 % bloat in cookies and JWTs. Browsers cap cookies near 4 KB and many gateways cap headers at 8 KB — Base64-encoding a 6 KB binary blob will not fit. Compress before encoding, or pass an opaque reference instead.

References

Encode and decode Base64 strings instantly with the Base64 Encode / Decode tool.

Was this helpful?

Read next

JWT Best Practices: Storage, Algorithms & Revocation

Security best practices for JSON Web Tokens: algorithm selection, storage, expiration, refresh patterns, revocation, and common vulnerabilities.

Continue →

Frequently Asked Questions

Is Base64 encryption?

No. Base64 is an encoding scheme, not encryption. Anyone can decode a Base64 string without a key. It provides no security and should never be used to protect sensitive data.

Why does Base64 increase file size?

Base64 encodes 3 bytes of binary data into 4 ASCII characters, resulting in roughly a 33% size increase. This overhead is the trade-off for being able to represent binary data as text.

What is the difference between Base64 and Base64URL?

Standard Base64 uses + and / characters which are special in URLs. Base64URL replaces them with - and _, and omits padding (=). It is used in JWTs, URL parameters, and file names.

How do I encode and decode Base64 in the terminal?

macOS/Linux: `echo -n hello | base64` and `echo aGVsbG8= | base64 -d`. With OpenSSL: `openssl base64 -in file -out file.b64`. Node: `Buffer.from(s).toString("base64")`. Python: `base64.b64encode(b"hello")`.

Stay up to date

Get notified about new guides, tools, and cheatsheets.