Anatomy of a URL: what every part of a link does.

You type hundreds of URLs a week and most of them are seven machines wearing one trench coat: a protocol choice, an optional identity, an address, a door number, a file path, a note to the application, and a note the server never even sees. Here's the whole grammar, part by part — and the trap hiding in each one.

The structure comes from RFC 3986, the URI standard, and it's strict enough that every browser and server on Earth splits a URL the same way. One worked example carries the whole article:

The map.

https://user:pw@shop.example.co.uk:8443/products/shoes?color=red&size=42#reviews
└─┬─┘   └──┬──┘ └───────┬────────┘ └┬─┘ └──────┬──────┘ └───────┬───────┘ └──┬──┘
scheme  userinfo      host         port      path            query       fragment

Scheme, then ://, then an optional user:pw@, then the host, an optional :port, the path, an optional ?query, an optional #fragment. Every part except scheme and host can be absent — https://example.com is a complete URL. Now, part by part.

Scheme: which rules apply.

The scheme (https, http, mailto, ftp, file, data) declares which protocol — which rulebook — the rest of the URL should be read with. It's why mailto:someone@example.com has no slashes and no host section: the generic syntax only applies as far as each scheme adopts it. The everyday trap is scheme-dropping: paste example.com/page into contexts expecting a full URL and parsers can read example.com/page as a path, not a host. And the difference between http and https isn't cosmetic — it decides whether the query string and path cross the network readably or encrypted.

Userinfo: the part that's now mostly a scam.

The user:password@ slot predates the modern web — it was built for FTP-era credentials, and browsers have spent two decades removing support because its main surviving use is deception: https://paypal.com@evil.example/login is a URL whose host is evil.example — everything before the @ is just a username the attacker chose to look like a domain. Modern browsers strip or warn on userinfo in web URLs, and credentials belong in headers, not URLs. The lesson generalizes: the real host is what sits between the last @ (if any) and the next /, ?, or # — reading that correctly is the single most security-relevant URL skill.

Host and port: the address.

The host names the machine — a domain (shop.example.co.uk) or an IP address. Domains read right to left: the top-level domain, the registrable domain, then subdomains — which is why secure-bank.evil.example belongs to evil.example, no matter how reassuring its left end looks. Hosts are case-insensitive (EXAMPLE.COM = example.com) — the only part of a URL that is. Non-ASCII domains exist too (bücher.example), but DNS speaks ASCII, so they travel in Punycode (xn--bcher-kva.example) — and lookalike Unicode characters in hostnames are their own phishing genre.

The port is the door number on that machine. You rarely see it because each scheme has a default — 443 for https, 80 for http — and browsers hide the default. An explicit :8443 or :3000 just means "not the usual door," which is why local dev servers wear ports so prominently.

Path: the request.

The path (/products/shoes) tells the server which resource. It looks like a filesystem path and historically was one; on modern sites it's a routing key the application interprets however it likes. Unlike the host, the path is case-sensitive per the standard/About and /about may be different pages, and whether they are depends on the server. Trailing slashes are similarly server-defined: /docs and /docs/ can differ, which is why canonical URLs pick one form and redirect the other.

Query: parameters for the application.

Everything after ? is the query string: key=value pairs joined by &, the URL's general-purpose parameter channel — search terms, filters, page numbers, and the utm_* tracking crumbs marketing tools append. Order doesn't matter to the syntax, duplicate keys are legal (how multi-select filters travel), and every value must be percent-encoded so the data can't be mistaken for the grammar — that whole story has its own article. Two practical notes: query strings are visible everywhere (logs, history, referrers — never put secrets in them), and cleaning tracking parameters off a shared link is both polite and safe, since the page itself is addressed by host + path.

Fragment: the part the server never sees.

Everything after # is the fragment, and it has the strangest property in the URL: the browser doesn't send it to the server at all. It's a client-side note — classically "scroll to the element with this id" (#reviews, or the #the-map headings on this very page), and in single-page apps a whole routing state. Because it never crosses the wire, changing only the fragment doesn't reload the page, fragments never appear in server logs, and — a corollary that surprises people — the server cannot redirect you based on a fragment it never received. If it's after the #, it's between you and your browser.

Takeaways.

The thing to remember: scheme picks the rulebook, host is what sits between the last @ and the next / (read domains right to left), the port hides when it's the default, the path is the app's case-sensitive routing key, the query is the visible parameter channel (no secrets), and the fragment never reaches the server at all.

A URL is a small contract with seven clauses, and every phishing trick, broken deep-link, and mystery redirect is someone exploiting a clause you skimmed. Read one carefully, once, and you'll never quite skim them again.

Dissect any URL in your browser.

The URL Parser splits a link into scheme, userinfo, host, port, path, and every decoded query parameter — the diagram from this article, live. Entirely client-side, which matters when the URL you're inspecting contains a token.

Open the URL Parser
Tooly mascot

Made with love by a very serious person pretending not to be. Tooly McToolface is a workshop of free, client-side web tools. The escaping rules this article keeps gesturing at are fully unpacked in URL encoding: why spaces become %20, and HTTP status codes that matter covers what the server says once your URL reaches it.