URL Encoding Explained
Three encode modes, one bytes-to-characters rule, and a surprising number of ways to break URLs. Here is the full picture.
https://example.com/search?q=hello world&tag=café → https%3A%2F%2Fexample.com%2Fsearch%3Fq%3Dhello%20world%26tag%3Dcaf%C3%A9
https://example.com/search?q=hello world&tag=café → https://example.com/search?q=hello%20world&tag=caf%C3%A9
The Core Rule
URL characters are limited to A–Z a–z 0–9 plus a handful of symbols. Anything else must be percent-encoded: each byte of the UTF-8 representation becomes %XX, where XX is the hex value of the byte.
Three Encode Modes in JavaScript
encodeURIComponent— encodes everything exceptA–Z a–z 0–9 - _ . ! ~ * ' ( ). Use this for query values and path segments.encodeURI— leaves URL-structural characters alone (:/?#[]@!$&'()*+,;=). Use for whole URL strings where you want to keep the scheme, host, and separators intact.form-urlencoded— likeencodeURIComponentbut spaces become+. HTML form submissions use this.
Reserved vs Unreserved (RFC 3986)
Unreserved characters never need encoding. Reserved characters (: / ? # [ ] @ ! $ & ' ( ) * + , ; =) have special meaning in the URL grammar and must be encoded when used literally in a value.
Common Mistakes
- Double-encoding: encoding an already-encoded string turns
%20into%2520 - Using
encodeURIon a query value:&and=leak through and break parsing - Forgetting UTF-8: non-ASCII must be encoded as UTF-8 bytes, not Latin-1
- Mixing
+and%20: query strings accept both for spaces; be consistent
Try It
Encode or decode any string in your browser with our free URL Encoder and URL Decoder.
Encode values, not URLs
Use encodeURIComponent for query values; encodeURI for whole URLs.
Always UTF-8
Non-ASCII goes in as UTF-8 bytes before percent-encoding.
Encode once
Double-encoding is a top-10 production bug source.