URL Encoding Explained: Which Characters to Escape and Why

By Junaid Aslam. 4 min read. Updated .

Copy a link and you may find it full of %20 and %3D. That's URL encoding, also called percent-encoding. The rule is simple. Some characters have a job inside a URL. If you want to use one of them as plain data, you have to escape it so the browser doesn't mistake it for punctuation.

How percent-encoding works

A URL can only safely carry a small set of characters. Anything outside that set gets replaced by a percent sign followed by two hex digits. Those two digits are the byte value. A space is byte 32, which is hex 20, so it becomes %20.

For characters outside basic ASCII, the text is first converted to UTF-8 bytes, and each byte gets its own percent code. The letter é is two bytes in UTF-8 (C3 A9), so it becomes %C3%A9. Emoji take four bytes, so they turn into four percent groups.

Safe characters, reserved characters

RFC 3986, the standard that defines URLs, splits characters into two groups.

  • Unreserved (never need escaping): letters A-Z and a-z, digits 0-9, and the four symbols - . _ ~.
  • Reserved (have a special meaning): : / ? # [ ] @ ! $ & ' ( ) * + , ; =.

Reserved characters are fine when they're doing their job. The ? starts the query string, & separates parameters, and = joins a name to its value. The trouble starts when one of them appears inside your data. If a search term contains &, you must escape it, or the server will think a new parameter began.

The ones you'll hit most often

CharacterEncodedWhy it matters
Space%20Spaces aren't allowed in URLs at all.
&%26Would start a new query parameter.
=%3DWould split a name from its value.
?%3FWould start the query string early.
#%23Would start the fragment and cut off the rest.
/%2FWould add a new path segment.
+%2BOften read as a space in query strings.
%%25The escape character itself must be escaped.
@%40Separates user info from host.
:%3ASeparates scheme, port, and user info.

%20 or +? Both show up for spaces

This confuses everyone at some point. In the path part of a URL, a space is always %20. In HTML form submissions (the application/x-www-form-urlencoded format), a space is often written as +. Servers that parse query strings usually understand both. But if you send a literal plus sign as data, you must write %2B, or the server will read it as a space. That's a classic bug when people pass phone numbers like +15551234567 or Base64 strings in a query.

encodeURI vs encodeURIComponent

JavaScript gives you two functions, and picking the wrong one causes a lot of broken links.

  • encodeURIComponent escapes nearly everything, including / ? & = #. Use it on a single value that goes inside a URL, like one query parameter.
  • encodeURI leaves reserved characters alone so a full URL still works. Use it only when you're encoding a whole address that's already structured correctly.

The same input through both:

encodeURI("a b+c/d?e#f&g=h")
// a%20b+c/d?e#f&g=h

encodeURIComponent("100% & more")
// 100%25%20%26%20more

encodeURI kept +, /, ?, #, &, and = untouched. If you'd used it on a search term containing &, that term would break your query. When in doubt for parameter values, use encodeURIComponent.

The double-encoding trap

Encode a string twice and the percent signs themselves get escaped. %20 becomes %2520, because % turned into %25. You'll see this when a value passes through two layers of code that each think they're responsible for encoding. Symptoms are links that show %2520 in the address bar, or a server that receives the literal text %20 instead of a space.

The fix is to encode exactly once, at the last moment before the value goes into the URL, and decode exactly once on the other side. The URL Encoder can help you check. Decode once and see whether %20 shows up where you expected a space. If it does, something encoded the value twice. Its Double encode/decode box runs the operation twice in one click when you need to undo that.

Quick checklist

  1. Encode each parameter value separately, not the whole finished URL.
  2. Use UTF-8 for anything that isn't plain ASCII.
  3. Escape + as %2B when you mean a real plus sign.
  4. Never encode the same string twice.
  5. If a link works in one browser and not another, check for an unescaped # or & first.

Moving a Base64 or hash value through a URL? You'll want to read our notes on Base64 and why + and / cause trouble.

Try it yourself

More guides