Percent-encode text for a URL or decode it back, with every broken escape pointed out by position. Paste a full link to see its parts, from the real host to each query parameter, decoded.
Runs entirely in your browser. Nothing you type or upload is sent to a server.
Why URLs need encoding
A URL can only contain a small set of ASCII characters, and some of those have jobs. The ? starts the query, & separates parameters, = splits a name from its value and # starts the fragment. A value that contains one of them has to be disguised, or it changes the structure of the URL. Search for fish & chips and put it into a query string unencoded, and the server receives a search for fish plus a meaningless parameter called chips.
Percent-encoding is the disguise. Each byte that cannot appear as itself is written as % followed by its value in hexadecimal. Text that is not plain ASCII is first converted to UTF-8, so é, which is two bytes, becomes %C3%A9, and an emoji, which is four, becomes something like %F0%9F%98%80. The escapes you will see most often:
| Escape | Character | Escape | Character |
|---|---|---|---|
%20 | space | %26 | & |
%2F | / | %3D | = |
%3F | ? | %23 | # |
%3A | : | %2B | + |
%40 | @ | %25 | % itself |
Which kind of encoding to use
The four modes above differ only in which characters they leave alone, and picking the wrong one is the most common URL bug there is.
- Encode a value matches JavaScript's
encodeURIComponent. It leaves letters, digits and- _ . ! ~ * ' ( )alone and encodes everything else. Use it for anything you are placing inside a URL: one query value, one path segment, or a whole URL being passed as a parameter to another URL. - Strict RFC 3986 also encodes
! ' ( ) *. OAuth 1.0 signatures and AWS request signing require exactly this, and a single unencoded parenthesis makes the signature fail. - Encode a whole URL matches
encodeURI. It keeps the characters that give a URL its shape, so it repairs spaces and accents in a link without breaking it. It never protects a value, because it leaves&and=as they are. This version also leaves existing escapes alone and turns an international domain name into punycode, two things the built-in gets wrong. - Form-encode is
application/x-www-form-urlencoded, the format HTML forms submit andURLSearchParamsproduces. Spaces become+and only letters, digits and* - . _survive.
The plus sign problem
In form data a + means a space, but in a path, and in any query that was not built by a form, it is just a plus sign. Decoders therefore disagree, and values that really contain a plus get damaged. A phone number such as +44 20 7946 0000 or an address like me+news@example.com arrives with a space where the plus was, because it was sent unencoded and decoded as form data. The fix is to encode the value properly, which writes the plus as %2B. When decoding here, untick "Treat + as a space" for paths and other non-form text.
Double encoding
When a value is encoded and then encoded again, each % becomes %25, so a space ends up as %2520 and visitors see a literal %20 on the page. It nearly always means two layers of code each decided to encode the same value, which is common with redirect and tracking links that pass through several services. Encode a value once, at the moment it is placed in the URL, and decode it once when it is read. The decoder counts the layers and can peel off the next one.
Reading a URL's parts
A full URL reads scheme://user:password@host:port/path?query#fragment, and the breakdown panel separates each part. A few of them are worth knowing about:
- Anything before an @ is not the website. In
https://www.paypal.com@login-check.example/the real host is login-check.example. The first part is a user name, and the trick works because people read from the left. - International domain names travel as punycode, starting
xn--. A name that mixes alphabets, such as a Cyrillic а among Latin letters, can be made to look exactly like a well-known domain. The breakdown flags it. - The fragment never reaches the server. Everything after
#stays in the browser, which is why single-page apps and some login flows put data there. - Repeated parameters are handled differently by every server. For
?tag=a&tag=b, PHP keeps only the last value, Python'sparse_qsand Node'sqslibrary return a list, andURLSearchParams.getreturns the first.
To check a link from a printed code before opening it, use the QR code scanner. For other encodings, the Base64 converter handles data URIs and URL-safe Base64, and the JSON formatter tidies the API responses that query strings usually ask for.

