What a URL is actually made of
A URL looks like one string, but it is a small structured record: a scheme, optional credentials, a host, an optional port, a path, a query string, and a fragment. Each piece has its own rules about which characters it may hold and who is allowed to read it.
https://user@Example.com:443/a%20b?q=café#top → host example.com, port dropped, path /a%20b left exactly as written
Most URL bugs are one piece landing in the wrong slot, which is why this tool hands your text to the same WHATWG parser your browser already runs — the one behind new URL(), fetch() and the address bar. What you see here is what a browser will do with the link, not what a regular expression guesses about it. The parse, the query editing and the export all happen in this tab; close it and nothing is left behind.
Every part, one at a time
The Detail tab lists every part on its own line, empty ones included — a part with nothing in it is information too.
| Part | What it holds | Watch for |
|---|---|---|
| Protocol | The scheme and the colon after it — https:, mailto:, ftp:. | It is lowercased for you. Text with no scheme is not a URL at all, so the tool offers to add https:// rather than assuming it. |
| Username | The user half of credentials written into the URL itself. | Proxies and server logs record these. Treat a link that carries one as a password you have just pasted somewhere. |
| Password | The password half of the same credentials. | It travels in the clear inside the URL and lands in logs and browser history. If one appears here, rotate it. |
| Host | The domain or IP address, without the port. | It is lowercased, and an international domain becomes its punycode form — münchen.de reads back as xn--mnchen-3ya.de. An IPv6 address keeps its square brackets. |
| Port | The port number, when the URL names one. | Empty means the scheme's default: 443 for https, 80 for http. Writing the default out is allowed, but the parser drops it again. |
| Path | Everything from the first slash up to the query string. | Unlike the host it is case-sensitive, and it stays percent-encoded here: /a%20b is one segment with a space in it. |
| Query | The raw query string, question mark included. | This is the text exactly as written. The Params tab shows the same thing decoded and split into pairs. |
| Fragment | The #hash at the end. | It never leaves the browser, so a server never sees it. Wrong place for anything the server must act on; right place for an anchor. |
| Origin | Scheme, host and port together. | This is the unit that same-origin policy, CORS and cookies reason about. A scheme with no origin — mailto:, urn: — shows nothing here. |
Editing the query string
The Params tab splits the query into pairs and decodes each one, so a value reads as café bar rather than caf%C3%A9%20bar. Edit a key or a value and the URL above rebuilds itself; the blank row at the bottom becomes a parameter as soon as you type in it, and the cross beside a row removes it.
Repeated keys are kept, in order. ?tag=a&tag=b is two parameters, not one that overwrote the other — which is how most servers read it — so the table shows two rows.
Rebuilding encodes the way an HTML form does: a space becomes +, and a literal plus becomes %2B. That round-trips cleanly and is what a query parser on the far end expects. A pair with a key but no value (k=) is kept, because an empty value and an absent parameter are different things.
Only the query is rewritten. Credentials, port, path and fragment come back exactly as they were.
What the parser changes without asking
The parser is not a passive reader; it canonicalises. The scheme and host are lowercased, an international domain is punycoded, a default port is dropped, and an empty path becomes /. Whenever that changes the text you pasted, the line under the box says so and shows the result.
It matters when URLs are compared as strings — a cache key, a signature, an allow-list. HTTPS://Example.com and https://example.com are one URL to a browser and two different strings to a naive comparison.
What it does not touch: the path's case, the path's percent-encoding, and the order of the query parameters. All three are significant, and a tool that tidied them would be changing what your link means.
When you would reach for it
Reading a link somebody sent you before you click it: which host it really points at, whether it carries credentials, and what is sitting in the query.
Working on tracking parameters — drop the utm_ rows, rename a campaign, add one, and copy the rebuilt link straight out.
Debugging a redirect or an OAuth callback, where the interesting part is usually a whole URL percent-encoded inside another one's query. Copy the decoded value out of the Params tab and paste it back in the box to go one level deeper.
Frequently asked questions
/. The status line names the result whenever it differs from what you typed./a%2Fb is one segment containing a slash, and /a/b is two segments. Query values have somewhere safe to be shown decoded — the Params tab, one pair per row.+ in a query value means a space, per application/x-www-form-urlencoded, so the table shows a space. Rebuilding the URL turns it back into a +. A plus you meant literally is %2B, and that is what the tool writes.# is for the page itself — an anchor, a client-side route, a token some flows deliberately put there. If a server has to see it, it belongs in the query.https:// (or mailto:, or ftp:) at the front. Without one, example.com/page is ambiguous — it could just as well be a path on the current site. The tool shows what it would become with https:// in front and lets you accept that in one click, rather than rewriting what you typed.