What is URL Encoding?
Why URLs can only contain certain characters, how percent-encoding works, and when to encode and decode in practice.
Why URLs need encoding
URLs can only contain a limited set of characters defined by the RFC 3986 specification: letters (A–Z, a–z), digits (0–9), and a small set of special characters (- _ . ~). Characters outside this set must be encoded before being placed in a URL.
The restriction exists because URLs are transmitted over the internet as ASCII text, and many characters — spaces, non-Latin letters, symbols like &, =, ? — have special meaning in URL syntax or are not safe to transmit.
How percent-encoding works
Each unsafe character is replaced with a percent sign followed by its two-digit hexadecimal ASCII code. A space becomes %20. An at-sign (@) becomes %40.
Original: Hello World! How are you? Encoded: Hello%20World%21%20How%20are%20you%3F Original: user@example.com Encoded: user%40example.com Original: price=100¤cy=€ Encoded: price%3D100%26currency%3D%E2%82%AC
Non-ASCII characters (like the euro sign €) are first converted to UTF-8 bytes, then each byte is percent-encoded. That's why € becomes %E2%82%AC — three bytes.
Common encoded characters
| Character | Encoded | Why it needs encoding |
|---|---|---|
| Space | %20 | Not allowed in URLs |
| ! | %21 | Reserved character |
| # | %23 | Marks the fragment identifier |
| $ | %24 | Reserved character |
| & | %26 | Separates query string parameters |
| + | %2B | Used as space in some encodings |
| , | %2C | Reserved character |
| / | %2F | Path separator |
| : | %3A | Separates scheme from host |
| = | %3D | Separates key from value in query string |
| ? | %3F | Marks the start of the query string |
| @ | %40 | Separates userinfo from host |
encodeURI vs. encodeURIComponent
JavaScript has two built-in encoding functions with different scopes:
encodeURI()
Encodes a complete URL. Does not encode characters that have special meaning in URL structure: ; , / ? : @ & = + $ #
encodeURI("https://example.com/search?q=hello world")
// → "https://example.com/search?q=hello%20world"encodeURIComponent()
Encodes a URL component (like a query parameter value). Does encode the structural characters. Use this when encoding individual values before building a URL.
encodeURIComponent("hello world & goodbye")
// → "hello%20world%20%26%20goodbye"Frequently asked questions
- What's the difference between %20 and + for spaces?
- Both represent spaces, but in different contexts. %20 is the standard percent-encoding for a space in any URL context. The + sign is an alternative encoding for spaces used specifically in HTML form data (application/x-www-form-urlencoded format) and query strings. In a path segment, + means a literal plus sign — not a space. When in doubt, use %20.
- Do I need to encode URLs in HTML?
- URLs in HTML attributes should use HTML entity encoding for the ampersand (& instead of &), but the URL characters themselves follow URL encoding rules. When building URLs dynamically in JavaScript, always use encodeURIComponent() on individual values before concatenating them into a URL string.
- Why do some URLs look garbled?
- If you see strings like %E2%80%99 or %C3%A9 in a URL, you're seeing UTF-8 percent-encoded characters — typically non-ASCII characters like curly quotes, accented letters, or emoji. Decoding reveals the original character. Most modern browsers display decoded versions in the address bar for readability, but encode them when actually making the request.