URL Encoding Explained (Why You See %20 in Links)
September 8, 20265 min readWhat percent-encoding is, how it works, and the difference between encoding a whole URL and a single parameter value.
Ever seen a link with %20 or %2F scattered through it and wondered what those were? That’s URL encoding (also called percent-encoding), and it’s what keeps links from breaking when they contain spaces, symbols, or non-English characters. Here’s how it works and when you need it.
Why URLs need encoding
A URL can only safely contain a limited set of characters: letters, digits, and a handful of symbols. Everything else has to be represented indirectly, because many characters already have a special job in a URL. A ? starts the query string, & separates parameters, / separates path segments, and a space isn’t allowed at all. If your data contains one of those, it has to be encoded so it’s treated as data, not as structure.
How percent-encoding works
The rule is simple: take the character’s byte value and write it as a % followed by two hexadecimal digits. A space is byte 32, which is 20 in hex — hence %20.
Space → %20
/ → %2F
? → %3F
& → %26
= → %3D
é → %C3%A9 (two bytes in UTF-8)Non-English characters take more than one byte in UTF-8, so they encode to multiple percent-pairs. The URL Encoder / Decoder handles all of this both ways.
A worked example
Say you want to put the search phrase coffee & tea into a URL parameter:
Broken: https://site.com/search?q=coffee & tea
Encoded: https://site.com/search?q=coffee%20%26%20teaWithout encoding, the raw & would be read as the start of a second parameter and the space would break the URL. Encoding turns the whole phrase into a single, safe value.
Encoding a whole URL vs. one piece of it
This is the subtle part. There are two levels:
- Encoding a component (one parameter value) escapes everything special, including
/,?, and&, because inside a single value those are just characters. This is what you want almost every time — it matches JavaScript’sencodeURIComponent(). - Encoding a full URL leaves the structural characters alone so the URL still works as a URL (like
encodeURI()). You’d only use this on a complete address, not on a value you’re inserting into one.
The mistake people make is component-encoding a full URL (turning the :// into gibberish) or full-encoding a value that contained an & (which then breaks the query string). When in doubt, you’re usually encoding a value, so use component encoding.
Related: it’s not the only kind of encoding
URL encoding is a cousin of Base64 encoding — both make data safe for a text-based channel, and neither is encryption. And like all encoding, it’s fully reversible: decoding %20 always gives back a space. Paste any messy or encoded URL into the decoder to read it in plain text.