What is Base64URL? Handling URL-Safe Encoding

Published: 2023-11-08 | Category: Foundations

If you have ever tried to pass a standard Base64 string via an HTTP GET query parameter, you may have noticed that your backend server received corrupted data. The solution to this problem is Base64URL encoding.

The Problem with Standard Base64 in URLs

The standard Base64 alphabet (RFC 4648) utilizes 64 characters: A-Z, a-z, 0-9, and two specific symbols: the plus sign (+) and the forward slash (/).

Both of these symbols carry strict semantic meaning in the context of a Uniform Resource Locator (URL):

The Base64URL Solution

To safely transmit encoded binary data via URLs, the IETF defined the Base64URL standard. It is identical to standard Base64 in its mathematical approach, but it makes two critical modifications to the alphabet:

  1. The Plus sign (+) is replaced with a Minus sign / Hyphen (-).
  2. The Forward Slash (/) is replaced with an Underscore (_).

Both - and _ are designated as "URL-safe" characters that do not require URL-encoding (percent-encoding) and will pass transparently through any web server, proxy, or router.

The Padding Dilemma (=)

Standard Base64 also uses the equals sign (=) for padding. The equals sign is the primary delimiter in URL query strings (e.g., key=value).

While some servers handle trailing equals signs without issue, the official Base64URL standard highly recommends stripping the padding entirely before transmission. The receiving system can mathematically calculate how much padding is missing based on the string length and re-append it prior to decoding.

Where is Base64URL Used?

You interact with Base64URL encoded data constantly in modern web development:

Converting Between the Two Formats

If your programming language does not provide a native Base64URL decoder, you can convert a Base64URL string back to standard Base64 using simple string replacement before decoding:

JavaScript
// 1. Replace the URL-safe characters
let standardBase64 = base64UrlString.replace(/-/g, '+').replace(/_/g, '/');

// 2. Pad the string with '=' until its length is a multiple of 4
while (standardBase64.length % 4 !== 0) {
    standardBase64 += '=';
}

// 3. Safely decode
const decoded = atob(standardBase64);

Conclusion

Never place a standard Base64 string directly into a URL without either heavily URL-encoding it (which wastes space) or natively converting it to the Base64URL alphabet. By standardizing on Base64URL for all HTTP transport, you eliminate a massive category of subtle data corruption bugs.