URLs look simple on the surface, but the moment you start passing dynamic dataβusernames, tokens, JSON, Base64, or even plain textβthings can fall apart quickly. Suddenly parameters disappear, special characters mutate, or the server receives something completely different from what you sent. If you've ever wondered why %20, +, %2F, or %3D keep showing up in your URLs, this guide is for you.
We'll break down the problem, explain the underlying causes, and give you a practical workflow for handling URL encoding correctly in any language.
1. The Problem: "Why Did My URL Parameter Change?"
URL encoding issues usually show up in confusing ways:
- Spaces turn into
+or%20 - Slashes break the URL path
- Query parameters disappear or get truncated
- Base64 or JSON becomes corrupted
- Double encoding (
%2520instead of%20) - Server receives a different value than the client sent
Real-World Error Messages
// Double encoding
value=%252Fimages%252Fcat.png
// Slash breaks path
GET /download?file=images/cat.png
// Space mismatch
"Hello World" β "Hello+World" or "Hello%20World"2. The Cause: ASCII Limits, Reserved Characters, and Encoding Rules
2.1 URLs Only Support ASCII
URLs were designed long before Unicode. Anything outside AβZ, aβz, 0β9, and a few symbols must be encoded.
2.2 Reserved Characters
| Character | Meaning | Must Encode? |
|---|---|---|
| ? | Start of query | Yes (inside values) |
| & | Parameter separator | Yes |
| = | Key/value separator | Yes |
| / | Path separator | Yes (inside values) |
| + | Space (legacy) | Yes |
2.3 Space Encoding: + vs %20
One of the most confusing parts:
%20= Standard percent encoding+= HTML form encoding
Different languages treat them differently.
2.4 Multi-Language Encoding Differences
| Language | Function | Space | Encodes /? | Encodes +? |
|---|---|---|---|---|
| JavaScript | encodeURI | %20 | No | No |
| JavaScript | encodeURIComponent | %20 | Yes | Yes |
| Python | urllib.parse.quote | %20 | Yes | Yes |
| PHP | urlencode | + | Yes | No |
| Go | url.QueryEscape | + | Yes | No |
2.5 Double Encoding
%20 β %2520This happens when encoding is applied twice.
2.6 Slashes Inside Values
file=images/cat.png β images (value) + cat.png (new param)Must encode as %2F.
3. Real-World Scenarios
Scenario 1: Search Query
// User input
"red & blue"
// Wrong
?q=red&blue
// Correct
?q=red%20%26%20blueScenario 2: Base64 in URLs
// Standard Base64
abc+/=
// Must convert to Base64URL
abc-__Scenario 3: File Paths
// Wrong
?file=images/cat.png
// Correct
?file=images%2Fcat.png4. The Solution: A Reliable Workflow
4.1 Use the Right Function
// JavaScript
encodeURIComponent("red & blue");
encodeURI("https://example.com?q=hello world");# Python
from urllib.parse import quote
quote("red & blue")// PHP
urlencode("red & blue");4.2 Encode Before Adding to URL
// Wrong
?q=red&blue
// Correct
?q=red%26blue4.3 Avoid Double Encoding
// Detect double encoding
function isDoubleEncoded(str) {
return /%25[0-9A-F]{2}/i.test(str);
}4.4 Encode JSON
encodeURIComponent(JSON.stringify(obj));4.5 Encode File Paths
encodeURIComponent("images/cat.png"); // β images%2Fcat.png4.6 Debugging Checklist
- β Are spaces encoded as %20?
- β Are &, =, ? encoded inside values?
- β Are slashes encoded?
- β Is the value encoded only once?
- β Are you using the correct function?
5. Practical Utility Functions
JavaScript: Safe URL Builder
function buildURL(base, params) {
const query = Object.entries(params)
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
.join('&');
return `${base}?${query}`;
}Python: Safe Query Builder
from urllib.parse import urlencode
urlencode({"q": "red & blue", "page": 1})PHP: Safe Query Builder
http_build_query(["q" => "red & blue", "page" => 1]);Conclusion
URL encoding looks simple, but it's full of edge cases. Most bugs come from reserved characters, space encoding differences, slashes inside values, and double encoding. Once you understand these patterns, URL encoding becomes predictable and easy to manage.
Follow the workflow in this guide to eliminate most URL-related bugs and make your applications far more robust.