DevTools Hub

Search tools

Search for a developer tool

Base64 vs URL Encoding: What's the Difference?

Both turn readable input into a string full of unfamiliar characters, both show up constantly in URLs, and both get called "encoding" — so it's an easy pair to conflate. But they solve two completely different problems, and mixing them up is exactly what causes the classic "this token breaks when I put it in a link" bug.

The short answer

Base64 converts arbitrary binary data into printable text, so it can survive being carried through systems built for text. URL encoding (percent-encoding) converts text that's already text into a form that's safe inside one specific syntactic context — a URL — by escaping the characters that would otherwise be misread as part of the URL's structure. One is about representing data; the other is about escaping syntax. For the full mechanics of the first one, see What Is Base64 Encoding?

What each one is actually for

  • Base64 — you reach for it when you have bytes that aren't text at all (an image, a file, a cryptographic hash or signature) and need to embed them somewhere that only accepts text: a JSON field, an XML document, an HTTP header, a data: URL.
  • URL encoding — you reach for it when you have ordinary text (a search query, a filename, a form value) that might contain characters with special meaning in a URL — &, =, ?, /, spaces — and you need it to survive as a single, unambiguous path segment or query parameter value.

How they work, side by side

Base64 groups input into 3-byte chunks and re-maps each chunk onto 4 characters from a fixed 64-symbol alphabet (A–Z, a–z, 0–9, +, /). Every byte of input is transformed, whether or not it was "safe" to begin with — the output size is always about 4/3 (≈33%) larger than the input, no matter what that input contains.

URL encoding leaves almost everything untouched. It only replaces the specific characters that are unsafe or reserved in a URL, each with a % followed by two hex digits representing that character's byte value — %20 for a space, %3F for ?, and so on. A string of plain letters and digits comes out completely unchanged; a string that's mostly reserved punctuation can nearly triple in size, since every escaped byte turns 1 character into 3.

A concrete example

Take the raw bytes 0x12 0x00 0x7e. Standard Base64 encodes them as EgB+. Drop that straight into a URL and you're fine — until the data happens to contain a / instead, like c3ViamVjdHM/ (the Base64 of the string "subjects?"). Paste that into a URL path unescaped and the / reads as a path separator, silently splitting your token into two segments.

You have two ways to fix it, and they produce different results:

ApproachInputOutputLength
Percent-encode the standard Base64c3ViamVjdHM/c3ViamVjdHM%2F14
Use the Base64URL alphabet insteadc3ViamVjdHM/c3ViamVjdHM_12

Both decode back to the same bytes, but the URL-safe alphabet stays shorter because it swaps the two troublesome characters (+-, / _) instead of escaping them, and conventionally drops the = padding too, since it's reconstructible from the string's length. This is the variant JWTs use for exactly this reason — it's why a JWT can sit directly in a URL query parameter with no additional escaping at all.

Size overhead: a real difference

  • Base64 overhead is fixed: always ≈33% larger, regardless of content, because every byte gets re-encoded.
  • URL-encoding overhead is content-dependent: 0% for a string of plain unreserved characters, up to 3x in the worst case, since only about 66 of the 256 possible byte values are left unescaped — every other byte turns 1 character into a 3-character %XX sequence.

That worst case is exactly why you never percent-encode raw binary data directly — running arbitrary bytes through encodeURIComponent instead of Base64 first produces a far larger string than necessary, for data that Base64's fixed 33% overhead handles more predictably.

When to use which

  • Binary data going anywhere (a file, hash, image, or opaque token) → Base64 — the URL-safe variant if it might end up in a URL, standard Base64 otherwise.
  • Human-authored text going into a URL (a search term, a filename, form input) → URL encoding, specifically encodeURIComponent for a single value. It keeps the text mostly readable instead of turning it into an opaque blob.
  • Both, when unavoidable — if you must embed already-Base64-encoded data (standard alphabet) inside a URL you don't control the format of, percent-encode the result. But switching to Base64URL at the source is almost always the cleaner fix.

Common mistakes worth avoiding

  • Assuming standard Base64 is already URL-safe. It isn't — the + and / characters are legal Base64 output and legal URL syntax, just with two different meanings.
  • + silently becoming a space. Many query-string parsers follow the older application/x-www-form-urlencoded convention where + means an encoded space — so a standard Base64 string with a + in it can get corrupted by a server that decodes it that way, with no error raised anywhere.
  • Percent-encoding raw bytes instead of Base64-encoding them first. Works in principle, wildly inflates the result in practice — see the overhead comparison above.
  • Double-encoding. Running encodeURIComponent on a string that's already percent-encoded turns %20 into %2520, a classic source of mangled query parameters.
  • encodeURI vs. encodeURIComponent. encodeURI assumes you're encoding a whole URL and deliberately leaves &, =, and ? untouched — using it on a single query parameter value instead of encodeURIComponent will leave those characters unescaped and break the query string the moment your value contains one.

Try it yourself

Encode binary-safe text with Base64 Encode (toggle URL-safe output to see the alphabet swap in action), or escape text for a URL with URL Encode, which offers both component and full-URI modes. Both run entirely in your browser — nothing you paste in is ever sent anywhere.

Related tools