ToolSite
All posts

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.

By ToolSite5 min readguides

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:

CharacterEncodedMeaning in a URL
Space%20Not allowed raw
#%23Fragment separator
&%26Query parameter separator
?%3FQuery string start
=%3DKey-value delimiter
+%2BSpace (in form data)
/%2FPath separator
%%25Percent 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:

  1. Space becomes %20
  2. & 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 GET method: 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 & Elsa into the input, and click Encode. The output should show Anna%20%26%20Elsa. Paste the encoded string back into the input and click Decode to verify the round-trip. Then encode 50% off and confirm the % becomes %25. Try encoding a full URL like https://example.com/path?q=test and observe that every : and / is percent-encoded.

Related Reading