URL Encoding Explained: Why Special Characters Need Escaping
URLs can only contain a limited set of characters. The allowed characters are letters (A–Z, a–z), digits (0–9), and a handful of punctuation marks (-, _, ., ~). Everything else — spaces, ampersands, equals signs, slashes, non-ASCII characters — must be encoded before it can appear in a URL.
URL encoding (also called percent-encoding) is the mechanism for doing that. Understanding it saves you from mysterious 400 errors and garbled request parameters.
How percent-encoding works
Each character that cannot appear literally in a URL is replaced by a percent sign followed by two hexadecimal digits representing the character's byte value in UTF-8. For example:
- A space becomes
%20(or+in query strings — more on that below) - An ampersand
&becomes%26 - An equals sign
=becomes%3D - A forward slash
/becomes%2F - A question mark
?becomes%3F - The copyright symbol © becomes
%C2%A9(two bytes in UTF-8)
Query strings vs. path segments
Different parts of a URL have different reserved characters and different encoding rules. In the path (the part before the ?), a forward slash / is a path separator and should not be encoded. In a query parameter value (after ?), a forward slash has no special meaning and does not need encoding — but an ampersand & does, because it separates query parameters.
This is why you need to encode each parameter key and value individually before assembling them into a query string with &, rather than encoding the whole query string at once.
The space problem: %20 vs +
Spaces in query string values have two valid encodings: %20 and +. The+ shorthand comes from the HTML form specification — when a browser submits a form with method="GET", it encodes spaces as + in the query string. Most web servers decode both correctly, but some APIs are strict. When in doubt, use %20.
In JavaScript, encodeURIComponent produces %20 for spaces. encodeURI also produces %20. The legacy escape() function produces %20 for spaces but incorrectly handles non-ASCII characters — avoid it.
encodeURI vs encodeURIComponent
JavaScript offers two built-in encoding functions with an important difference:
encodeURI(url)encodes a full URL. It leaves the characters that are valid in a URL structure — like/,?,#,&,=— untouched, because they have structural meaning.encodeURIComponent(value)encodes a URL component — a single parameter key or value. It encodes all characters that are not unreserved, including/,?,&, and=. Use this when encoding individual query parameter values.
The most common mistake: using encodeURI to encode a query parameter value. Since it leaves & and = unencoded, those characters will break the query string structure if they appear in the value.
Decoding: when and why
When a server receives a URL, it decodes the percent-encoded characters before passing them to your application. In most frameworks this happens automatically — you get the decoded string in your route handler. But when you are debugging raw HTTP requests, reading logs, or working with URLs programmatically, you will see the encoded form.
Double-encoding is another common issue: encoding something that is already encoded, producing %2520 (the % in %25 is the encoding of a literal percent sign). Always decode before re-encoding to avoid this.
Try it now