Base64 vs Base64URL: What Is the Difference
Base64 and Base64URL use two different characters and padding rules. Learn when each is correct, why URLs and JWTs need the URL-safe form, and how to convert.
Base64 and Base64URL encode the same bytes in almost the same way. They differ in two characters and in whether = padding is used, and mixing them up is a common cause of "invalid character" errors when handling tokens, URLs and file names.
Use the Base64 tool to encode or decode in either form and see the difference on your own data.
Base64 Encoder & DecoderEncode text to Base64 or decode it back. Unicode is handled correctly, so Japanese, Chinese, Korean and emoji all round-trip without corruption.What Base64 does
Base64 turns arbitrary bytes into text made of 64 safe characters, so binary data can travel through systems built for text such as JSON, email and HTML. Every 3 bytes become 4 characters, so the output is about a third larger than the input. If the input length is not a multiple of 3, the output is padded with =.
Standard Base64 (RFC 4648) uses this alphabet: A-Z, a-z, 0-9, + and /.
What changes in Base64URL
Two of the standard characters are awkward inside URLs and file names, so the URL-safe variant replaces them.
| Standard Base64 | Base64URL | |
|---|---|---|
| Character 62 | + | - |
| Character 63 | / | _ |
| Padding | = usually kept | = often omitted |
| Typical use | Email, data URIs, PEM files | JWTs, URL parameters, file names |
Why the difference matters
+in a URL query string is read as a space, so a standard Base64 value can be silently corrupted./is a path separator, so it can split a value across URL segments.=separates keys from values in a query string and often needs escaping.
That is why JWTs, which are passed in headers and URLs, use Base64URL without padding for each of their three parts.
Converting between them
To go from standard Base64 to Base64URL, replace + with - and / with _, and strip any trailing =. To go back, reverse the replacements and add = until the length is a multiple of 4.
const toBase64Url = (b64) =>
b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const fromBase64Url = (s) => {
const b64 = s.replace(/-/g, '+').replace(/_/g, '/');
return b64 + '='.repeat((4 - (b64.length % 4)) % 4);
};
Common errors
atobfails on a JWT segment. The segment is Base64URL; convert it with the function above first.- Garbled non-English text.
btoaonly handles Latin-1 characters. Encode text as UTF-8 bytes first, then encode the bytes. - Decoded output looks like noise. The data may be binary (an image, a hash) rather than text, which is expected.
- Whitespace or line breaks. Some encoders wrap output at 64 or 76 characters; strip line breaks before decoding if your decoder is strict.
Related tools
If the value ends up in a URL, you may also need percent-encoding, which is a different mechanism from Base64URL. If it came from a token, the JWT decoder splits and decodes the parts for you.
URL Encoder & DecoderPercent-encode text for use in a URL, or decode it back. Choose whether you are encoding one query value or an entire URL, because the two need different escaping. JWT DecoderPaste a JWT to read its header and payload and see when it expires. Decoding happens entirely in your browser, so the token never leaves your device.