How to encode or decode a URL
- Choose Encode or Decode.
- When encoding, pick what the text is for. Use a query value or path segment for anything you will put between = and & or between two slashes — this is the right choice nine times out of ten. Use a whole URL only when you have a complete address that contains spaces or non-English characters and must keep its slashes and question mark. Use form data to match what an HTML form sends.
- Type or paste the text. The result updates as you type; press Copy to take it.
- When decoding, paste the encoded text or the whole link. Tick Treat + as a space if it came from a form submission or a search URL. If the text contains a stray % that is not an escape, tick Keep invalid % as it is instead of fixing it by hand.
- Whenever the input is a full URL, the Parts of this URL panel lists the scheme, host, port, path, fragment and every query parameter, decoded, one per row.
How percent-encoding works
A URL may only contain a limited set of ASCII characters, and some of those have jobs: / separates path segments, ? starts the query, & and = separate parameters, # starts the fragment. RFC 3986 defines how to include anything else: convert the text to UTF-8 bytes and write each byte as % followed by two hexadecimal digits. A space becomes %20; é, two bytes in UTF-8, becomes %C3%A9; a Chinese character, three bytes, becomes three escapes.
Why there are three modes
The difference is which characters are left alone. encodeURIComponent encodes everything except letters, digits and - _ . ! ~ * ' ( ), so a value containing & or / cannot break the URL it is placed in. encodeURI additionally leaves the structural characters ; , / ? : @ & = + $ # untouched, because it assumes you are encoding a complete URL. Using encodeURI on a single value is a classic bug: a value of "a&b" stays "a&b" and is read back as two parameters.
Form encoding (application/x-www-form-urlencoded, defined in the WHATWG URL Standard) is what browsers send for HTML forms and what URLSearchParams produces. It writes spaces as + and also encodes ! ' ( ) ~. That is why a search URL often shows q=hello+world, and why a literal plus sign in form data has to be sent as %2B.
Decoding precisely
JavaScript's decodeURIComponent throws a bare "URI malformed" error on bad input without saying where. This tool decodes the escapes itself: it collects consecutive %XX bytes and checks them as UTF-8, so it can report either an escape that is not followed by two hex digits or a multi-byte character that was cut off — usually the result of truncating a URL in the middle of a character.
International domain names
Host names are not percent-encoded. Non-ASCII domains are converted to Punycode, defined in RFC 3492, with an xn-- prefix. The parts panel shows both forms so you can see that 例子.com and xn--fsqu00a.com are the same host.
Examples
| Input | Mode | Result |
|---|---|---|
a b&c=d/é | query value | a%20b%26c%3Dd%2F%C3%A9 |
https://example.com/a b?q=1&r=é#x | whole URL | https://example.com/a%20b?q=1&r=%C3%A9#x |
a b+c | form data | a+b%2Bc |
it's (fine)!*~ | query value | it's%20(fine)!*~ |
it's (fine)!*~ | form data | it%27s+%28fine%29%21*%7E |
你好 | query value | %E4%BD%A0%E5%A5%BD |
😀 | query value | %F0%9F%98%80 |
Decoding 100%zz fails at character 4, the % that is not followed by hex digits; with Keep invalid % as it is turned on, a lone trailing % as in 100% is kept as text. Decoding %E4%BD fails because it is the first two bytes of a three-byte character. Decoding %25E4%25BD%25A0 once gives %E4%BD%A0, and decoding that again gives 你 — the telltale sign of a value that was encoded twice.
Pasting https://user@例子.com:8443/路径/a%20b?q=%E4%BD%A0&q=2&empty=&flag#frag lists the host as 例子.com (xn--fsqu00a.com), port 8443, path /路径/a b and four parameters: q = 你, q = 2, empty = (empty) and flag = (empty). Repeated keys and empty values are kept, because servers treat them differently.
Common mistakes
- Encoding twice. A value that is encoded and then placed in a URL that is encoded again shows up as %2520 instead of %20. Encode each value once, when you insert it.
- Encoding a whole URL as a component. encodeURIComponent turns https:// into https%3A%2F%2F. That is correct when the URL is itself a parameter value (a redirect target, for example), and wrong otherwise.
- Treating + as a space everywhere. Only form data uses + for spaces. In a path, + is a literal plus sign.
Limits
- UTF-8 only. Old sites sometimes encoded text in GBK or Windows-1252. Those bytes are not valid UTF-8 and are reported as errors; with the lenient option they are kept as escapes.
- One layer at a time. Decoding removes one level of encoding. Use Use result as input to decode again when a value was encoded twice.
- The parts panel follows the WHATWG URL parser, the same one browsers use. A text without a scheme is treated as https:// for display, and a text with spaces is not considered a URL.
Frequently asked questions
What is the difference between encodeURI and encodeURIComponent?
encodeURIComponent encodes the characters that have a meaning in URLs, such as / ? & =, so it is right for a single value. encodeURI leaves them alone and is only for a complete URL.
Should a space be %20 or +?
In a path and in most APIs, %20. In HTML form data and many search URLs, +. Both decode to a space when the receiver expects form encoding.
Why does my URL contain %2520?
It was encoded twice: % itself became %25. Decode it twice, and fix the code so it encodes only once.
Why do Chinese characters become so long?
Each Chinese character is three bytes in UTF-8, and each byte becomes three characters (%XX), so one character turns into nine.
Is my text sent anywhere?
No. Encoding, decoding and URL parsing all happen in your browser.