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.
| Base64 | URL Encoding | |
|---|---|---|
| Purpose | Binary → text conversion | Make data URL-safe |
| Input | Arbitrary bytes | Text that goes in a URL |
| Character set | A-Z, a-z, 0-9, +, /, = | % followed by hex digits |
| Size increase | ~33% | Variable (0-300%) |
| Used for | Images in JSON, email attachments, JWT payloads | Query 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:
| Character | URL Problem | Base64URL Replacement |
|---|---|---|
+ | Interpreted as space in query strings | - (minus) |
/ | Path separator | _ (underscore) |
= | Key-value separator in query strings | Stripped 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:
- Check the output format. Is it
hello%20world(URL encoding) oraGVsbG8gd29ybGQ=(Base64)? The%prefix is the immediate giveaway. - 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 decodingapplication/x-www-form-urlencoded. - Check for
=padding at the end of parameter values. If you seeabc123==, someone probably Base64-encoded a value and put it directly in a query string without URL-encoding or Base64URL conversion. - 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.