A URL can only carry a small set of plain characters. Anything else, such as a space, an accent, an emoji or a character that has a meaning in URL syntax, is written as a percent sign and two hex digits for each byte: a space is %20, "é" is %C3%A9. This tool has three tabs. Encode turns text into that form, Decode turns it back and tells you exactly which escape is broken, and Parse a URL splits an address into scheme, user, host, port, path, query and fragment, lists the query parameters in a small editor, and rebuilds the URL as you change them.
Three kinds of encoding
The same text can be encoded three ways, and picking the wrong one is the most common mistake.
- Component (
encodeURIComponent) encodes everything except letters, digits and - _ . ! ~ * ' ( ). Use it for one value that goes inside a URL, such as a search term. a/b?c=d&e becomes a%2Fb%3Fc%3Dd%26e. - Whole URL (
encodeURI) also leaves ; , / ? : @ & = + $ # alone, so a complete address keeps its shape: the same text stays a/b?c=d&e. It is wrong for a single value, because an & or = inside it would be read as syntax. It does encode [ and ], so it breaks an IPv6 address. - Form is what HTML forms and
URLSearchParams write: a space becomes +, and ~ ! ' ( ) are encoded as well. "café au lait & crème" is caf%C3%A9+au+lait+%26+cr%C3%A8me in form style and caf%C3%A9%20au%20lait%20%26%20cr%C3%A8me in component style.
All three work on UTF-8 bytes, so an emoji, which is a surrogate pair in JavaScript, becomes four bytes: 😀 is %F0%9F%98%80. A lone half of a surrogate pair has no UTF-8 form, so JavaScript's own function throws "URI malformed". This tool reports the position instead.
Decoding and what can go wrong
Decoding reverses each escape. A plus sign is only a space in form style, and %2B is always a plus. Decoding fails in two ways. A % that is not followed by two hex digits, as in 100% or %zz, is a broken escape. And escapes that do not form valid UTF-8, such as %C3%28 (a two-byte start followed by a plain parenthesis), are not text. The tool names each problem with its position and keeps the undecodable part as written, so you can see where it is instead of getting an error and nothing else. Switch on "Stop at the first error" if you prefer no output when something is wrong. If the decoded text still contains escapes, such as %2520 becoming %20, it was probably encoded twice, and a button decodes it again.
Taking a URL apart
The parser first splits the address exactly as written, following RFC 3986, so nothing is hidden. Then it compares each part with what the browser's URL parser makes of it and shows the difference underneath. For https://user:[email protected]:443/a/./b?q=a+b#top the browser drops the default port 443, resolves the ./ in the path and, for an address such as münchen.de, writes the host as xn--mnchen-3ya.de. Addresses without a scheme are read as relative references, and localhost:3000/x is flagged because it reads as a scheme called localhost. An empty query (?) is not the same as no query, and the table keeps that difference.
Editing the query string
Each parameter is a row with a name and a value. Order and duplicate names are kept (?q=1&q=2), a name without = stays that way until you type a value, and an empty value stays empty. Parameters you do not touch come back exactly as written; edited ones are encoded with %20 for spaces, or with + if the query already used it. Reorder, remove or add rows and copy the rebuilt URL. The Base64 tool and the JSON formatter help when a parameter holds encoded data, and the regex tester is useful for picking URLs out of text.
URLs often carry tokens and personal data. Everything here runs in your browser and nothing is uploaded, and no link is ever opened for you.