Ever pasted a link and seen %E4%B8%AD where a word should be, or had a query parameter mysteriously break? That’s URL encoding at work. Understanding it turns those cryptic strings into something you can reason about.
Why URLs need encoding
A URL may only contain a limited set of ASCII characters. Anything else — spaces, non-ASCII text, or characters that have special meaning like ?, &, #, / — must be percent-encoded: replaced by a % followed by the byte’s two-digit hex value. For example, a space becomes %20 and 中 (UTF-8) becomes %E4%B8%AD.
You can encode or decode any string instantly with a URL encoder.
Reserved vs. unreserved characters
- Unreserved characters (
A–Z a–z 0–9 - _ . ~) never need encoding. - Reserved characters (
: / ? # [ ] @ ! $ & ' ( ) * + , ; =) have structural meaning in a URL. Whether you encode them depends on context — inside a value they must be encoded; as structure they must not.
This is the heart of the encodeURIComponent vs. encodeURI distinction.
encodeURIComponent vs. encodeURI
encodeURIComponentencodes reserved characters too. Use it for a single value — one query parameter, one path segment.encodeURIleaves reserved structural characters (/ ? & =) intact. Use it for an entire URL you don’t want to break apart.
encodeURIComponent("a b&c=d") // "a%20b%26c%3Dd" ✅ safe as a value
encodeURI("https://x.com/a b") // "https://x.com/a%20b" ✅ whole URL
Picking the wrong one is a top source of bugs: use encodeURI on a value and the & inside won’t be escaped, corrupting your query string.
%20 vs. +
Both can represent a space, but in different contexts. In a URL path and modern query strings the standard is %20. The + for a space comes from the older application/x-www-form-urlencoded format used by HTML form submissions. When in doubt, %20 is the safe, universal choice — and it’s what our tool produces.
The classic double-encoding bug
If a string is encoded twice, %20 becomes %2520 (because the % itself gets encoded to %25). Symptoms: literal %20 showing up in the browser, or spaces turning into %2520. The fix is to encode exactly once — decode first if you’re unsure of the input’s state. A decoder makes it easy to inspect what you actually have.
Quick reference
- Encoding a parameter value? →
encodeURIComponent. - Encoding a whole URL? →
encodeURI. - See a stray
%XX? → decode it to read the original.
Encode and decode URLs and query parameters instantly with the free URL encoder / decoder — it runs locally in your browser.