Base64 vs URL Encoding: What Is the Difference?

Base64 and URL encoding both take a string and produce a different-looking string. Both are used for "safe transport" of data. And both appear in contexts like JWTs, API payloads, and OAuth flows.

But they solve fundamentally different problems, and using the wrong one silently corrupts your data in ways that are hard to debug.

Here's the difference, when to use each, and what happens when you mix them up.

The Core Difference

Base64 converts binary data into ASCII text. It takes bytes (an image, a PDF, encrypted data) and produces a string of characters that won't be mangled by text-based systems like JSON, email, or HTTP headers. Base64 is about data format — turning non-text into text.

URL encoding makes characters safe inside a URL. It takes text (a query parameter, a path segment) and replaces characters that would break URL parsing — spaces, ampersands, hashes, question marks. URL encoding is about transport safety — preventing structural characters from being misinterpreted.

Input:      hello world
Base64:     aGVsbG8gd29ybGQ=
URL-encoded: hello%20world

Both outputs are ASCII-safe. Both are reversible. That's where the similarity ends.

Base64URL Encoding
PurposeBinary → text conversionMake data URL-safe
InputArbitrary bytesText that goes in a URL
Character setA-Z, a-z, 0-9, +, /, =% followed by hex digits
Size increase~33%Variable (0-300%)
Used forImages in JSON, email attachments, JWT payloadsQuery strings, path segments, form submissions

When to Use Base64

Use Base64 when you need to represent binary data in a text-only medium.

Images in JSON

const response = await fetch('/api/upload', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    filename: 'screenshot.png',
    data: fileToBase64(imageFile) // iVBORw0KGgoAAA...
  })
});

Without Base64, the raw binary bytes would break JSON parsing — null bytes, control characters, and non-UTF-8 sequences are illegal in JSON strings.

Email Attachments (MIME)

Content-Type: image/png
Content-Transfer-Encoding: base64

iVBORw0KGgoAAAANSUhEUgAA...

SMTP was designed for 7-bit ASCII. Base64 encoding makes binary attachments travel safely through email servers.

JWT Payloads

JWT segments use Base64URL (a URL-safe variant) to encode the header and payload JSON:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIn0.
dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U

Each eyJ... segment is Base64URL-encoded JSON. Read more about this in How JWT Uses Base64 Encoding.

When to Use URL Encoding

Use URL encoding when you need to include arbitrary text in a URL without breaking its structure.

Query Parameters

const params = new URLSearchParams({
  query: "books & magazines",
  category: "reference"
});
const url = `/search?${params}`;
// /search?query=books+%26+magazines&category=reference

The & in books & magazines had to be encoded as %26. Without encoding, the URL parser would interpret & as a parameter separator, splitting the value at magazines.

Path Segments

const filename = "report 2026.pdf";
const url = `/download/${encodeURIComponent(filename)}`;
// /download/report%202026.pdf

Without encoding, the space would break the URL. Some servers reject unencoded spaces outright. Others accept them but fail when the URL is used in other contexts (redirects, HTTP headers, logs).

OAuth Redirect URLs

const redirectUri = "https://myapp.com/callback?code=abc&state=xyz";
const authUrl = `https://auth.provider.com/authorize?redirect_uri=${encodeURIComponent(redirectUri)}`;

The entire callback URL becomes a single query parameter value. Without encoding, the ? and & inside it would be misinterpreted as part of the outer URL's query string.

URL-Safe Base64: The Middle Ground

Standard Base64 uses three characters that are problematic in URLs:

CharacterURL ProblemBase64URL Replacement
+Interpreted as space in query strings- (minus)
/Path separator_ (underscore)
=Key-value separator in query stringsStripped or %3D

Base64URL replaces + with - and / with _, and removes trailing = padding:

Standard Base64:  YWJjKysvLz09   (contains +, /, =)
Base64URL:        YWJjKysvLz09
                  ↓ fix
                  YWJjKysvLz09   → YWJjKy0vLzA5

Converting between them in JavaScript:

// Standard → Base64URL
function toBase64URL(base64) {
  return base64
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');
}

// Base64URL → Standard
function fromBase64URL(base64url) {
  base64url = base64url
    .replace(/-/g, '+')
    .replace(/_/g, '/');
  while (base64url.length % 4) {
    base64url += '=';
  }
  return base64url;
}

