Try the Base64 Encoder/Decoder

Base64 vs Base64url: Why `+`, `/`, and `=` Break URLs, and Why JWTs Use a Different Alphabet

Standard Base64's `+`, `/`, and `=` characters all have special meaning in URLs β€” which is why a Base64-encoded JWT pasted directly into a URL can silently corrupt, and why Base64url exists as a separate, URL-safe alphabet. Here's exactly which characters differ, why JWTs require Base64url specifically, how padding works and why Base64url commonly omits it, and how to tell the two variants apart.

By sadiqbd Β· June 13, 2026

Share:
Base64 vs Base64url: Why `+`, `/`, and `=` Break URLs, and Why JWTs Use a Different Alphabet

Standard Base64 uses characters that have special meaning in URLs β€” which is why a Base64-encoded JWT pasted into a URL can silently break, and why "Base64" and "Base64url" are subtly different encodings that aren't interchangeable

Standard Base64 encoding (covered in previous articles) uses an alphabet of 64 characters: A-Z, a-z, 0-9, plus + and /, with = used for padding. This works fine for embedding encoded data in most contexts β€” but +, /, and = all have special meaning in URLs β€” which is why a separate variant, Base64url, exists, and why mixing up the two produces data that looks like Base64 but decodes incorrectly (or fails to decode) when handled by tools expecting the other variant.


Why +, /, and = are problematic in URLs

+ in a URL's query string represents a space (a long-standing convention from URL encoding, predating Base64's common use in web contexts) β€” if a Base64-encoded string containing a + character is placed directly into a URL's query string without additional URL-encoding, a + would be interpreted as a space by anything parsing the URL β€” corrupting the Base64 data (a + silently becoming a space changes the decoded result).

/ in a URL is a path separator β€” a Base64 string containing / placed into a URL path (rather than a query parameter) could be misinterpreted as introducing additional path segments β€” breaking routing/path-parsing logic that splits the URL on / characters, without awareness that part of what looks like "path segments" is actually part of an encoded string.

= is used to separate keys and values in query strings (?key=value) β€” a Base64 string ending in = or == (padding), if placed as a query-string value without additional encoding, could confuse parsers that split on = β€” potentially truncating the value at the first = encountered within the Base64 string itself, rather than treating the entire Base64 string as one value.


Base64url: a URL-safe alphabet substitution

Base64url replaces the problematic characters:

  • + β†’ - (hyphen)
  • / β†’ _ (underscore)
  • = (padding) β†’ often omitted entirely β€” many Base64url implementations don't use padding at all, since the length of the encoded string, combined with knowledge of the original data's length (or, for self-describing formats, structural information within the decoded data itself), can often allow correct decoding without padding β€” and omitting padding avoids the = character issue entirely (rather than URL-encoding the =, which would work but adds complexity)

The core encoding algorithm is identical β€” Base64url isn't a different encoding scheme; it's the same underlying bit-to-character mapping, with a different character alphabet for the specific 2 characters (and padding convention) that differ from standard Base64.


JWTs: Base64url is the required encoding, not optional

JSON Web Tokens (JWTs), covered in a previous article, consist of three Base64url-encoded segments (header, payload, signature) separated by periods (.).

Why Base64url specifically, and not standard Base64, for JWTs: JWTs are commonly transmitted within URLs (as query parameters, or within Authorization headers that might, in some implementations, also appear in logged URLs or similar contexts) β€” and JWTs are designed to be self-contained, URL-safe tokens by specification β€” using Base64url ensures that no additional URL-encoding step is needed when placing a JWT into a URL β€” the JWT itself, as-generated, is already URL-safe.

If a JWT library/tool incorrectly uses standard Base64 (with +, /, =) instead of Base64url β€” the resulting "JWT-like" string could contain characters that, if placed directly in a URL without URL-encoding, would be misinterpreted as described above β€” a subtle, potentially intermittent bug (only manifesting for tokens that happen to contain +, /, or = in their Base64-encoded segments β€” which, depending on the specific content being encoded, might occur for some tokens but not others, making the bug appear "intermittent" if not understood as an encoding-alphabet issue).


