URL encoding is one of those topics where everyone knows %20 is a space and almost nobody is sure about the rest. It matters more than it looks: get it wrong and you break a link, and get it wrong in a specific way and you introduce a vulnerability.

Encode or decode components with the URL Encoder / Decoder, which runs entirely in your browser.

Why it exists

A URL has structure. ? starts the query string, & separates parameters, = splits name from value, # begins the fragment, / divides path segments.

So what happens when a value contains one of those characters? Consider a search for coffee & cake:

https://example.com/search?q=coffee & cake

The & is read as a separator, so the server sees a parameter q holding coffee and a second parameter called cake. The space breaks things further. Percent-encoding removes the ambiguity:

https://example.com/search?q=coffee%20%26%20cake

Each problematic byte becomes % followed by its two-digit hex value. Space is %20, & is %26, / is %2F.

What needs encoding

Unreserved characters never need it: A–Z a–z 0–9 - _ . ~.

Reserved characters need encoding when they appear inside a value rather than doing their structural job: : / ? # [ ] @ ! $ & ' ( ) * + , ; =.

That distinction is the whole thing. The ? that starts your query string stays raw. A ? inside a parameter value gets encoded. Same character, different role.

The plus-sign trap

In a query string, + historically means a space. In a path, it means a literal plus.

So ?q=a+b is usually read as "a b", while /a+b is the path "a+b". This inconsistency is genuinely confusing and causes real bugs, most visibly with email addresses: a subaddress like you+news@example.com passed unencoded through a query string can arrive as you news@example.com and fail validation.

Encode it as %2B and the ambiguity disappears.

encodeURI versus encodeURIComponent

JavaScript gives you two functions and the difference matters.

encodeURI() is for a whole URL. It leaves the structural characters alone, so the URL still works.

encodeURIComponent() is for a single value. It encodes / ? & = # and the rest, because inside a value those are data, not structure.

The rule: building a URL, use encodeURI. Inserting a value into one, use encodeURIComponent. Using the wrong one is how a URL passed as a redirect parameter silently truncates at its own query string.

Where this becomes a security problem

Double encoding. Encode % itself and %2F becomes %252F. If one layer of your stack decodes and another decodes again, a value that passed a filter as harmless can turn into something meaningful afterwards. This is a classic path-traversal bypass: %252e%252e%252f survives a filter looking for ../, then decodes into it downstream.

The defence is to decode exactly once, then validate. Never validate before decoding, and never decode twice.

Open redirects. Encoding is often used to disguise a redirect target so it slips past a naive check. Validate the destination after decoding, against an allowlist of your own hosts — the redirect article goes into this.

Filter evasion generally. Any filter matching on raw strings can be dodged by encoding. Encoding is not sanitisation, and it never was — it changes representation, not meaning.

Reading an encoded URL

Phishing links lean on this, because a heavily encoded URL is unreadable at a glance and people click rather than squint.

Paste it into the decoder and read what comes out. Two things to look for: where the host actually is — everything before the first single / after the scheme — and whether any parameter contains another full URL, which usually signals a redirect.

A useful habit: @ in a URL means everything before it is credentials, not the host. https://www.yourbank.com@attacker.example/ goes to attacker.example. Encoded, that is even easier to miss.

Common questions

Why is a space %20 sometimes and + other times?
+ means space in query strings by convention; %20 works everywhere. Use %20 when unsure.

encodeURI or encodeURIComponent?
encodeURI for a complete URL, encodeURIComponent for a single value going into one.

What is double encoding?
Encoding already-encoded data, so %2F becomes %252F. Used to slip past filters when something decodes twice.

Does URL encoding make input safe?
No. It changes representation, not meaning. Validate after decoding.

Where to go next

  • Decode a URL with the URL Encoder / Decoder.
  • For binary data rather than URL components, see Base64.
  • Chasing a suspicious link? Combine this with the redirect checker to see where it really lands.
  • Encoded URL you cannot make sense of? Bring it to the BitCops community.
  • Encoding bugs that turn into security bugs get picked apart in the forum.