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_verifier and code_challenge parameters
  • 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 →