URL encoder / decoder
Percent-encode a URL or a value, or decode it back to text. Choose the mode that matches how the result will be used.
Input is processed in your browser and is not sent to the server.
Quick start
- Distinguish an entire URL from one value.
- Enter text and choose the conversion.
- Match the destination system’s format.
Choose a mode
| Mode | Input | Encoded output |
|---|---|---|
| Component | a&b=c | a%26b%3Dc |
| Entire URL | https://example.com/?q=a b | https://example.com/?q=a%20b |
Separators matter
Component encoding also encodes separators such as &, =, and /. Using it on a whole URL changes the structure. Entire-URL mode preserves separators but cannot distinguish an & inside a parameter value from a structural separator.
Decoding rules
Decoding uses decodeURIComponent. It does not convert form-encoded + into a space: a+b keeps its plus, while %20 becomes a space.
Encoding an already encoded value changes % into %25. Decoding is not HTML, SQL, or command sanitization. Input is processed in your browser.
Why non-ASCII text gets long
Percent-encoding converts each character to UTF-8 bytes and writes every byte as % followed by two hexadecimal digits. Characters outside ASCII take 2 to 4 bytes in UTF-8: é is 2 bytes and € is 3 bytes, so they become 6 and 9 characters.
| Input | UTF-8 bytes | Encoded |
|---|---|---|
| é | C3 A9 | %C3%A9 |
| € | E2 82 AC | %E2%82%AC |
| a b | 61 20 62 | a%20b |
Why a space becomes %20 or +
The HTML form format (application/x-www-form-urlencoded) turns a space into +, while general URL-encoding functions use %20. The same value can come out differently depending on the function, so check which format the receiving server expects.
encodeURIComponent('a b') // a%20b
new URLSearchParams({q: 'a b'}).toString() // q=a+b
urllib.parse.quote('a b') # a%20b
urllib.parse.quote_plus('a b') # a+bSpotting double encoding
If a log or address contains something like %2520, where %25 is followed by more hex digits, suspect double encoding. If decoding once with this tool still leaves sequences such as %20, the value was encoded twice. Check the proxy, the framework and your own code in turn to find the step that encodes again.