Free tool
URL parser
Paste a URL to split it into protocol, host, port, path, query parameters and fragment. Every part is editable: change a value, delete tracking tags or add a parameter, and the rebuilt URL updates as you type.
Free · no sign-up · runs in your browser, nothing is uploaded
Anatomy of a URL
https://user:pass@shop.example.co.uk:8443/products/shoes.html?color=blue&size=42#reviews └─┬─┘ └───┬───┘ └───────┬────────┘ └┬─┘└────────┬─────────┘ └───────┬────────┘ └──┬──┘ scheme userinfo host port path query fragment
| Part | In the example | JavaScript URL property | Notes |
|---|---|---|---|
| Scheme | https | protocol ("https:") | Lowercased by parsers |
| User info | user:pass | username, password | Avoid: it ends up in logs and history |
| Host name | shop.example.co.uk | hostname | International names become punycode (xn--) |
| Port | 8443 | port | Empty when it is the default (443 for https, 80 for http) |
| Path | /products/shoes.html | pathname | Segments split by / |
| Query | color=blue&size=42 | search, searchParams | Starts with ?, pairs split by & |
| Fragment | reviews | hash ("#reviews") | Never sent to the server |
The host name splits further. In shop.example.co.uk, co.uk is the public suffix, example.co.uk is the domain someone registered and shop is a subdomain. Which suffixes have two parts is not a rule you can compute; it comes from the Public Suffix List that browsers ship. The parser knows the common ones.
What the parser tells you
Besides the parts, the tool points out things that often cause bugs:
| Note | Why it matters |
|---|---|
| Repeated keys | Servers read them differently: first value, last value or a list |
| Values still containing %XX | The value was probably encoded twice; the [decode] button on the row decodes it fully |
| User name or password in the URL | Leaks into logs, history and Referer headers |
| Default port written out | :443 on https is dropped by parsers, so two URLs that look different are the same |
| International domain | Shows the punycode form a browser actually sends to DNS |
| Spaces in the URL | Browsers escape inner spaces as %20 and strip tabs and line breaks |
| UTM tags and click IDs | Labelled so you can remove them before sharing or caching a link |
| Invalid scheme | A scheme like ht!tp:// is rejected instead of being read as a host name |
Values in the table are shown decoded. To decode or encode a single value by hand, use the URL decoder and encoder.
Parse a URL in code
JavaScript (browser and Node.js)
const u = new URL('https://shop.example.com:8443/p/shoes?size=42&size=43#reviews');
u.hostname; // 'shop.example.com'
u.port; // '8443'
u.searchParams.get('size'); // '42'
u.searchParams.getAll('size'); // ['42', '43']
// Edit and rebuild
u.searchParams.delete('size');
u.searchParams.set('utm_source', 'newsletter');
u.toString(); // 'https://shop.example.com:8443/p/shoes?utm_source=newsletter#reviews'
URL.canParse('not a url'); // false, without try/catchPython
from urllib.parse import urlsplit, parse_qs, urlencode, urlunsplit
u = urlsplit('https://shop.example.com:8443/p/shoes?size=42&size=43#reviews')
u.hostname, u.port, u.path # ('shop.example.com', 8443, '/p/shoes')
parse_qs(u.query) # {'size': ['42', '43']}
q = urlencode({'utm_source': 'newsletter'})
urlunsplit(u._replace(query=q))PHP
$u = parse_url('https://shop.example.com:8443/p/shoes?size=42#reviews');
$u['host']; // 'shop.example.com'
$u['port']; // 8443
parse_str($u['query'], $params); // $params['size'] === '42'Go
u, err := url.Parse("https://shop.example.com:8443/p/shoes?size=42&size=43#reviews")
u.Hostname() // "shop.example.com"
u.Port() // "8443"
u.Query()["size"] // []string{"42", "43"}
q := u.Query(); q.Set("page", "2"); u.RawQuery = q.Encode()URL parsing gotchas
Relative URLs need a base. new URL('/p/shoes') throws; pass a base as the second argument: new URL('/p/shoes', 'https://example.com'). This tool adds https:// when the scheme is missing.
Do not parse URLs with a regex or split(). A ? inside the fragment, an @ in user info, an IPv6 host in brackets or a # before the query all break simple patterns. Parsers that disagree with the browser are a known source of SSRF and open-redirect bugs, so check redirect targets with new URL() and compare the origin.
Encoding changes on rebuild. URLSearchParams writes spaces as + and re-escapes every value, so q=red%20shoes&x=a!b comes back as q=red+shoes&x=a%21b after any edit. This tool keeps parameters you did not edit exactly as they were, and only re-encodes the ones you changed.
Building links for a site? The meta tag generator previews how a URL looks when shared, and the curl converter turns a request into code. For API clients and testing tools, see API tools on DevHunt.
More free developer tools
FAQ
What are the parts of a URL?+
Scheme (https), optional user info (user:password@), host (example.com), optional port (:8443), path (/products/shoes), query (?color=blue&size=42) and fragment (#reviews). Only the scheme is always required; the parser above shows each part separately and lets you edit it.
How do I get query parameters from a URL in JavaScript?+
Use new URL(href).searchParams. searchParams.get("q") returns the first value of q, already decoded, or null if it is missing. getAll("q") returns every value of a repeated key, and has("q") checks if it is there. For the current page, use new URLSearchParams(location.search).
What is the difference between the host and the hostname?+
The hostname is the name alone (shop.example.com). The host is the hostname plus the port when one is given (shop.example.com:8443). The origin adds the scheme in front (https://shop.example.com:8443); browsers use it for same-origin checks and CORS.
Is the fragment (#) sent to the server?+
No. The browser keeps the part after # to itself: it scrolls to that element or hands it to JavaScript. A server log never contains it. That is why single-page apps used #/routes in the past, and why OAuth implicit flows put tokens there.
What are UTM parameters?+
Query parameters that tell analytics tools where a visit came from: utm_source (google, newsletter), utm_medium (cpc, email), utm_campaign, utm_term, utm_content and utm_id, plus a few newer ones in Google Analytics. They do not change the page. The parser labels them, along with click IDs like gclid and fbclid, and can remove them all in one click.
What happens when a query parameter is repeated?+
It depends on the server. URLSearchParams.get() returns the first value, Python parse_qs() returns a list, PHP keeps only the last one unless the key ends in [], and Express returns an array. The parser marks repeated keys, and the JSON view turns them into arrays.
How long can a URL be?+
There is no fixed limit in the URL standard. RFC 9110 recommends that clients and servers support at least 8,000 octets; individual browsers, servers, CDNs and proxies set their own limits. Very long query strings are better sent as a POST body.
Sources: RFC 3986 (URI syntax) · RFC 9110 (URI length) · WHATWG URL Standard · MDN: URL · MDN: URLSearchParams · Google Analytics: URL builders and UTM parameters · Python urllib.parse · PHP parse_url() · Go net/url · Public Suffix List. Checked 2026-10-30.