URL Encoding Explained: Percent-Encoding Made Simple
Which characters are allowed in a URL, why a space becomes %20, and how to avoid double-encoding bugs.
Why URLs need encoding
A URL is more than an address. Its characters also describe its structure: / separates path segments, ? starts the query string, & separates parameters and # starts a fragment. If one of those characters appears inside a value, for example a search for “fish & chips”, the browser or server cannot tell data from structure.
URLs are also limited to a small set of ASCII characters. Spaces, accented letters, emoji and most symbols are not allowed as they are. Percent-encoding, defined in RFC 3986, solves both problems.
How percent-encoding works
A character that is not allowed is converted to bytes using UTF-8, and each byte is written as a percent sign followed by two hexadecimal digits:
- A space (byte 32) becomes
%20. - An ampersand becomes
%26. - “é” is two bytes in UTF-8, so it becomes
%C3%A9. - The emoji 👋 is four bytes, so it becomes
%F0%9F%91%8B.
Unreserved and reserved characters
RFC 3986 splits characters into groups:
- Unreserved:
A–Z a–z 0–9 - . _ ~. These never need encoding. - Reserved:
: / ? # [ ] @ ! $ & ' ( ) * + , ; =. These have structural meaning and must be encoded when they appear inside a value. - Everything else, including spaces and non-ASCII characters, must always be encoded.
Encoding a whole URL versus one value
This is where most mistakes happen. JavaScript offers two functions that reflect the difference:
encodeURIComponent()encodes everything except unreserved characters (and a few marks such as! ' ( ) *). Use it for a single value, such as a query parameter or a path segment.encodeURI()leaves reserved characters alone, so a complete URL keeps working. Use it only when you already have a full address that contains spaces or non-ASCII characters.
Suppose a user searches for cats & dogs. The correct link is /search?q=cats%20%26%20dogs. If you only used encodeURI(), the & would stay as it is, and the server would read a query of “cats ” plus a second, empty parameter called “ dogs”. Our URL Encoder offers both modes.
%20 or + for spaces?
Both appear in the wild. %20 is the general URL encoding of a space and is valid anywhere. The plus sign comes from the application/x-www-form-urlencoded format that HTML forms use for query strings, where + means a space. Outside query strings, a plus is just a plus. When decoding form data or analytics reports, treat + as a space. The URL Decoder has an option for this.
The double-encoding trap
If a value is encoded twice, the percent sign itself is encoded as %25, so a space turns into %2520. Links like this show literal “%20” text on the destination page. It usually happens when a library encodes values automatically and the developer encodes them as well. The fix is to encode each value exactly once, at the point where the URL is built. If you receive double-encoded data, decode it twice.
Readable URLs with slugs
For page addresses that you control, it is better to avoid the need for encoding. A slug such as /guides/url-encoding-explained uses only lowercase letters, digits and hyphens, so it is readable, shareable and never needs escaping. Our Slug Generator turns titles into slugs like this.
Checklist
- Encode each query value and path segment separately with component encoding.
- Use UTF-8, the web standard, for non-ASCII characters.
- Encode once.
%25in your links is a sign of double encoding. - Use clean slugs for your own page URLs.