What Is URL Encoding and When Do You Need It?
Learn what URL encoding (percent-encoding) is, which characters are reserved, and when you need it for query strings, form submissions, and safe URL building.
What URL Encoding Is
URL encoding, also called percent-encoding, is a way to represent characters in
a URL that are not safe to send as-is. Each unsafe character is replaced with a
% followed by two hexadecimal digits representing the character's byte value.
URLs have a restricted character set as defined by RFC 3986. The only characters that are always safe without encoding are:
- Unreserved:
A-Z,a-z,0-9,-,_,.,~ - Reserved (have special meaning in certain URL parts):
:,/,?,#,[,],@,!,$,&,',(,),*,+,,,;,=
Everything else, spaces, accented characters, emoji, non-ASCII symbols, must be percent-encoded. Reserved characters only need encoding when you intend them as literal data rather than their structural function.
Reserved Characters and Their Encodings
Reserved characters have special meaning in specific parts of a URL. When you want to use them as literal data (not as their special function), you must encode them:
| Character | Encoded | Meaning in a URL |
|---|---|---|
| Space | %20 | Not allowed raw |
| # | %23 | Fragment separator |
| & | %26 | Query parameter separator |
| ? | %3F | Query string start |
| = | %3D | Key-value delimiter |
| + | %2B | Space (in form data) |
| / | %2F | Path separator |
| % | %25 | Percent sign itself |
The percent sign must be encoded as %25 whenever it appears as literal data.
If you do not encode it, the parser interprets the following two characters as
a hex code. This is why double-encoding bugs happen: a URL that contains %20
as literal text gets encoded to %2520 instead of the intended %20.
Spaces, &, ?, # in Query Strings
Consider a search for the literal string cats & dogs:
https://example.com/search?q=cats%20%26%20dogs
Without encoding, the & would split the query string into two parameters:
https://example.com/search?q=cats & dogs
^
parser sees: q=cats, then bogus text
If you want to pass a URL as a query parameter (common for redirect callbacks), you must encode the inner URL too:
Original: https://example.com/login?redirect=https://app.com/dashboard?tab=home
Encoded: https://example.com/login?redirect=https%3A%2F%2Fapp.com%2Fdashboard%3Ftab%3Dhome
Every structural character in the inner URL, the ://, the /dashboard, the
?tab=, all of it must be encoded so the outer URL's parser does not see them
as structural.
encodeURIComponent vs encodeURI
JavaScript provides two built-in functions for URL encoding. They behave differently, and picking the wrong one is a common source of bugs:
const url = "https://example.com/search?q=hello world&lang=en";
encodeURI(url);
// "https://example.com/search?q=hello%20world&lang=en"
// Preserves: : / ? & = # (structural characters stay intact)
encodeURIComponent(url);
// "https%3A%2F%2Fexample.com%2Fsearch%3Fq%3Dhello%20world%26lang%3Den"
// Encodes everything, including : / ? & = #
Use encodeURIComponent when building individual query parameter values. Use
encodeURI only when you have a complete URL that already contains its
structural characters and you only need to fix unsafe characters within it. In
practice, most bugs come from using encodeURI on query values and leaking raw
& or = into the URL.
For path segments, encodeURIComponent is also the right choice, but / will
be encoded to %2F. If you need to keep / as a path separator in a multi-level
path, encode each segment individually and join them with literal slashes.
How Browsers Handle Encoding Automatically
When you submit a <form method="GET">, the browser encodes form field values
using application/x-www-form-urlencoded rules before appending them to the
action URL. Spaces become +, not %20. This is a legacy from the early web
and is different from encodeURIComponent, which uses %20.
When you type a URL with non-ASCII characters into the address bar, modern browsers apply Punycode for the domain and percent-encoding for the path, query, and fragment. You rarely see the encoded form unless you copy the URL from the address bar.
Worked Example
You have a form where a user types their name. The value is Anna & Elsa.
You are building a query string:
?name=Anna%20%26%20Elsa
Step by step:
- Space becomes
%20 &becomes%26
The key name itself is safe (plain ASCII letters), so it stays as-is. Only
the value is encoded. This is the most common pattern: encode values, leave
keys and structural characters alone.
Now a trickier example. Your user enters a value containing a % sign, like
50% off. The encoding must produce 50%25%20off. If you encode 50% off to
50%20off and later decode it, you get 50 off. The percent was lost because
the parser treated %20 as a space. This is why % always encodes to %25.
When You Actually Need It
- Query strings: any user-supplied value that goes after a
?key - Path segments: if a filename contains a space or special character
- Redirect URLs: passing a full URL as a query parameter
- Form submissions with
GETmethod: the browser encodes automatically, but you need to be aware of it when debugging - API clients: when constructing URLs programmatically, always encode parameter values. Most HTTP libraries do this for you, but check.
Try it yourself: open the URL Encoder/Decoder, type
Anna & Elsainto the input, and click Encode. The output should showAnna%20%26%20Elsa. Paste the encoded string back into the input and click Decode to verify the round-trip. Then encode50% offand confirm the%becomes%25. Try encoding a full URL likehttps://example.com/path?q=testand observe that every:and/is percent-encoded.