"Padding" and why it matters for decoding

Base64 (standard) encodes data in groups of 3 bytes, producing groups of 4 characters β€” if the input data's length isn't a multiple of 3 bytes, the final group has fewer than 3 input bytes, and padding characters (=) are added to the output to indicate this β€” = (one padding character) indicates the final group represented 2 input bytes; == (two) indicates 1 input byte.

Padding tells a decoder exactly how many "extra" bits, from the last group, to discard β€” without padding, a decoder encountering the end of a Base64 string without knowing the original data's exact byte-length might not know whether the final group represents 3, 2, or 1 original bytes (since all three cases produce 4 output characters, just with different amounts of "meaningful" vs "padding" bits within those 4 characters).

Base64url's common "no padding" convention works because: many contexts using Base64url (JWTs, for instance) have a known, fixed total length for each segment (or can determine the length from the overall string's length, given the known number of segments/delimiters) β€” allowing the decoder to infer the correct padding (how many "extra" characters would, in standard Base64, have been =) from the string's length alone β€” length mod 4 determines how much "virtual padding" to assume, without needing the padding characters to be explicitly present in the encoded string.

The practical implication: a Base64url decoder must handle "missing" padding correctly β€” if a decoder expects = padding characters to be present (as standard Base64 typically requires) and is given a Base64url string without them β€” it might fail to decode, or (depending on implementation) decode incorrectly β€” **converting between Base64 and Base64url isn't just "swap +// for -/_" β€” it may also require adding or removing padding characters, depending on the specific source/target formats and the specific libraries'/tools' expectations regarding padding.


Filesystem-safe Base64: a third, less-common variant

A less-commonly-encountered third variant exists for contexts where Base64-encoded strings need to be safe as filenames β€” some operating systems/filesystems treat / (and, on some systems, \) as path-separator characters even outside of URLs β€” a Base64-encoded string containing / couldn't be used directly as (part of) a filename on such systems. Filesystem-safe Base64 variants typically address this the same way Base64url does for / (substituting _ or a similar filesystem-safe character) β€” though this variant is considerably less standardized/common than Base64url, and encountering it is comparatively rare compared to standard Base64 and Base64url, which are the two variants most likely to be encountered in practice.


How to use the Base64 Encoder/Decoder on sadiqbd.com

  1. For data destined for URLs/JWTs: use Base64url encoding (or, if the tool only offers standard Base64, manually substitute +β†’-, /β†’_, and remove = padding afterward, if the target context β€” like JWTs β€” expects unpadded Base64url)
  2. For decoding JWT segments or other Base64url data: if pasting into a standard-Base64 decoder produces an error or unexpected output β€” check whether the input contains -/_ (Base64url characters) or is missing expected = padding β€” either of these indicates Base64url, requiring conversion (substituting characters back, and/or adding appropriate padding based on the string's length) before standard-Base64 decoding will succeed
  3. For general data embedding (Data URLs, email MIME, covered in previous articles): standard Base64 (with +, /, =) is typically the expected format β€” Base64url is specifically relevant for URL/JWT-adjacent contexts, not a universal replacement for standard Base64 across all use cases

Frequently Asked Questions

How can I tell, just by looking at an encoded string, whether it's standard Base64 or Base64url? If the string contains + or / β€” it's standard Base64 (these characters don't appear in Base64url). If the string contains - or _ β€” it's Base64url (these don't appear in standard Base64). If the string contains none of +, /, -, _ (which is possible β€” not every encoded string will happen to contain these specific characters, depending on the underlying data) β€” the string is ambiguous from its characters alone β€” it could be validly decoded as either (since, for such strings, the two alphabets overlap entirely) β€” context (is this a JWT segment? Was it generated for URL use?) would be the deciding factor in such ambiguous cases, rather than the string's characters themselves.

Is the Base64 Encoder/Decoder free? Yes β€” completely free, no sign-up required.

Try the Base64 Encoder/Decoder free at sadiqbd.com β€” encode and decode both standard Base64 and Base64url instantly.

Share:
Try the related tool:
Open Base64 Encoder/Decoder

More Base64 Encoder/Decoder articles