Encode a value for a query string, encode a whole URL, or decode percent-encoded text back to something readable.
A URL is not free text. Certain characters carry structural meaning — ? starts the query string, & separates parameters, = joins a name to its value, # begins the fragment, / divides path segments. If any of those appear inside a value, the parser on the other end has no way to tell them apart from the real thing.
Percent encoding solves it by replacing the character with a % followed by its two-digit hexadecimal byte value. A space becomes %20, an ampersand becomes %26, a question mark %3F. The parser sees inert text and the value survives intact.
Encode a component. Use this on a single value that is going inside a URL — a search term, a name, a redirect target. It escapes everything with structural meaning, including / ? : @ & = + $ #. This is what you want the overwhelming majority of the time.
Encode a whole URL. Use this when the input is already a complete address and you only want to fix illegal characters such as spaces. It deliberately leaves / ? : @ & = alone, because escaping those would break the address. Applying component-encoding to a full URL turns https://example.com into https%3A%2F%2Fexample.com, which is correct if it is a parameter value and wrong if it is meant to be a working link.
Decode. Reverses either. This tool also converts + to a space, because HTML form submissions encode spaces that way — a legacy of the older application/x-www-form-urlencoded format rather than the percent-encoding standard itself.
The value price & tax = 50% component-encodes to price%20%26%20tax%20%3D%2050%25. Every space becomes %20, the ampersand becomes %26, the equals becomes %3D, and — this one is easy to miss — the literal percent sign becomes %25. A percent sign that is not escaped is the most common cause of a decode failure, because the decoder tries to read the next two characters as hex and finds something else.
| Character | Encoded | Why it matters |
|---|---|---|
| space | %20 | Illegal in a URL; sometimes written as + |
| & | %26 | Separates query parameters |
| = | %3D | Joins a parameter name to its value |
| ? | %3F | Starts the query string |
| # | %23 | Starts the fragment — everything after is never sent to the server |
| / | %2F | Separates path segments |
| % | %25 | The escape character itself |
| + | %2B | Otherwise read as a space by form decoders |
The # row has a consequence people hit repeatedly: a fragment is handled entirely by the browser and never transmitted to the server. An unescaped # inside a parameter value silently truncates everything after it from the server’s point of view, and the request looks fine in the address bar while arriving incomplete.
Modern percent-encoding works on UTF-8 bytes, so a character outside ASCII becomes several escapes. The é in café is two bytes in UTF-8 and encodes to %C3%A9. A CJK character is usually three bytes and produces three escapes. This is why an encoded string containing non-English text looks disproportionately long, and why a mismatched character set produces mojibake rather than an error.
Domain names work differently. Internationalised domains use Punycode rather than percent-encoding — münchen.de becomes xn--mnchen-3ya.de — because the DNS system predates and does not accept percent escapes.
Encoding something that is already encoded turns each % into %25, so %20 becomes %2520. Seeing %25 where you expected a plain escape is the signature of a value that passed through two encoding layers, typically because a framework encoded it automatically and application code encoded it again. The fix is to decode twice, then find and remove the duplicate encoding step rather than compensating for it downstream.
Component encoding escapes every character with structural meaning, including slashes, colons, ampersands and question marks. Use it for a single value that will sit inside a URL. Whole-URL encoding leaves those characters intact so the address still functions, and only fixes genuinely illegal characters such as spaces. Applying component encoding to a full URL produces something that is correct as a parameter value but useless as a link.
Two different specifications. Percent-encoding proper, as used in URL paths, represents a space as %20. HTML form submissions using application/x-www-form-urlencoded represent it as +, a convention that predates the modern standard and survives for compatibility. Query strings built by forms use +; almost everything else uses %20. Decoders generally accept both, and this tool converts + back to a space.
It is a literal percent sign. Because % is the escape character itself, it has to be escaped too. Seeing %25 followed by what looks like another escape — for example %2520 — means the value was encoded twice, usually because a framework escaped it automatically and application code escaped it again. Decode twice to read it, then find the duplicated step rather than patching around it.
No. Percent-encoding is a formatting convention, not a security control. It exists so a parser reads a URL the way you intended, nothing more. It does not hide data, and anything in a URL is visible in browser history, server logs, proxy logs and referrer headers — which is exactly why sensitive values should travel in a request body over HTTPS rather than in a query string, encoded or not.
Percent-encoding operates on bytes, and modern URLs use UTF-8, where any character outside basic ASCII takes two to four bytes. Each byte becomes its own three-character escape, so é becomes %C3%A9 and a single CJK character typically becomes nine characters. The expansion is unavoidable. Internationalised domain names sidestep it entirely by using Punycode instead, since DNS does not accept percent escapes.
Related: Base64 Converter · IP Subnet Calculator · Password Generator · Word Counter