What is URL-safe Base64?
URL-safe Base64, defined in RFC 4648 §5 and sometimes called Base64URL or Base64-URL, is a variant of standard Base64 designed for use in URLs, filenames, and other contexts where the +, /, and = characters cause problems. The encoding uses the same 64-symbol alphabet as standard Base64 with two substitutions: + (index 62) becomes -, and / (index 63) becomes _. The = padding character at the end of the output is optional — most implementations strip it.
The result is an alphabet — A-Z a-z 0-9 - _ — that is safe to embed anywhere a URL is valid: as a path segment, a query parameter value, a fragment identifier, an HTTP header value, a cookie value, or a filename on every mainstream operating system. No further percent-encoding is required, which keeps URLs shorter and human-readable.
Why not just URL-encode standard Base64?
You could take a standard Base64 string and percent-encode + to %2B, / to %2F, and = to %3D — that's what happens implicitly when you paste standard Base64 into a URL. The problem is size and complexity. A 40-byte Base64 string with 20% +// characters becomes ~48 bytes after percent-encoding. Base64URL avoids the round-trip entirely: the output is already URL-safe with zero additional escaping.
It also avoids double-encoding bugs. Percent-encoded values get decoded once by the URL parser, but some middleware (proxies, load balancers, CDN edge nodes) decodes URL characters more than once. If the recipient decodes twice, %2B becomes + becomes something wrong. Base64URL sidesteps this whole class of problems by never using characters that need URL encoding.
Real-world uses
JWTs (RFC 7515). Every JWT segment — header, payload, signature — is Base64URL without padding. This is not optional; standard Base64 in a JWT causes signature validation to fail on every conformant library.
OAuth 2.0 PKCE (RFC 7636). The code_verifier is a random string; the code_challenge is Base64URL(SHA-256(code_verifier)) with no padding. Padding characters would break the challenge match on the server side.
WebAuthn credentials. Client Data JSON, credential IDs, and signatures in the Web Authentication API are all Base64URL-encoded per the W3C WebAuthn spec.
Filenames and cache keys. Content-addressed storage systems (IPFS CIDs, S3 object keys built from hashes) use Base64URL because / would create fake path separators and + would cause shell quoting problems.
Cryptographic nonces in APIs. Stripe setup intents, Twilio verification codes, Slack signing secrets — many API providers use Base64URL for anything they generate that a client will embed in a URL.
Implementation in different languages
Every mainstream language has native Base64URL support. Avoid rolling your own — subtle bugs in padding handling or character substitution have caused real security incidents.
JavaScript / TypeScript (browser)
function base64UrlEncode(bytes) {
const b64 = btoa(String.fromCharCode(...bytes));
return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
// Encode a string:
const utf8 = new TextEncoder().encode('Hello, world?');
const urlSafe = base64UrlEncode(utf8);
// → 'SGVsbG8sIHdvcmxkPw'Node.js (built-in)
const urlSafe = Buffer.from('Hello, world?', 'utf8').toString('base64url');
// → 'SGVsbG8sIHdvcmxkPw'Python (standard library)
import base64
data = 'Hello, world?'.encode('utf-8')
url_safe = base64.urlsafe_b64encode(data).rstrip(b'=').decode('ascii')
# → 'SGVsbG8sIHdvcmxkPw'Go (standard library)
import "encoding/base64"
encoded := base64.RawURLEncoding.EncodeToString([]byte("Hello, world?"))
// → "SGVsbG8sIHdvcmxkPw"
// RawURLEncoding uses URL-safe alphabet AND omits paddingPadding — to include or not
The = padding at the end of Base64 output pads the length to a multiple of 4. Standard Base64 requires it. URL-safe Base64 makes it optional. In practice, strip it — every major spec that uses Base64URL (JWT, PKCE, WebAuthn) omits padding, and most decoders accept both.
The one exception is if you're feeding the output into a strict RFC 4648 §4 decoder that doesn't support Base64URL natively. Then you need to add the padding back before decoding: pad the string with = until its length is divisible by 4, and substitute - → +, _ → /. All modern languages have a urlsafe_b64decode or equivalent that handles both cases automatically.
Related Base64 & Encoding Tools
- Base64 Encoder (Parent Tool) — the underlying encoder used by every variant on this page
- Base64 Encode Online — general-purpose text encoder with copy-to-clipboard
- Text to Base64 — convert plain text or UTF-8 to Base64
- Base64 Encode in JavaScript — btoa(), TextEncoder, and Buffer.from() patterns
- Base64 Encode in Python — base64.b64encode() reference and examples
- Base64 Decoder — reverse the encoding — Base64 back to text or file
- Base64 to Image Converter — decode a data URI back into a viewable image file