What Is Base64URL and When Is It Used?

Base64URL is a small but important variant of Base64. The difference is two character substitutions and the removal of padding — but those changes make it safe to use in URLs, HTTP headers, and filenames where standard Base64 would cause parsing errors.

The two differences from standard Base64

Standard Base64 uses 64 characters: A–Z, a–z, 0–9, +, /, with = for padding.

Base64URL changes two characters and removes padding:

CharacterStandard Base64Base64URLWhy changed
62nd character+-+ means space in URL query strings
63rd character/_/ is a URL path separator
Padding=Omitted= separates query string keys from values

The encoding algorithm is otherwise identical. Base64URL produces strings that are safe to embed in URLs without percent-encoding any characters.

Where Base64URL is used

JWT tokens. The header and payload of every JWT are Base64URL-encoded. Try decoding the middle section of a JWT in your browser console: atob(payload.replace(/-/g, '+').replace(/_/g, '/')). You'll see the JSON claims object. JWTs use Base64URL because they appear in Authorization headers and sometimes in URL query parameters — standard Base64's special characters would need escaping.

OAuth 2.0 PKCE. The code challenge in OAuth's Proof Key for Code Exchange is SHA-256 of the code verifier, encoded as Base64URL. It travels in a URL query parameter, so URL-safe encoding is essential.

URL-safe identifiers. When you need to encode binary data (like raw UUID bytes or a cryptographic nonce) as a string that can appear in a URL path or query string, Base64URL is more compact than hex encoding and safe without percent-encoding.

Web Crypto API. Browser cryptography operations return ArrayBuffers that are commonly converted to Base64URL strings for storage, transmission, or comparison.

Decoding Base64URL in JavaScript

The browser's built-in atob() handles standard Base64 but not Base64URL — it doesn't recognise - and _. You need to convert back to standard Base64 first:

function decodeBase64URL(str) {
  // Swap URL-safe chars back to standard Base64
  const base64 = str.replace(/-/g, '+').replace(/_/g, '/');
  // Restore padding
  const padded = base64.padEnd(base64.length + (4 - base64.length % 4) % 4, '=');
  return atob(padded);
}

// Usage
const jwtPayload = "eyJzdWIiOiJ1c2VyXzEyMyIsImV4cCI6MTc0MzAwMDAwMH0";
console.log(decodeBase64URL(jwtPayload));
// {"sub":"user_123","exp":1743000000}
Library support: most languages have Base64URL support in their standard library or a widely-used package. In Python: base64.urlsafe_b64encode(data).rstrip(b'='). In Node.js: Buffer.from(str, 'base64url'). Don't implement it manually in production code.

How to tell Base64 from Base64URL by inspection

Look at the string character by character. If it contains + or /, it's standard Base64. If it contains - or _, it's Base64URL. If it ends with =, it's standard Base64 (Base64URL omits padding). This quick check is enough to determine which decoder to use.