URL-Safe Base64 — What It Is, Why It Exists, and When to Use It
Table of Contents
Standard Base64 uses 64 characters: A-Z, a-z, 0-9, and two symbols: + and /. The problem is that both + and / have special meaning in URLs. A + in a URL query string is interpreted as a space. A / is a path separator. This means that a standard Base64 string embedded in a URL can be silently corrupted or misrouted by web servers, proxies, and browsers.
URL-safe Base64 (also called base64url) was created specifically to solve this. It is identical to standard Base64 except for two character substitutions that eliminate the URL conflicts.
The Two Changes That Make Base64 URL-Safe
Base64url differs from standard Base64 in exactly two ways:
| Character | Standard Base64 | URL-Safe Base64 |
|---|---|---|
| 62nd character | + (plus sign) | - (hyphen) |
| 63rd character | / (forward slash) | _ (underscore) |
Additionally, standard Base64 pads output to a multiple of 4 characters using = signs. Base64url typically omits this padding because = also requires percent-encoding in URLs. Whether padding is included depends on the specific application — JWT tokens omit it, some other systems include it.
Every other character (A-Z, a-z, 0-9) is identical between the two variants. Only those two symbols change.
Where You Encounter Base64url in Practice
JWT tokens (JSON Web Tokens) are the most common place you will encounter base64url. A JWT looks like three base64url strings separated by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0In0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
All three parts — the header, payload, and signature — use base64url encoding. If standard Base64 were used, any + or / characters in the encoded output would break the token when placed in a URL or HTTP Authorization header.
OAuth 2.0 and OIDC — authorization codes, PKCE verifiers and challenges, and state parameters are all base64url-encoded values passed through URLs.
Web Crypto API — browser cryptography operations often produce binary output that gets base64url-encoded before storage or transmission.
Kubernetes secrets — use standard Base64, not base64url. This is a common point of confusion. If you are decoding a Kubernetes secret, use a standard Base64 decoder, not a base64url decoder.
Sell Custom Apparel — We Handle Printing & Free ShippingConverting Between Standard and URL-Safe Base64
If you have a base64url string and want to decode it with a standard Base64 decoder, you need to convert it first:
- Replace all
-(hyphens) with+ - Replace all
_(underscores) with/ - Add
=padding until the string length is a multiple of 4
In code:
// JavaScript — base64url to standard base64
function base64urlToBase64(str) {
return str.replace(/-/g, '+').replace(/_/g, '/')
+ '=='.slice(0, (4 - str.length % 4) % 4);
}
atob(base64urlToBase64(jwtPayload));
Most modern JWT libraries handle this automatically, so you rarely need to do the conversion by hand. But understanding it helps when debugging token issues — if your decoder produces garbage, check whether the source string uses hyphens/underscores (base64url) or plus signs/slashes (standard Base64).
Decoding Base64url Strings — What Works and What Does Not
Our Base64 encoder/decoder handles standard Base64. If you paste a raw base64url string (with hyphens and underscores, no padding), it may produce an error or incorrect output because the characters differ.
To decode a JWT payload specifically, the fastest approach is to split the token on dots, take the second segment (index 1), apply the standard character conversion above, add padding, and then decode. Many browsers let you do this directly in the developer console using atob() with the manual conversion.
Alternatively, our JWT Decoder tool handles the full base64url-to-readable-JSON conversion automatically for JWT tokens — no manual conversion needed.
Generating URL-Safe Base64 in Code
Most languages have built-in URL-safe Base64 support:
# Python
import base64
encoded = base64.urlsafe_b64encode(b"Hello!")
decoded = base64.urlsafe_b64decode(encoded)
# Node.js (v14.18+)
const encoded = Buffer.from("Hello!").toString('base64url');
const decoded = Buffer.from(encoded, 'base64url').toString();
// Java
String encoded = Base64.getUrlEncoder()
.withoutPadding()
.encodeToString("Hello!".getBytes(StandardCharsets.UTF_8));
If your use case involves creating or validating JWT tokens, do not implement Base64url manually — use a well-maintained JWT library for your language. These libraries handle the encoding, signature verification, expiry checking, and claim validation correctly, avoiding subtle implementation mistakes.
Try It Free — No Signup Required
Runs 100% in your browser. No data is collected, stored, or sent anywhere.
Open Free Base64 Encoder/DecoderFrequently Asked Questions
Is base64url the same as Base64?
Almost. Base64url is Base64 with two character substitutions: + becomes - and / becomes _. Padding (=) is also typically omitted. These changes make it safe to embed in URLs and HTTP headers without percent-encoding.
How can I tell if a string is base64url vs standard Base64?
Look for hyphens (-) and underscores (_) in the string. Standard Base64 uses plus (+) and slash (/) instead. If you see hyphens and underscores, it is base64url. If you see plus and slash, it is standard Base64.
Why do JWT tokens use base64url instead of standard Base64?
JWT tokens are often passed as URL parameters, in HTTP Authorization headers, and in cookies. Standard Base64 characters + and / cause problems in these contexts. Base64url eliminates those problem characters so JWT tokens can be used safely anywhere.

