Ever clicked a link with %20 or %3D in it and wondered what those strange codes mean? That's URL encoding in action. It's how the web handles spaces, special characters, and non-ASCII text in URLs. Get it wrong, and your links break, forms fail, or APIs return errors. This guide explains exactly when and how to encode URLs properly.
Key Takeaways
- 1URL encoding converts unsafe characters to %XX format (hex ASCII/UTF-8 values)
- 2Use encodeURIComponent for query values and path segments; encodeURI for full URLs (rarely needed)
- 3Never double-encode: encode raw values once, at the final step before sending
- 4Space can be + (forms only) or %20 (works everywhere)—use %20 when in doubt
- 5Modern approach: Use URL and URLSearchParams APIs for automatic, correct encoding
1What Is URL Encoding?
Scenario
Encode a search query with spaces and special characters
Solution
"Hello World!" → "Hello%20World%21" — Space becomes %20 (hex 20 = decimal 32, the ASCII code for space). Exclamation mark becomes %21.
| Character | Encoded | Reason |
|---|---|---|
| Space | %20 or + | Not allowed in URLs |
| & | %26 | Query string separator |
| = | %3D | Key-value separator |
| ? | %3F | Query string start |
| # | %23 | Fragment identifier |
| / | %2F | Path separator |
| + | %2B | Often means space in forms |
2When to Encode (and When Not To)
| URL Part | Encode? | Example |
|---|---|---|
| Protocol (https://) | Never | https:// stays as-is |
| Domain (example.com) | Never | Use Punycode for internationalized domains |
| Path segments | Encode values | /users/John%20Doe |
| Query parameter names | Encode | my%20key=value |
| Query parameter values | Always encode | search=hello%20world |
| Fragment (#section) | Encode value | #section%20name |
URL Encoding in JavaScript
| Function | Use For | Does NOT Encode |
|---|---|---|
| encodeURIComponent() | Query params, path segments | A-Z a-z 0-9 - _ . ! ~ * ' ( ) |
| encodeURI() | Full URLs (rarely needed) | All above + : / ? # [ ] @ ! $ & ' ( ) * + , ; = |
| escape() ❌ | DEPRECATED - never use | Inconsistent, doesn't handle UTF-8 |
Scenario
Create a search URL with user input that might contain special characters
Solution
const url = `https://api.example.com/search?q=${encodeURIComponent(userInput)}&page=1`; — Only encode the value, not the whole URL. The ? and & must stay unencoded.
4Common URL Encoding Mistakes
| Mistake | Problem | Fix |
|---|---|---|
| Double encoding | %20 becomes %2520 | Encode once, at the end |
| Encoding whole URL | https%3A%2F%2F breaks URL | Only encode values, not structure |
| Not encoding at all | Spaces break URL, & splits values | Always encode user input |
| Using encodeURI for params | Doesn't encode &, =, ? | Use encodeURIComponent |
| Forgetting + vs %20 | Plus decoded as space in forms | Use %20 in path, + or %20 in query |
| Mixing encoded/decoded | Inconsistent handling | Decode on receive, encode on send |
Scenario
User searches for "50% off" — you encode it, store it, then encode again when building the URL
Solution
First encode: "50%25%20off" (correct). Second encode: "50%2525%2520off" (broken). Solution: Track whether data is encoded or raw. Encode only once.
Special Cases & Edge Cases
- **Unicode/Emoji** – Encoded as UTF-8 bytes: 🎉 → %F0%9F%8E%89
- **Plus sign (+)** – Encode as %2B if you want a literal plus, not a space
- **Slash in path** – Use %2F only if slash is data, not a path separator
- **Reserved characters in values** – Always encode: & = ? # when they're data
- **Form data (application/x-www-form-urlencoded)** – Space as +, not %20
- **RFC 3986 strict** – Also encode ! ' ( ) * for maximum compatibility
6URL Encoding for APIs
| Scenario | Approach |
|---|---|
| Query parameters | Always encodeURIComponent values |
| Path parameters | Encode each segment separately |
| JSON in URL | JSON.stringify then encodeURIComponent |
| Arrays in query | ids=1&ids=2 or ids=1,2 or ids=[1,2] (API-specific) |
| OAuth tokens | Encode before including in URL |
| Webhook URLs | Full URL as parameter: callback=https%3A%2F%2F... |
Scenario
Call an API with a callback URL: https://api.com/share?url=https://mysite.com/page?id=123
Solution
Encode the callback: /share?url=https%3A%2F%2Fmysite.com%2Fpage%3Fid%3D123 — The inner ? and = must be encoded so they're not parsed as part of the outer query string.
7Decoding URLs
| Function | Use For | Notes |
|---|---|---|
| decodeURIComponent() | Query params, path segments | Throws on malformed input |
| decodeURI() | Full URLs (rare) | Doesn't decode reserved chars |
| URLSearchParams.get() | Query params | Auto-decodes, handles + as space |
| unescape() ❌ | DEPRECATED | Never use |
Encode & Decode URLs Online
Use our free URL Encoder tool to quickly encode or decode URLs, query strings, and special characters—all processed locally in your browser.
Open URL EncoderURL Encoding in Other Languages
| Language | Encode | Decode |
|---|---|---|
| Python | urllib.parse.quote(s, safe="") | urllib.parse.unquote(s) |
| PHP | rawurlencode($s) | rawurldecode($s) |
| Java | URLEncoder.encode(s, "UTF-8") | URLDecoder.decode(s, "UTF-8") |
| C# | Uri.EscapeDataString(s) | Uri.UnescapeDataString(s) |
| Ruby | CGI.escape(s) | CGI.unescape(s) |
| Go | url.QueryEscape(s) | url.QueryUnescape(s) |