URL Encoding vs Base64 Encoding: What's the Difference?
URL encoding (percent-encoding) converts special characters in URLs to %XX format per RFC 3986. Base64 encoding converts binary data to a text string using 64 ASCII characters per RFC 4648. They serve different purposes and are not interchangeable.
What is URL Encoding?
URL encoding, also called percent-encoding, is defined by RFC 3986 as the mechanism for representing characters in a URI that are not allowed or have special meaning. Each character to be encoded is converted into one or more bytes (using UTF-8), and each byte is represented as a percent sign (%) followed by two uppercase hexadecimal digits.
For example, a space character becomes %20, an ampersand becomes %26, and a non-ASCII character like the Euro sign becomes %E2%82%AC (three UTF-8 bytes, each percent-encoded).
// URL encoding examples in JavaScript
encodeURIComponent('hello world'); // "hello%20world"
encodeURIComponent('price=10&qty=2'); // "price%3D10%26qty%3D2"
encodeURIComponent('cafe'); // "caf%C3%A9"URL encoding is specifically designed for making URLs safe and valid. It only encodes characters that are not permitted or have reserved meanings in URIs, leaving alphanumeric characters and a few safe symbols untouched.
What is Base64 Encoding?
Base64 encoding, defined by RFC 4648, is a binary-to-text encoding scheme that represents binary data using a set of 64 ASCII characters: A-Z, a-z, 0-9, +, and /, with = used for padding. Every three bytes of input produce four characters of output.
Base64 was designed to transmit binary data over channels that only reliably support text, such as email (MIME) or embedding data in XML/JSON. It is not specific to URLs and encodes all input bytes, not just special characters.
// Base64 encoding examples in JavaScript
btoa('hello world'); // "aGVsbG8gd29ybGQ="
btoa('price=10&qty=2'); // "cHJpY2U9MTAmcXR5PTI="
// For Unicode strings, encode to UTF-8 first
function toBase64(str) {
return btoa(unescape(encodeURIComponent(str)));
}
toBase64('cafe'); // "Y2Fmw6k="There is also a URL-safe variant of Base64 (Base64url) that replaces + with - and / with _, and often omits the = padding. This variant is used in JWTs, data URIs in URLs, and other contexts where standard Base64 characters would conflict with URL syntax.
Key Differences
| Feature | URL Encoding | Base64 Encoding |
|---|---|---|
| Standard | RFC 3986 | RFC 4648 |
| Purpose | Make URLs safe | Represent binary as text |
| Encodes | Only special/reserved characters | All input bytes |
| Output format | %XX hex sequences | A-Z, a-z, 0-9, +, /, = |
| Size increase | Variable (only encoded chars grow) | Always ~33% larger |
| Reversible | Yes | Yes |
| Human-readable | Partially (unreserved chars stay) | No |
| URL-safe by default | Yes (by design) | No (contains +, /, =) |
When to Use Which
Use URL encoding when you need to include special characters in a URL, such as query parameter values, path segments, or fragment identifiers. URL encoding is the correct choice for any situation where data must be embedded within a URL structure.
Use Base64 encoding when you need to represent binary data (images, files, encrypted payloads) as text, embed binary content in JSON or XML, or transmit data through text-only channels. Base64 is also used in HTTP Basic Authentication headers and JSON Web Tokens (JWTs).
// URL encoding: embedding a search term in a URL
const searchUrl = 'https://example.com/search?q=' +
encodeURIComponent('C++ & Java');
// "https://example.com/search?q=C%2B%2B%20%26%20Java"
// Base64: embedding an image in CSS or HTML
const imageData = 'data:image/png;base64,iVBORw0KGgoAAAANS...';
// Base64: HTTP Basic Auth header
const credentials = btoa('username:password');
const header = 'Authorization: Basic ' + credentials;Can You Combine Them?
Yes, and in some cases you must. If you need to pass Base64-encoded data as a URL parameter, the standard Base64 output may contain +, /, and = characters, which have special meanings in URLs. You have two options:
Option 1: URL-encode the Base64 string before placing it in the URL. The + becomes %2B, / becomes %2F, and = becomes %3D.
Option 2: Use the Base64url variant (RFC 4648 Section 5), which replaces+ with -, / with _, and removes padding. This is the approach used by JWTs and many modern APIs.
// Option 1: URL-encode standard Base64
const base64 = btoa('binary data here'); // "YmluYXJ5IGRhdGEgaGVyZQ=="
const urlSafe = encodeURIComponent(base64);
// "YmluYXJ5IGRhdGEgaGVyZQ%3D%3D"
// Option 2: Base64url encoding
function toBase64url(str) {
return btoa(str)
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
toBase64url('binary data here');
// "YmluYXJ5IGRhdGEgaGVyZQ"