URL Encode Decode — Encode and Decode URLs Online
URL encoding converts special characters to percent-encoded sequences (%20 for space, %2F for slash). Here's when to encode, what gets encoded, and the difference between...
URL encoding converts characters that aren’t safe in a URL into percent-encoded sequences. A space becomes %20. A forward slash becomes %2F. An ampersand becomes %26. The encoded URL carries the same information but uses only the 66 characters that are safe in URLs.
Use the URL Encoder to encode and decode URLs and query strings instantly.
Which characters need encoding
URLs are built from a limited safe character set (RFC 3986 unreserved characters):
- Letters:
A–Z,a–z - Digits:
0–9 - Special:
-,_,.,~
Everything else — spaces, non-ASCII characters, &, =, ?, #, /, : — must be percent-encoded if they appear as literal data (not as URL structure).
Unencoded: hello world
Encoded: hello%20world
Unencoded: Price: $20 & tax
Encoded: Price%3A%20%2420%20%26%20tax
Unencoded: search=hello world&category=tech & news
Encoded: search=hello%20world&category=tech%20%26%20news
Percent encoding explained
Each percent-encoded character is % followed by two hexadecimal digits representing the byte value in UTF-8:
Space (ASCII 32, hex 20): %20
/ (ASCII 47, hex 2F): %2F
@ (ASCII 64, hex 40): %40
= (ASCII 61, hex 3D): %3D
& (ASCII 38, hex 26): %26
# (ASCII 35, hex 23): %23
? (ASCII 63, hex 3F): %3F
For non-ASCII characters (Unicode), the character is first encoded as UTF-8 bytes, then each byte is percent-encoded:
Ñ → UTF-8: 0xC3 0x91 → %C3%91
€ → UTF-8: 0xE2 0x82 0xAC → %E2%82%AC
😀 → UTF-8: 0xF0 0x9F 0x98 0x80 → %F0%9F%98%80
encodeURI vs encodeURIComponent
This is the most common URL encoding mistake in JavaScript.
encodeURI: Encodes a full URL. Preserves characters that have structural meaning in a URL (/, ?, #, &, =, :, @).
encodeURIComponent: Encodes a URL component (a single value). Encodes everything including structural URL characters.
const path = 'search/hello world';
const param = 'hello & world';
const date = '2024-05-11';
// Wrong: encodeURI on a parameter value
console.log('?q=' + encodeURI(param));
// ?q=hello%20&%20world ← & NOT encoded → breaks the URL structure!
// Correct: encodeURIComponent on a parameter value
console.log('?q=' + encodeURIComponent(param));
// ?q=hello%20%26%20world ← & encoded to %26 ✓
// For a full URL:
console.log(encodeURI('https://example.com/path/hello world?q=test'));
// https://example.com/path/hello%20world?q=test ← space encoded, structure preserved
Rule: Use encodeURIComponent for any individual value being inserted into a URL. Use encodeURI for the entire URL string.
How to encode and decode
JavaScript (browser/Node.js)
// Encoding:
const encoded = encodeURIComponent('hello world & more');
console.log(encoded); // "hello%20world%20%26%20more"
// Decoding:
const decoded = decodeURIComponent('hello%20world%20%26%20more');
console.log(decoded); // "hello world & more"
// Building a URL with query parameters (use URLSearchParams):
const params = new URLSearchParams({
q: 'hello world',
category: 'tech & news',
page: '1'
});
console.log(params.toString());
// q=hello+world&category=tech+%26+news&page=1
// Note: URLSearchParams uses + for spaces, not %20 (form encoding standard)
const url = `https://example.com/search?${params}`;
Python
from urllib.parse import quote, unquote, urlencode
# Encode a single value:
encoded = quote('hello world & more')
print(encoded) # "hello%20world%20%26%20more"
# Safe characters (don't encode these):
encoded_safe = quote('path/to/resource', safe='/')
print(encoded_safe) # "path/to/resource" (/ preserved)
# Decode:
decoded = unquote('hello%20world%20%26%20more')
print(decoded) # "hello world & more"
# Build a full query string:
params = {'q': 'hello world', 'category': 'tech & news'}
query_string = urlencode(params)
print(query_string) # "q=hello+world&category=tech+%26+news"
PHP
// Encode for use in a query parameter:
$encoded = urlencode('hello world & more');
echo $encoded; // "hello+world+%26+more"
// Decode:
$decoded = urldecode('hello+world+%26+more');
echo $decoded; // "hello world & more"
// For path components (uses %20 instead of +):
$encoded_path = rawurlencode('hello world');
echo $encoded_path; // "hello%20world"
+ vs %20 for spaces
Two conventions for spaces in URLs:
- %20: Correct per RFC 3986 for all URL contexts
- +: Correct in form-encoded (
application/x-www-form-urlencoded) query strings
This creates confusion: some APIs expect + for spaces in query strings, others expect %20. Most modern APIs accept both. When building URLs manually: use %20. When using URLSearchParams or urlencode(), you get + in query strings by default.
+ is only valid as a space replacement in query strings — not in path segments.
What not to double-encode
If you receive an already-encoded string and pass it through encoding again, you get double-encoding:
Original: hello world
Encoded: hello%20world
Double-encoded: hello%2520world (% itself got encoded to %25)
%2520 decodes to %20, which decodes to . If you see %25 in a URL, double-encoding is likely the cause.
Only encode when taking raw user input and inserting it into a URL. If the value is already encoded (from a URL parameter), don’t re-encode it.
Related tools
- URL Encoder — encode and decode URLs in your browser
- URL Encoding Bugs — common mistakes and how to fix them
- Percent Encoding RFC 3986 — the specification for URL encoding
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…
- Base64 Encode Online — Encode Text and Files to Base64 Instantly — Base64 encoding converts binary data into printable ASCII text. It's used in ema…
Related tool
Percent-encode and decode URLs per RFC 3986.
Written by Mian Ali Khalid. Part of the Encoding & Crypto pillar.