Why URLs need encoding
A URL is a plain-text string, but not all characters are safe to include in one. The URL specification (RFC 3986) divides characters into two groups:
- Reserved characters — they have a defined meaning within URL syntax:
: / ? # [ ] @ ! $ & ' ( ) * + , ; = - Unreserved characters — they carry no special meaning and are always safe: letters (
A–Z,a–z), digits (0–9), and-,_,.,~
Any other character — or any reserved character being used as data rather than as a delimiter — must be encoded before it appears in a URL.
What is percent encoding?
Percent encoding (also called URL encoding) replaces an unsafe character with a % sign followed by the character's two-digit hexadecimal byte value.
For example:
| Character | Encoded form |
|---|---|
| Space | %20 |
# | %23 |
& | %26 |
= | %3D |
+ | %2B |
/ | %2F |
? | %3F |
@ | %40 |
The space problem
Spaces are not allowed in URLs. They have two common encodings depending on context:
%20— the correct percent-encoding for a space in a URL path or query value.+— a historical convention used in HTML form submissions (application/x-www-form-urlencoded). In this encoding,+means space and an actual+is written as%2B.
This distinction causes bugs. A query string decoded with form-decoding logic will turn %20 back into a space correctly, but it will also turn + into a space — which may not be what you intended. When building URLs programmatically, always use %20 for spaces in the URL itself and let the framework handle form encoding separately.
A practical example
Suppose a search form submits this query:
search term & filter=price>100
The raw query string would be:
q=search term & filter=price>100
This is broken — the bare & looks like a parameter separator, the space is invalid, and > is not a reserved character but is commonly encoded for safety. After URL encoding:
q=search%20term%20%26%20filter%3Dprice%3E100
Now the entire value is safely embedded as a single query parameter.
URL encoding vs decoding
Encoding converts plain text or binary data into a percent-encoded representation safe for use in a URL.
Decoding reverses that process — converting %20 back to a space, %26 back to &, and so on.
Most programming environments provide built-in functions for both:
| Language | Encode | Decode |
|---|---|---|
| JavaScript | encodeURIComponent(str) | decodeURIComponent(str) |
| Python | urllib.parse.quote(str) | urllib.parse.unquote(str) |
| Java | URLEncoder.encode(str, "UTF-8") | URLDecoder.decode(str, "UTF-8") |
| PHP | urlencode(str) | urldecode(str) |
Note: JavaScript has both encodeURI() and encodeURIComponent(). Use encodeURIComponent() for individual values (it encodes /, ?, &, =, etc.). Use encodeURI() only for a complete URL that already has its structure in place.
Non-ASCII characters
Characters outside the ASCII range (e.g. accented letters, emoji, Chinese characters) are first encoded as UTF-8 bytes, and each byte is then percent-encoded.
For example, the Euro sign € is encoded in UTF-8 as the three bytes 0xE2 0x82 0xAC, which becomes %E2%82%AC.
Modern browsers generally handle this transparently, but server-side code must consistently decode URL parameters as UTF-8 to reconstruct the original string.
Common mistakes
- Double-encoding — encoding an already-encoded string produces
%2520instead of%20. If your URLs show%25unexpectedly, something is encoding twice. - Not encoding query parameter values — forgetting to encode
&within a value splits it into a new parameter. - Encoding the full URL instead of individual values — calling
encodeURIComponent()on an entire URL encodes the slashes and colons, breaking the URL structure.
Use the URL Encoder to encode individual values you need to embed in a URL, and the URL Decoder to inspect what an encoded URL or query string actually says.