URL Encoding Special Characters — Which Characters to Encode and When
URL encoding converts special characters to percent-encoded sequences (%20, %26, etc.). Here's which characters require encoding in query strings vs path segments, and how to...
URL encoding (percent-encoding) converts characters that have special meaning in URLs — or that aren’t valid URL characters — into %XX sequences where XX is the hexadecimal ASCII code. Getting encoding right prevents broken links, security vulnerabilities, and API failures.
Use the URL Encoder to encode and decode URL components online.
Why URL encoding is necessary
URLs have reserved characters with structural meaning:
https://example.com/path?key=value&key2=value2#fragment
└─────────┘ └───┘ └────┘└───────────────┘
path chars query key=value pairs
If your data contains &, =, ?, or #, they must be encoded to avoid being interpreted as URL structure.
Example problem:
// Query parameter with unencoded &:
https://api.com/search?q=fish & chips&format=json
// The & splits into two parameters:
q = "fish "
" chips" = "json" (fragment after second &)
// Correct (& encoded as %26):
https://api.com/search?q=fish%20%26%20chips&format=json
Characters by URL position
Path segments
Characters safe to use in path segments (no encoding needed):
A-Z a-z 0-9 - _ . ~ ! $ & ' ( ) * + , ; = : @ /
Characters that MUST be encoded in path segments:
Space → %20
? → %3F
# → %23
[ ] → %5B %5D
% → %25 (if literal percent needed)
Query string values
In query string values (?key=value), additional characters need encoding:
Space → %20 or +
& → %26
= → %3D
+ → %2B (if + is literal, not space)
# → %23
% → %25
Fragment identifier
After #, the fragment is not sent to servers (browser-only), but encoding still applies for non-ASCII characters.
RFC 3986 unreserved characters
These characters NEVER need encoding:
A-Z a-z 0-9 - _ . ~
All other characters either:
- Are reserved and have special meaning (
/ ? # : @ ! $ & ' ( ) * + , ; =) - Or must be percent-encoded if used as data
JavaScript encoding functions
JavaScript provides multiple encoding functions — choose the right one:
// encodeURIComponent — encode a single value/parameter:
encodeURIComponent('hello world'); // 'hello%20world'
encodeURIComponent('price=10&tax=1'); // 'price%3D10%26tax%3D1'
encodeURIComponent('https://example.com'); // 'https%3A%2F%2Fexample.com'
// encodeURI — encode a full URL (doesn't encode URL structure chars):
encodeURI('https://example.com/path?q=hello world');
// 'https://example.com/path?q=hello%20world'
// (/ : ? = are NOT encoded because they're URL structure)
// URLSearchParams — the cleanest way for query strings:
const params = new URLSearchParams({
q: 'fish & chips',
format: 'json',
page: '1',
});
console.log(params.toString());
// 'q=fish+%26+chips&format=json&page=1'
// Note: URLSearchParams uses + for spaces (application/x-www-form-urlencoded)
// Build full URL:
const url = new URL('https://api.example.com/search');
url.searchParams.set('q', 'hello & world');
url.searchParams.set('lang', 'en');
console.log(url.toString());
// 'https://api.example.com/search?q=hello+%26+world&lang=en'
When to use which function
// Encoding a query string value:
const searchTerm = 'fish & chips';
const url = `https://api.com/search?q=${encodeURIComponent(searchTerm)}`;
// Building query strings (best practice):
const params = new URLSearchParams({ q: searchTerm, page: 1 });
const url = `https://api.com/search?${params}`;
// Never use encodeURI for individual values:
encodeURI('fish & chips'); // 'fish%20&%20chips' — & NOT encoded! Bug!
// Encoding a path segment:
const slug = encodeURIComponent('hello world'); // 'hello%20world'
const url = `https://example.com/posts/${slug}`;
Python encoding
from urllib.parse import quote, quote_plus, urlencode, urlparse
# Encode a path segment (safe chars are preserved):
quote('hello world') # 'hello%20world'
quote('fish & chips') # 'fish%20%26%20chips'
# Encode a query string value (+ for spaces):
quote_plus('fish & chips') # 'fish+%26+chips'
# Encode multiple query parameters:
params = {'q': 'fish & chips', 'format': 'json', 'page': 1}
urlencode(params) # 'q=fish+%26+chips&format=json&page=1'
# Build a URL:
from urllib.parse import urlunparse, urlencode
base = 'https://api.example.com/search'
query = urlencode({'q': 'hello & world', 'page': 1})
url = f'{base}?{query}'
# 'https://api.example.com/search?q=hello+%26+world&page=1'
# Decode:
from urllib.parse import unquote, unquote_plus
unquote('hello%20world') # 'hello world'
unquote_plus('hello+world') # 'hello world'
Common encoding mistakes
Double encoding:
// WRONG: encoding already-encoded string:
const encoded = encodeURIComponent('hello%20world');
// 'hello%2520world' — %20 becomes %2520!
// CORRECT: only encode the original value:
const encoded = encodeURIComponent('hello world');
// 'hello%20world'
Not encoding user input in URLs:
// WRONG — XSS risk if user controls search:
const url = `https://example.com/search?q=${userInput}`;
// CORRECT:
const url = `https://example.com/search?q=${encodeURIComponent(userInput)}`;
Using encodeURI for query values:
// WRONG: encodeURI doesn't encode & = ?
const url = `https://api.com/?key=${encodeURI('a=b&c=d')}`;
// 'https://api.com/?key=a=b&c=d' — & creates new parameter!
// CORRECT:
const url = `https://api.com/?key=${encodeURIComponent('a=b&c=d')}`;
// 'https://api.com/?key=a%3Db%26c%3Dd'
Decoding URL components
// Decode:
decodeURIComponent('hello%20world'); // 'hello world'
decodeURIComponent('fish%20%26%20chips'); // 'fish & chips'
// Read query parameters from current URL:
const params = new URLSearchParams(window.location.search);
const q = params.get('q'); // Automatically decoded
// Parse a full URL:
const url = new URL('https://api.com/search?q=fish+%26+chips&page=2');
console.log(url.searchParams.get('q')); // 'fish & chips' (decoded)
Related tools
- URL Encoder — encode and decode URLs online
- URL Encode Decode Guide — encoding reference
- Percent Encoding RFC 3986 — standard specification
Related posts
- URL Encoding: The 7 Bugs That Break Your API — Every API has at least one URL-encoding bug. Here are the seven I see most — wha…
- Percent Encoding and RFC 3986 Explained — Why is `+` sometimes a space and sometimes a literal plus? Why does `%2520` show…
- Double URL Encoding — What It Is, Why It Happens, and How to Prevent It — Double URL encoding happens when an already-encoded URL is encoded again, turnin…
- URL Encode Decode — Encode and Decode URLs Online — URL encoding converts special characters to percent-encoded sequences (%20 for s…
Related tool
Percent-encode and decode URLs per RFC 3986.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.