Encode query strings for safe URLs. Decode percent-encoded text back to readable form. Auto-detects whether your input is already encoded — one button does the right thing.
encodeURIComponent encodes all special characters — including / ? & = #. Use this for encoding individual query parameter values. encodeURI preserves URL structure characters — use it for encoding a full URL string, not component values.
Common mistake: using encodeURI on query values. It won't encode & or =, which breaks query string parsing. Always use encodeURIComponent for query parameter values. The "Auto Detect" button checks whether input contains %XX patterns indicating pre-encoded text.
Percent-encoding has a reserved set, and knowing which characters are in it explains most encoding bugs. RFC 3986 marks four characters unreserved — A–Z, a–z, 0–9, and - _ . ~ — and those never need encoding. Everything else is either a delimiter that carries structural meaning (/ ? # & =) or a character that must be escaped when it appears as data.
Space is the interesting one, because it has two valid representations that mean different things. In a URL path, space is %20. In a query string submitted as application/x-www-form-urlencoded — which is what an HTML form does by default — space is +. Both decode to a space on the server, but only in their own context. Put a literal + in a query value and a form-aware parser turns it into a space; to send an actual plus sign you must write %2B.
This produces a specific, recognisable failure. Base64 values contain +. Pass one as a query parameter without encoding it, and every + arrives as a space, so the decoded bytes are wrong and the value fails to parse — while the same string works fine in a request body. encodeURIComponent('a+b') returns a%2Bb, which is why that function, not encodeURI, belongs anywhere a value is being placed into a URL.
%2520 shows up in your logsThe percent sign is itself a character that needs encoding — it becomes %25. That creates a familiar failure mode: a space becomes %20, gets encoded a second time, and becomes %2520.
Nothing in a single application usually does this deliberately. It happens when two layers both believe they own encoding: an API gateway that normalises and re-emits a URL, a redirect handler that appends an already-encoded value to a new query string, a logging pipeline that serialises a URL into another URL. The symptom is unmistakable once you know to look for it — a search for hello world returns results for the literal text %20, because the server decoded once and stopped.
Diagnosis is a matter of counting the passes. Decode the fragment in front of you: if %2520 becomes %20, there is one more encoding step than the consumer expects. The fix belongs at whichever layer is doing the second pass, not in the value itself.
Percent-encoding prevents a value from being misread as syntax. It prevents nothing else. A SQL injection payload survives percent-encoding intact — the database driver decodes it before parsing, which is precisely why parameterised queries, not encoding, are the defence. The same is true of cross-site scripting: %3Cscript%3E is decoded by whatever reads it, so the protection has to live at the point of output, in the correct escaping for that context.
One historical exception is worth knowing because it still appears in older stacks: %00, a percent-encoded null byte. Languages that treat strings as C-style byte arrays read a null as a terminator, so a filename like shell.php%00.jpg could pass an extension check and then be truncated to shell.php when opened. Modern runtimes reject null bytes in paths outright, but the pattern is a reminder that encoding interacts with the parser, not just with the transport.
Multi-byte characters expand by a factor of nine. Percent-encoding operates on UTF-8 bytes, and each byte costs three characters. One CJK character is 3 bytes and therefore 9 characters; one emoji is 4 bytes and 12 characters. A query of twenty Chinese characters becomes roughly 180 characters of URL before any other parameters. Since proxies, CDNs and servers commonly cap request lines in the low kilobytes, a long query built from non-Latin text can be truncated in transit — and the failure looks like a malformed request rather than a length problem.
See also: Base64 Encode/Decode · HTML Entity Encoder · JWT Decoder · Encoding Tools