Web 4 min read · 2 August 2026

URL encoding: why your link is full of %20 and what it means

Percent-encoding exists because a URL can only legally contain a small set of characters. Understanding which ones — and why — makes a whole category of broken links obvious.

URLs were specified in 1994, when the safe assumption was that anything travelling between two computers should be plain ASCII. That decision is why a link to a file called "annual report.pdf" arrives as annual%20report.pdf, and why understanding the rule saves you from a whole family of broken links.

The rule

A URL may only contain a limited set of characters: letters, digits, and a handful of punctuation marks. Everything else has to be encoded as a percent sign followed by two hexadecimal digits giving the character's byte value.

A space is byte 0x20, so it becomes %20. That is the whole mechanism.

For anything outside ASCII, the character is first converted to its UTF-8 bytes, and then each byte is percent-encoded. This is why non-English text expands so dramatically in a URL. The character é is two bytes, so it becomes %C3%A9. An emoji is four bytes and becomes twelve characters. A URL with a few emoji in it looks absurd for a completely mundane reason.

Reserved characters: the part that actually matters

Some characters are legal in a URL but have a structural job. These are the reserved characters:

: / ? # [ ] @ ! $ & ' ( ) * + , ; =

The ? starts the query string. The & separates parameters. The = splits a parameter name from its value. The / separates path segments. The # starts the fragment.

Here is the whole problem in one line: if one of those characters appears inside a value rather than as structure, it must be encoded, or it will be read as structure.

Consider a search for "cats & dogs":

https://example.com/search?q=cats & dogs     ← broken
https://example.com/search?q=cats%20%26%20dogs  ← correct

In the broken version, the server sees a parameter q with the value cats , and then a second parameter called dogs with no value. The ampersand did its structural job, which is not what you wanted. No error is raised — you simply get the wrong search results, which is a far more annoying failure than a crash.

Encoding a whole URL versus encoding one value

This is the distinction that trips up most people, and in JavaScript it is the difference between two functions.

encodeURIComponent() encodes reserved characters too. Use it on a single value you are inserting into a URL — a search term, a filename, a redirect target.

encodeURI() leaves reserved characters alone. Use it on a complete URL that is already assembled, where the slashes and question marks are meant to be structure.

Getting them the wrong way round produces two distinct failures. Using encodeURI on a value leaves the ampersands intact and your parameter splits in two. Using encodeURIComponent on a whole URL turns https:// into https%3A%2F%2F and the link stops being a link.

The rule of thumb: encode the pieces, then assemble. Never assemble and then encode.

Why + sometimes means space

There are two conventions, and the confusion is genuine.

In a URL path, a space is %20 and a + is a literal plus sign.

In a query string submitted by an HTML form, spaces are encoded as +. This comes from the older application/x-www-form-urlencoded format, and it is still what browsers do when they submit a form.

So ?q=cats+dogs and ?q=cats%20dogs both mean "cats dogs" in a query string, and a decoder has to handle both. In a path, they mean different things. A strict percent-decoder leaves + alone, which is why decoding a query string sometimes leaves you looking at plus signs where spaces should be.

Double encoding

If you encode something that is already encoded, the percent signs themselves get encoded. % is byte 0x25, so %20 becomes %2520.

This is easy to spot once you know the shape: a URL containing %25 followed by two more hex digits has usually been encoded twice. It normally happens when a value passes through two layers that each helpfully encode it — a framework and then a template, or an application and then a redirect service.

Decoding it twice recovers the original. Fixing it properly means finding which layer is encoding redundantly.

Where this shows up in practice

Redirect parameters. A URL inside a URL must be fully encoded, or its own query string merges into the outer one. This is the single most common place double-encoding appears, because it is the one place people know encoding is needed and apply it twice to be safe.

Filenames with spaces. Upload "final report v2.pdf" and any system that does not encode the space produces a link that stops at "final".

Tracking links. The long unreadable URLs from marketing emails are usually a destination URL, percent-encoded, sitting inside a parameter of a tracking URL. Decoding one reveals exactly where you are actually being sent — which is a reasonable thing to check before clicking something from an email you were not expecting.

Decoding a URL never visits it. It is pure text transformation, which makes it a safe way to inspect a link you do not trust.

More guides

Stay Updated

Get the latest tools, AI features, and product updates. No spam.