Understanding Base64: How It Works, What It's For, and Common Misconceptions
Base64 represents arbitrary binary data using only 64 ASCII characters. It is not encryption, and it is not compression — it makes data roughly 33% larger. It is ubiquitous anyway because of one property: it lets binary data travel safely through channels that only accept text.
How it works
Base64 groups the input into 3-byte (24-bit) chunks and slices each chunk into four 6-bit pieces. Six bits hold a value from 0 to 63, which maps neatly onto a 64-character alphabet (A–Z, a–z, 0–9, +, /). Three bytes become four characters, so the output is 4/3 the size of the input — about 33% larger.
When the input length isn't a multiple of three, the final group is short and the missing positions are filled with '=' characters. That's why Base64 strings end with zero, one, or two equals signs: one leftover byte produces '==', two leftover bytes produce '='.
'H' = 0x48 = 01001000 'i' = 0x69 = 01101001 Concatenate bits: 01001000 01101001 Slice into 6 bits: 010010 000110 1001(+00 pad) Decimal: 18 6 36 Alphabet: S G k Pad the short group with '=' → SGk=
How to use it
- Paste the text you want to encode, or the Base64 string you want to decode.
- Choose the Encode or Decode direction.
- Copy the result. When decoding, invalid Base64 input produces an error message.
- If the output goes into a URL or filename, read the URL-safe section below first.
Standard Base64 versus URL-safe Base64
The + and / characters used by standard Base64 both mean something special in URLs: + can be read as a space in a query string, and / is a path separator. RFC 4648 therefore defines a 'base64url' variant that swaps those two characters for - and _. JWTs use this variant, and they also drop the = padding.
| Aspect | Standard Base64 | base64url |
|---|---|---|
| 62nd character | + | - |
| 63rd character | / | _ |
| Padding | Uses = | Usually omitted |
| Typical use | MIME, data URIs, HTTP Basic auth | JWTs, URL parameters, filenames |
Why non-ASCII text breaks
Base64 is a specification about bytes. Turning characters into bytes is the job of the layer beneath it — character encoding. To Base64-encode 'héllo', you first encode it as UTF-8 to get the actual bytes, then Base64 those bytes.
The browser's legacy btoa() skips that step and treats each character as a single-byte code point, so anything above U+00FF — CJK text, emoji — throws an InvalidCharacterError. This tool runs input through TextEncoder to get UTF-8 bytes first, so Korean, Japanese, and emoji all work.
If a decode produces mojibake instead, the original bytes were probably encoded with something other than UTF-8, such as EUC-KR, CP949, or Latin-1.
// encode
const bytes = new TextEncoder().encode("héllo");
const b64 = btoa(String.fromCharCode(...bytes));
// decode
const raw = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
const text = new TextDecoder().decode(raw);Where you'll encounter it
- Data URIs: embedding a small icon directly in CSS or HTML to save a request
- HTTP Basic auth: the 'Basic dXNlcjpwYXNz' in an Authorization header is Base64 of user:pass
- JWTs: header and payload are base64url-encoded and joined with dots
- Email attachments: MIME assumes a 7-bit channel, so binary attachments are Base64'd
- Putting an entire certificate or key file on one line in a config file or env var
- Comparing HMAC results as text when verifying webhook signatures
A performance caveat
Embedding images as data URIs saves an HTTP request but often costs more than it saves: the payload grows 33%, the browser can no longer cache the asset separately, and the containing CSS or HTML file gets bigger, delaying first render. As a rule of thumb, icons under 1–2KB are reasonable to inline; anything larger belongs in its own file with cache headers.
Frequently Asked Questions
- Is Base64 encryption?
- No. There is no key and anyone can reverse it instantly, so it provides no security whatsoever. A Base64-wrapped password should be treated as plaintext — this is exactly why HTTP Basic auth is considered unsafe without TLS. Use real encryption like AES to protect a value, or a hash if it should not be reversible.
- What do the trailing = characters mean?
- They're padding, added when the input byte count isn't a multiple of three so the final four-character block is complete. One leftover byte yields '==', two leftover bytes yield '='. Some implementations decode fine without padding, but strict parsers require it, so don't strip it arbitrarily.
- My decoded output is gibberish. Why?
- Check three things. First, the original may be binary — an image or archive — rather than text. Second, it may use a character encoding other than UTF-8, such as EUC-KR or Latin-1. Third, the string may be the base64url variant decoded as standard Base64, or vice versa; if you see - or _ characters, it's base64url.
- Can a long Base64 string contain line breaks?
- The MIME spec (RFC 2045) actually mandates a line break every 76 characters, and most decoders ignore whitespace and newlines. In strict contexts like JWTs, however, an inserted newline invalidates the token.
- Does Base64 compress data?
- The opposite — it turns 3 bytes into 4 characters, growing the payload by about 33%. If you need compression, gzip first and then Base64 the compressed bytes. Doing it the other way round performs poorly, because Base64 output has high entropy and compresses badly.
- Can I encode a file?
- This tool takes text input. For turning an image into a data URI, the Image to Base64 tool is more convenient. On the command line, use base64 -i file.png on macOS or base64 -w 0 file.png on Linux.
💡 Note: Encoding and decoding both run in your browser and your input is never sent to a server. Even so, many organizations prohibit pasting production tokens or personal data into third-party sites — check your policy first.