You’ve seen %20 in URLs and wondered what it means. Or your API request failed because an & in a parameter value broke the query string. URL encoding — also called percent encoding — is one of those fundamentals that causes constant bugs when misunderstood. This guide covers everything you actually need to know.
Why URLs Need Encoding
URLs can only contain a specific set of ASCII characters. Characters outside this set — spaces, symbols, non-Latin letters — must be encoded before they can appear in a URL. Without encoding, a space in a URL breaks the request, and a & in a parameter value gets parsed as a parameter separator.
The safe characters that don’t need encoding: A–Z a–z 0–9 - _ . ~
Everything else — including spaces, &, =, ?, /, #, and non-ASCII characters — must be percent-encoded when used in a query parameter value.
How Percent Encoding Works
Each unsafe character is replaced by a % followed by its two-digit hexadecimal ASCII (or UTF-8) code:
- Space →
%20(or+in form data) &→%26=→%3D+→%2B/→%2F?→%3F#→%23@→%40
You can encode and decode any string instantly with our URL Encoder tool.
encodeURI vs encodeURIComponent — The Critical Difference
This is where most bugs happen. JavaScript gives you two functions, and choosing the wrong one breaks things:
encodeURI(url)— encodes a complete URL. Leaves:// ? & = # /untouched because they’re structural parts of the URL.encodeURIComponent(value)— encodes a single value. Encodes everything including& = ? /— use this for query parameter values.
// Wrong — & in value breaks the query string
const url = `https://api.example.com/search?q=${userInput}`
// Correct — encode the value, not the full URL
const url = `https://api.example.com/search?q=${encodeURIComponent(userInput)}`
URL Encoding in Other Languages
# Python
from urllib.parse import quote, urlencode
quote(string) # encodes a path segment
quote(string, safe='') # encodes everything (like encodeURIComponent)
urlencode({'key': 'value with spaces & symbols'}) # encodes a dict as query string
# PHP
urlencode($string) # encodes for query strings (spaces as +)
rawurlencode($string) # RFC 3986 encoding (spaces as %20)
# curl (command line)
curl -G "https://api.example.com" --data-urlencode "q=hello world & more"
Common URL Encoding Bugs
- Double-encoding — encoding an already-encoded string turns
%20into%2520. Always decode first, then re-encode if needed. - Encoding the whole URL — encoding
https://produceshttps%3A%2F%2Fwhich breaks the request. Only encode parameter values. - Forgetting non-ASCII characters — emoji and accented characters must be UTF-8 encoded then percent-encoded.
ébecomes%C3%A9. - Using + for spaces outside forms —
+means space only inapplication/x-www-form-urlencodedcontent type. In path segments, use%20.
Frequently Asked Questions
What is the difference between %20 and + for spaces?
%20 is the RFC 3986 standard encoding for a space in any part of a URL. + represents a space only in HTML form data (application/x-www-form-urlencoded). Use %20 for path segments and when in doubt; use + only for form-encoded query strings.
Why do some URLs work with spaces in them?
Browsers are lenient — they automatically encode spaces in URLs you type in the address bar. But this is browser behavior, not the URL spec. Code that constructs URLs must always encode explicitly; relying on browser tolerance breaks in APIs, curl, and server-side code.
How do I decode a URL-encoded string?
In JavaScript: decodeURIComponent(encoded). In Python: from urllib.parse import unquote; unquote(encoded). Or paste it into our URL Encoder / Decoder for an instant result.
Are URLs case-sensitive?
The host portion (example.com) is case-insensitive. The path, query string, and fragment are case-sensitive on most servers. Percent-encoded hex digits are case-insensitive — %2F and %2f are equivalent, but it’s best practice to use uppercase.