URL Encoding Demystified: Why %20 Exists
A URL looks simple until it breaks. Here's the definitive guide to percent-encoding, the difference between encodeURI and encodeURIComponent, and the gotchas that will ruin your API calls.
Every developer has hit this bug: you pass a search query to an API, and it works perfectly until
someone searches for "Tom & Jerry." The ampersand splits your query parameter in half. The server
receives q=Tom and a mysterious second parameter called Jerry.
URL encoding exists to prevent exactly this kind of chaos.
1. The Anatomy of a URL
Before we can understand encoding, we need to understand what a URL is made of. RFC 3986 defines the structure:
https://api.example.com:8080/v2/search?q=hello+world&lang=en#results
\___/ \_______________/\___/\________/ \__________________/ \_____/
scheme host port path query string fragment
Each part has its own rules about which characters are allowed. The ? separates the
path from the query. The & separates query parameters. The # marks the
fragment. The / separates path segments.
These characters are called reserved characters. If your data contains one of them, the URL parser can't tell the difference between structure and content. That's where percent-encoding comes in.
2. How Percent-Encoding Works
Percent-encoding replaces unsafe characters with a % followed by two hexadecimal
digits representing the character's ASCII (or UTF-8) byte value.
- Space →
%20(ASCII 32 = hex 20) &→%26(ASCII 38 = hex 26)=→%3D(ASCII 61 = hex 3D)#→%23(ASCII 35 = hex 23)/→%2F(ASCII 47 = hex 2F)
So "Tom & Jerry" in a query parameter becomes Tom%20%26%20Jerry. The URL parser now
sees the %26 as data, not as a parameter separator.
What About the + Sign?
In HTML form submissions (application/x-www-form-urlencoded), spaces are encoded as
+ instead of %20. Both are valid, but they belong to different specs.
%20 is the RFC 3986 standard. + is the HTML form convention. Most
servers accept both, but it's a common source of double-encoding bugs.
3. encodeURI vs. encodeURIComponent
JavaScript gives you two encoding functions, and using the wrong one is one of the most common web development mistakes.
encodeURI()
Encodes a full URL. It leaves structural characters alone
(: / ? # & =) because it assumes they're part of the URL's structure.
encodeURI("https://example.com/path?q=hello world")
// "https://example.com/path?q=hello%20world"
// ✅ The :// and ? are preserved
encodeURIComponent()
Encodes a single value within a URL. It encodes everything except
letters, digits, and - _ . ~ .
encodeURIComponent("hello world&foo=bar")
// "hello%20world%26foo%3Dbar"
// ✅ The & and = are escaped because they're DATA, not structure
The Golden Rule
Building a full URL from scratch? Use encodeURI(). Inserting a user-provided value
into a query parameter? Always use encodeURIComponent().
// ❌ WRONG: encodeURI won't escape the & in the user's input
const url = encodeURI(`https://api.com/search?q=${userInput}`);
// ✅ RIGHT: encode just the value
const url = `https://api.com/search?q=${encodeURIComponent(userInput)}`;
4. Unicode and Internationalized URLs
ASCII only covers 128 characters. What happens when someone searches for "café" or "日本語"?
The character is first converted to its UTF-8 byte sequence, and then each byte is percent-encoded individually:
- "é" → UTF-8 bytes:
C3 A9→%C3%A9 - "日" → UTF-8 bytes:
E6 97 A5→%E6%97%A5
Modern browsers hide this complexity by displaying decoded Unicode in the address bar while sending the encoded version over the wire. But if you're logging URLs or building them manually, you need to be aware of this multi-byte encoding.
5. Common Pitfalls
Double Encoding
If you encode a value that's already encoded, %20 becomes %2520 (the
% itself gets encoded to %25). The server receives a literal
%20 string instead of a space. Always encode raw values, never pre-encoded
strings.
Forgetting to Encode Path Segments
Most developers remember to encode query parameters but forget that path segments can contain
special characters too. A file named my report (final).pdf needs encoding in the
path:
/files/my%20report%20(final).pdf
API Keys in URLs
If your API key contains + or / (common in Base64-encoded keys), they
must be percent-encoded when placed in a URL. Otherwise the / creates a false path
segment and the + becomes a space.
Conclusion
URL encoding is invisible when it works and catastrophic when it doesn't. The rules are simple:
encode values with encodeURIComponent(), never double-encode, and test with special
characters like & = + # / and Unicode.
Need to debug a messy URL? Use our URL Encoder to encode, decode, and parse query strings instantly in your browser.