When and why to URL-encode a string
Percent-encoding is straightforward in theory and quietly tricky in practice. Here is what the encoder does and the three real-world traps.
URL encoding (officially "percent-encoding") is what turns hello world into hello%20world. Easy to grasp; quietly easy to get wrong. The URL Encoder/Decoder makes the conversion explicit.
What gets encoded
URLs have a set of reserved characters with specific syntactic meaning: : / ? # [ ] @ ! $ & ' ( ) * + , ; =. Plus % itself (because it's the escape character).
To put any of these characters into a URL as data (rather than as syntax), you escape them as % followed by the two hex digits of the UTF-8 byte. Space (ASCII 32, hex 20) becomes %20. Forward slash becomes %2F. The é character (UTF-8 bytes C3 A9) becomes %C3%A9.
Unreserved characters (A-Z a-z 0-9 - _ . ~) are safe to use raw. Everything else either has syntactic meaning or is outside ASCII and must be encoded.
encodeURI vs encodeURIComponent
JavaScript has two encoding functions and they do different things:
encodeURI(url)escapes only characters that have no meaning in a URL. It leaves reserved characters (/,?,&,=) alone, assuming they're being used syntactically.encodeURIComponent(value)escapes everything that's not unreserved, including reserved characters. Use this when you're inserting a single value INTO a URL.
The tool here uses encodeURIComponent — because the common case is "I have a value, I want to put it in a URL." If you're constructing a full URL from parts (different bug), you'd use encodeURI on the whole thing.
Three real-world traps
Trap 1: Double encoding.
You URL-encode a value, paste it into a string template, and the receiving system encodes it again. hello world → hello%20world → hello%2520world. The %25 is the encoded form of %. Now the decoded result is hello%20world, not hello world.
Always encode exactly once. If you're not sure whether something is encoded, decode it first and look — if it round-trips to the same thing, it wasn't encoded.
Trap 2: Form encoding vs URL encoding.
HTML forms with Content-Type: application/x-www-form-urlencoded use percent-encoding plus one extra rule: space becomes + (not %20). The decoder accepts both. The encoder produces %20. Mostly compatible, but worth knowing if you ever generate query strings that get fed to a form parser.
Trap 3: UTF-8 vs Latin-1.
Old systems sometimes encoded non-ASCII characters as their Latin-1 byte values rather than UTF-8. So é would be %E9 (Latin-1) instead of %C3%A9 (UTF-8). Modern systems are all UTF-8, but legacy URLs you find in databases or logs might use the old encoding.
Quick reference
The five most-encoded characters and their codes:
- Space →
%20 #→%23&→%26=→%3D+→%2B
Memorise those and you can read most encoded URLs at a glance.
When you don't need to encode
- Static URLs in HTML. If you type
<a href="/foo?q=bar">with no special characters, the browser handles it. - Hardcoded URLs in code. Same — the characters you type are valid.
- URLs from your own backend that you trust to be clean. No need to re-encode.
The encoder earns its keep when:
- A value comes from user input.
- A value contains anything non-ASCII.
- A value comes from another system that may have done partial encoding.
For those cases — paste, encode, ship.