URL Encoding Explained
Every developer has seen %20 in a URL, and most have at some point watched a link break because a stray & or # ended up in the wrong place. URL encoding is the mechanism that keeps URLs unambiguous — and it is one of those topics where a little precision saves a lot of debugging. This guide explains what gets encoded, why, and the two mistakes that cause nearly all URL bugs.
The problem
A URL is not just a string — it is a structured address, and it uses certain characters as punctuation to mark out its parts:
?begins the query string&separates one parameter from the next=separates a parameter's name from its value/separates path segments#begins the fragment
Now suppose a parameter's value genuinely contains one of these characters. A search for fish & chips would produce:
?q=fish & chips
The server sees the & and concludes that a new parameter has begun. Your search term is now fish and there is a mysterious empty parameter called chips. The URL has been misread — and worse, spaces are not permitted in URLs at all.
URL encoding (formally, percent-encoding) solves this by disguising such characters so they are treated as data rather than punctuation.
How percent-encoding works
The rule is simple: replace the character with a % followed by its byte value in hexadecimal.
- A space is byte 32, which is
20in hex → %20 &is 38 → %26?is 63 → %3F#is 35 → %23/is 47 → %2F%itself is 37 → %25
So the search becomes ?q=fish%20%26%20chips. Now the & is safely encoded, the server reads a single parameter, and everything works.
That famous %20is nothing more mysterious than “a space, written in hex.”
Why do I sometimes see + instead of %20?
Both encode a space, and the difference is genuinely confusing:
%20is the standard percent-encoding, valid anywhere in a URL.+means a space only in the query string, and only under the older HTML form-encoding convention (application/x-www-form-urlencoded).
The critical consequence: a + in the path is a literal plus sign, not a space. And if you want a literal plus in a query value, you must encode it as %2B — otherwise it will be read as a space. This bites people constantly with phone numbers: +8801712345678 becomes 8801712345678 unless properly encoded.
When in doubt, use %20. It is unambiguous everywhere.
What must be encoded, and what must not
A small set of characters are always safe and never need encoding — the unreserved characters:
A–Z a–z 0–9 - . _ ~
Everything else falls into two groups:
- Reserved characters (
: / ? # [ ] @ ! $ & ' ( ) * + , ; =) have structural meaning. Encode them when they appear inside a value; leave them alone when they are doing their structural job. - Everything else — spaces, quotes, non-English letters, emoji — must always be encoded.
That first point is the crux, and it explains the API most people get wrong.
encodeURI vs encodeURIComponent
JavaScript offers two functions, and choosing the wrong one is the most common URL-encoding bug in existence.
encodeURI()encodes a whole URL. It deliberately leaves the structural characters (/ ? & = #) intact, because they are supposed to be doing their job.encodeURIComponent()encodes a single piece — one parameter value. It encodes everything, including/ ? & =, because inside a value those are just data.
Use encodeURIComponent for individual parameter values. That is the one you want the vast majority of the time. Using encodeURI on a value leaves the & unencoded — and your URL breaks exactly as it did in the first example.
The double-encoding trap
A subtle, infuriating bug. Encode a string twice and you get nonsense:
- Original:
a b - Encoded once:
a%20b - Encoded again:
a%2520b— because the%itself got encoded to%25
Decode that once and you get a%20b — the literal text, not a space. The user sees %20 printed on the page.
This happens when a value is encoded in one layer of an application and then encoded again in another. If you are seeing %2520, %253A or similar, you are looking at double encoding. Encode exactly once, at the point where the URL is built.
Non-English characters and UTF-8
Characters outside ASCII — accented letters, Bengali, Chinese, emoji — are first encoded as UTF-8 bytes, and then each byte is percent-encoded. Since these characters take multiple bytes, they produce multiple percent-escapes.
The word café becomes caf%C3%A9 — the é is two UTF-8 bytes, so it needs two escapes. This is why a single character can expand into a long sequence, and why an encoding mismatch produces the classic garbled text.
Frequently asked questions
Is URL encoding a form of security? No. It is purely about correctness and transport. Anyone can decode it trivially.
Do I need to encode a URL I am just displaying? Not for display, but any URL you construct programmatically from user input must have its values encoded.
Why does my URL show %2520? Double encoding. Something encoded an already-encoded value.
Can URLs contain emoji? Yes — percent-encoded as UTF-8 bytes. Browsers often display them decoded, which hides how long the real URL is.
Encode a URL now
Use our URL Encoder/Decoder to encode and decode URLs in your browser — instant, private, nothing uploaded. Building clean, readable URLs for a website? The Slug Generator creates URL-safe slugs, and our guide on what a URL slug is explains why they matter.