fixmint

Percent-encoding in URLs: what %20, + and %2F really mean

· 4 min read

Percent-encoding writes a character that a URL cannot carry safely as a percent sign followed by its byte value in hexadecimal. A space becomes %20, an ampersand becomes %26, and a slash becomes %2F. The encoding protects the structure of a link, because characters such as & and = separate the parts of a query string.

URL encode and decodeURL is full of %20 codesOpen

Which characters can stay as they are

The URI standard (RFC 3986), which URLs are built on, leaves some characters alone: the letters A to Z and a to z, the digits, and the four marks - _ . ~. These never need encoding. Other characters have a job in a URL. The colon separates the scheme from the rest, the slash separates path parts, the question mark starts the query, the hash starts a fragment, and & and = divide the query into names and values. A character with a job must be encoded when you mean it as data rather than as structure.

That is why the same character can be encoded in one place and not another. In a query value, an ampersand has to be %26, or the link splits in the wrong place. In the path of a link, it is just a character.

Non-English letters

Letters outside basic English are encoded as their UTF-8 bytes, and each byte is written as a percent code. The é in café is the two bytes C3 and A9, so it becomes %C3%A9, and the whole word becomes caf%C3%A9.

A simple example makes the rules concrete. The text a b&c=d/é, encoded as a component, becomes a%20b%26c%3Dd%2F%C3%A9. Every character that is not a safe letter, digit or mark is encoded: the space, the ampersand, the equals sign, the slash and the accented letter.

Component or whole URL

Two kinds of encoding exist for a reason. A component encoding treats every reserved character as data. Use it for one value, such as a search term or a file name inside a link. Encoding "rock & roll" as a search term gives rock%20%26%20roll, so the ampersand stays inside the value.

A whole-URL encoding keeps the structure. Encoding https://example.com/a b gives https://example.com/a%20b, with the slashes and the colon left alone. Use it for a complete address that needs to be made valid, not for a value that goes inside a link.

The URL tool has a Component and a Full URL setting for this reason. Full URL decoding also keeps escaped structural characters such as %26 and %3D, so the link still works after it is decoded.

Plus signs and form data

Web forms use a different convention. When a form is submitted as form data, a space is written as + rather than %20. A literal plus sign is then written as %2B. So the phrase C++ tips becomes C%2B%2B+tips in form data, and C%2B%2B%20tips in a plain component encoding.

Decoding has the same difference. In a query string, + usually means a space. In the path of a link, + is a plus sign. The tool reads + as a space only when the "+ for spaces" option is ticked, so leave it off for paths and for values where a plus sign is real.

Reading a long query string

A link often carries its settings after the question mark. Take this example:

https://shop.example/search?q=red%20shirt&size=M&tag=summer%2Bsale

Decoded, it says that the search is for red shirt, the size is M, and the tag is summer+sale. The %2B stays a plus sign because it was encoded. Paste the link into the URL tool and it lists each name and value after decoding, which makes a long link easy to read. If you only want the shorter address without tracking settings, clean the link first.

Double encoding

The most common mistake is encoding a value twice. Encoding the text %20 again gives %2520, because the percent sign itself is encoded as %25. The page then looks for a literal %20 in the value, and the search or the page does not match. Decode the link once, check the result, and encode a value only when you need to.

Broken escapes

A percent sign must be followed by two hexadecimal digits, and the digits must form valid UTF-8 for accented letters. A link that was cut short, or a stray percent sign typed into a text, can leave a broken escape such as %E0%A4%A. The tool decodes what it can, leaves the broken bytes exactly as written, and reports how many it could not decode. It does not stop at the first error.

Edge cases

  • Spaces in a link typed by hand. A browser address bar encodes spaces for you, but a link copied into a document can still contain raw spaces. Encode them before you send the link on.
  • Non-English domain names. These use a separate system, punycode, and encoding the path or the query does not change the host name.
  • Half an emoji. A broken copy can leave a single surrogate half, which cannot be encoded. The tool replaces it with the replacement symbol and tells you that it did.

Quick answers

What does %20 mean?

A space. Its byte value is 20 in hexadecimal.

Why is there a + in my link instead of %20?

The link probably came from a form, where + stands for a space. The "+ for spaces" option decodes it.

Why do I see %2520 in my link?

The value was encoded twice. The percent sign of %20 was encoded again as %25. Decode once to get back to %20, and again to get the space.

Cover of How to Remain Valuable When Intelligence Becomes CheapHow to Remain Valuable When Intelligence Becomes Cheap

224 pages on the human, economic and strategic advantages that stay scarce when AI can do most cognitive work.

$3.84 Get it on Gumroad →