Base64 Encoder/Decoder
Encode text to Base64 and decode it back
The decoded bytes aren't UTF-8 text (they may be binary such as an image, compressed data or ciphertext). The � characters are not part of the original data.
Working…
0.0
It hasn't frozen — the result will appear when the calculation finishes.
About Base64 Encoder/Decoder
Base64 rewrites arbitrary bytes using only 64 characters: A–Z, a–z, 0–9, + and /. It exists for the moments when binary data has to travel through a channel built for text — email attachments, HTTP Basic auth headers, JWTs, images embedded as data URIs.
This tool converts your text to UTF-8 bytes first and then writes those bytes as Base64. When decoding, it accepts both the standard alphabet (+ /) and the URL-safe one (- _), and it doesn't care whether trailing = padding, spaces or line breaks are present.
How three bytes become four characters
RFC 4648 splits the input into 24-bit groups of three bytes, cuts each group into four 6-bit pieces, and maps each piece (0–63) to one character of the alphabet. “Man” is the bytes 4D 61 6E; as bits that's 010011 010110 000101 101110 — 19, 22, 5, 46 — which spells TWFu.
If the final group is short, = fills the gap. One leftover byte produces two characters plus ==; two leftover bytes produce three characters plus a single =. So “M” becomes TQ== and “Ma” becomes TWE=. With padding, a Base64 string's length is always a multiple of four.
The output length is ceil(n/3) × 4. A 30,000-byte file becomes exactly 40,000 characters (+33%), while a 100-byte file becomes 136 characters (+36%) because padding weighs more on small inputs. MIME email additionally inserts a CRLF every 76 characters, which pushes a real attachment to roughly +35%.
Base64 is not encryption
There is no key. Anyone with the alphabet table can reverse it — that's literally what the decode button does. A string like dXNlcjpwYXNz looks opaque, but it is just user:pass.
HTTP Basic authentication (RFC 7617) sends “username:password” as Base64 in the Authorization header. Without HTTPS, anyone who sees the header reads the password. JWTs are the same story: the header and payload are Base64url-encoded, not encrypted. The signature stops tampering, but it hides nothing — paste the middle segment of a token here and you'll see the user ID and expiry. That's why secrets and personal data don't belong in a JWT payload.
Base64 is also occasionally used to “obfuscate” config values or API keys in client-side code. It stops casual glances and nothing else; automated secret scanners decode Base64 routinely.
Why btoa() throws on non-English text
The browser's btoa() treats every character of its input as a single byte (0–255). A character like 한 (U+D55C) or 世 doesn't fit, so btoa("世界") throws InvalidCharacterError. The subtler failure is with characters that do fit: btoa("é") succeeds, but it encodes é as the single Latin-1 byte E9, not the two UTF-8 bytes C3 A9. A UTF-8 decoder on the other side then produces garbage.
The correct pipeline is text → UTF-8 bytes → Base64. This tool uses TextEncoder for the first step, so “Hello, 世界” becomes SGVsbG8sIOS4lueVjA== — 13 UTF-8 bytes, not 9 characters. The reverse also matters: if a server Base64-encoded Windows-1252 or Shift_JIS text, this tool decodes it as UTF-8 and you'll see � replacement characters.
Standard Base64 vs Base64url
+ and / have meaning in URLs and file paths. Section 5 of RFC 4648 defines a separate “URL and Filename safe” alphabet that swaps them for - and _. JWTs use that alphabet and also drop the = padding.
The URL-safe option here does the same: +→-, /→_, trailing = removed. “<<???>>” is PDw/Pz8+Pg== in standard Base64 and PDw_Pz8-Pg URL-safe. A classic bug is putting standard Base64 into a query string: a form-style decoder turns + into a space and the value no longer decodes. Either use URL-safe output or percent-encode the value.
Worked examples
Padding in action
- Input
M / Ma / Man- Output
TQ== / TWE= / TWFu
One byte gives 2 characters + ==, two bytes give 3 characters + =, three bytes fill exactly 4 characters.
Non-ASCII text goes through UTF-8
- Input
Hello, 世界- Output
SGVsbG8sIOS4lueVjA==
Each CJK character is 3 bytes in UTF-8, so the input is 13 bytes and the output is ceil(13/3)×4 = 20 characters. btoa() would throw on this input.
Reading a Basic auth header
- Input
dXNlcjpwYXNz (decode)- Output
user:pass
Anyone can do this with the value after “Authorization: Basic”. The protection comes from TLS, not from the encoding.
Where standard and URL-safe differ
- Input
😀- Output
Standard: 8J+YgA== / URL-safe: 8J-YgA
The emoji is 4 bytes (F0 9F 98 80). The + becomes - and the padding disappears in URL-safe mode.
How to use it
- Paste text to encode, or a Base64 string to decode.
- Turn on URL-safe if the result is going into a URL, filename or JWT (applies when encoding).
- Use the swap button to feed the output back in and confirm the round trip.
Key terms
- Padding (=)
- Filler characters that bring the output length to a multiple of four when the last group has fewer than three bytes. They carry no data.
- Base64url
- The RFC 4648 §5 variant that uses - and _ instead of + and /. Used by JWT and in URL parameters.
- UTF-8
- The encoding that stores each Unicode character in 1–4 bytes. ASCII stays 1 byte; CJK characters take 3; most emoji take 4.
Frequently asked questions
Is Base64 a secure way to hide data?
No. It is a reversible notation with no key. Use real encryption for secrets and TLS for data in transit.
Why does my decoded text contain � characters?
The original bytes weren't valid UTF-8. They were probably binary (an image, a zip) or text in another encoding such as Windows-1252. When that happens this tool shows a “not UTF-8 text” warning with a “Show as hex” option, so you can see the actual bytes (gA== → 80). To recover a binary file, use a tool that saves bytes to a file, such as the data URI converter.
Can I strip the trailing = signs?
The length can be reconstructed without them, which is why JWT drops them and why this tool decodes fine without them. Some strict decoders do require padding, so match whatever the receiving system expects.
How much bigger does Base64 make a file?
Every 3 bytes become 4 characters, so ceil(bytes/3)×4. That's +33% for large files, slightly more for tiny ones, and around +35% once MIME line breaks are added.
Do I need to remove line breaks before decoding?
No. MIME wraps at 76 characters and PEM at 64; this tool strips all whitespace before decoding.
Sources
- RFC 4648 — The Base16, Base32, and Base64 Data Encodings
- RFC 7617 — The 'Basic' HTTP Authentication Scheme
- RFC 2045 — MIME Part One (76-character lines)
- MDN — btoa()
Last reviewed: