URL-Safe Base64 (RFC 4648)
Standard Base64 uses + and / — characters with special meaning in URLs. URL-safe Base64 swaps them for - and _, producing output that is safe for use in URLs, cookies, filenames, and JWT tokens without any percent-encoding.
The Problem with Standard Base64 in URLs
Standard Base64 uses three "problematic" characters:
+— interpreted as a space (%20) in URL query strings/— separates path segments in URLs (/api/data)=— used as a key-value separator in query strings
// Standard Base64 in a URL — BROKEN
https://example.com/token?t=aGVsbG8+d29ybGQ=
↑ decoded as space ↑ ends query string?
// If percent-encoded — works but ugly
https://example.com/token?t=aGVsbG8%2Bd29ybGQ%3D
// URL-safe Base64 — clean
https://example.com/token?t=aGVsbG8-d29ybGQ
The Solution: RFC 4648 Section 5
URL-safe Base64 (defined in RFC 4648 §5) makes two substitutions:
Standard → URL-Safe + → - / → _ = → (omitted, optional)
Everything else stays the same — the 62 alphanumeric characters (A-Z, a-z, 0-9) are identical between both variants.
With or Without Padding?
The = padding characters are technically optional in URL-safe Base64. RFC 4648 defines both padded and unpadded variants:
- Padded: output length is always a multiple of 4 (e.g.,
SGVsbG8=) - Unpadded: trailing
=characters are stripped (e.g.,SGVsbG8)
In practice, unpadded URL-safe Base64 is most common — JWTs, OAuth PKCE, and most modern APIs use it.
// Padded URL-safe: "SGVsbG8sIHdvcmxkIQ==" → still has = at end // Unpadded URL-safe: "SGVsbG8sIHdvcmxkIQ" → clean, no padding
Where URL-Safe Base64 Is Used
- JSON Web Tokens (JWT): All three parts (header, payload, signature) are unpadded URL-safe Base64
- OAuth 2.0 PKCE: The
code_verifierandcode_challengeparameters - URL parameters: Passing binary tokens in GET request parameters
- Filenames: Base64-encoded filenames on filesystems that don't allow
/ - Cookies: Cookie values that must avoid special characters
- Email headers: Some MIME encodings
Converting Between Standard and URL-Safe
// JavaScript: standard → URL-safe
function toBase64URL(standard) {
return standard
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
// JavaScript: URL-safe → standard (for decoding)
function fromBase64URL(urlSafe) {
let base64 = urlSafe.replace(/-/g, '+').replace(/_/g, '/');
while (base64.length % 4) base64 += '=';
return base64;
}
## Python import base64 encoded = base64.urlsafe_b64encode(b"Hello, world!") decoded = base64.urlsafe_b64decode(encoded)
## Go
encoded := base64.RawURLEncoding.EncodeToString([]byte("Hello"))
decoded, _ := base64.RawURLEncoding.DecodeString(encoded)
Decoding URL-Safe Base64 with Standard Decoders
Many standard Base64 decoders reject URL-safe input because of the - and _ characters. Always convert back to standard first:
// Browser const decoded = atob(urlSafeBase64 .replace(/-/g, '+') .replace(/_/g, '/') .padEnd(Math.ceil(urlSafeBase64.length / 4) * 4, '='));
FAQ
Is URL-safe Base64 the same as Base64URL?
Yes — "Base64URL" and "URL-safe Base64" refer to the same encoding defined in RFC 4648 §5. The JWT specification calls it Base64URL.
Can I use URL-safe Base64 in HTTP Basic Auth?
No. HTTP Basic Authentication requires standard Base64 (RFC 4648 §4), not the URL-safe variant. The Authorization: Basic header value must use standard Base64.
Try URL-Safe Base64 encoding
Switch to the "URL Safe" tab on base64.dev to encode and decode URL-safe Base64 instantly.
Open base64.dev →