Base64URL is the recommended format whenever Base64-encoded data might end up in a URL — which is more often than you'd think.

Common Mistakes

Mistake 1: Using Base64 When You Mean URL Encoding

// Wrong: Base64-encoding a parameter value
const url = `/api/search?q=${btoa("hello world")}`;
// /api/search?q=aGVsbG8gd29ybGQ=

// Right: URL-encoding the parameter value
const url = `/api/search?q=${encodeURIComponent("hello world")}`;
// /api/search?q=hello%20world

Base64-encoding a query value works by accident — the server receives aGVsbG8gd29ybGQ= and can Base64-decode it back. But nothing about the server's URL parser suggests this. A future developer (or a library upgrade) will treat the value as plain text.

Mistake 2: Putting Base64 in URLs Without Base64URL

// Base64 can contain +, /, =
const data = btoa("\x3e\x00\xff\x3c");
// Contains / and + which break URL parsing

// Use Base64URL instead
const data = btoa("\x3e\x00\xff\x3c")
  .replace(/\+/g, '-')
  .replace(/\//g, '_')
  .replace(/=+$/, '');

Mistake 3: Confusing encodeURIComponent with Base64

// encodeURIComponent is NOT Base64
encodeURIComponent("hello world");
// "hello%20world" — NOT Base64

btoa("hello world");
// "aGVsbG8gd29ybGQ=" — actual Base64

They produce different outputs for the same input. If your API expects Base64-encoded data and you URL-encode it instead, the API will fail with a Base64 decode error.

Mistake 4: URL-Encoding Binary Data

// Wrong: URL-encoding raw binary
const binary = new Uint8Array([0x89, 0x50, 0x4E, 0x47]);
const text = new TextDecoder().decode(binary);
const urlEncoded = encodeURIComponent(text);
// "‰PNG" — still contains non-printable characters!

// Right: Base64-encode binary
const base64 = btoa(String.fromCharCode(...binary));
// "iVBORw0KGgo="

URL encoding only replaces specific problematic characters. It doesn't convert non-text bytes into safe text. Binary data URL-encoded still contains unprintable and non-UTF-8 sequences.

Debugging Checklist

If you're seeing corrupted data in URL parameters, API payloads, or file uploads:

  1. Check the output format. Is it hello%20world (URL encoding) or aGVsbG8gd29ybGQ= (Base64)? The % prefix is the immediate giveaway.
  2. Check for + signs in query parameters. If + shows up as a literal + in your server code instead of a space, your server-side URL decoder is not decoding application/x-www-form-urlencoded.
  3. Check for = padding at the end of parameter values. If you see abc123==, someone probably Base64-encoded a value and put it directly in a query string without URL-encoding or Base64URL conversion.
  4. Verify with a tool. Paste the string into the Base64 encoder/decoder. If it decodes successfully, it's Base64. If not, try the URL encoder/decoder.

FAQ

Is Base64 encoding the same as URL encoding?

No. Base64 converts binary to ASCII-safe text. URL encoding escapes characters that have special meaning in URLs. Different purposes, different outputs.

Can I use standard Base64 in a URL?

Technically yes, but you shouldn't. The +, /, and = characters have special meaning in URLs and will be misinterpreted by URL parsers. Use Base64URL instead.

Why do JWTs use Base64URL instead of standard Base64?

Because JWTs travel through URLs, HTTP headers, and cookies. Standard Base64's + and / would break in URL contexts. Base64URL replaces these characters to be safe everywhere.

Should I Base64-encode URLs?

No. Base64-encoding a URL changes the data itself. If you need to pass a URL as a parameter value, use URL encoding (encodeURIComponent), not Base64.

What happens if I use URL encoding for binary data?

URL encoding only escapes specific dangerous characters. It doesn't make arbitrary binary data safe for text-based transport. Binary data URL-encoded will still contain non-printable characters that break JSON, XML, or HTTP headers.


Bookmark both the Base64 encoder/decoder and the URL encoder/decoder if you work with APIs or data transport. Most encoding bugs in production are caught by pasting the corrupted data into one of these tools and comparing the decoded output to what you expected.