toolhq.io

All posts
July 14, 20265 min read

Parse a URL into its parts: scheme, host, path, query, and fragment

A URL looks like one opaque string, but it is a small structured document with named parts: a scheme, a host, an optional port, a path, a query string, and a fragment. Once you can name each part, most URL bugs become easy to spot. Paste any URL into the URL Encoder & Parser and it breaks the string into protocol, host, path, and individual query parameters, entirely in your browser.

One URL, taken apart

Take this example:

https://shop.example.com:8443/products/running-shoes?color=blue&size=42&q=trail%20running&sort=#reviews
PartValueWhat it does
SchemehttpsThe protocol the browser speaks, before the ://
SubdomainshopThe leftmost label of the host
Hostshop.example.comWhich server to contact
Port8443Which port on that server; omitted when it is the default
Path/products/running-shoesWhich resource on the server
Querycolor=blue&size=42&q=trail%20running&sort=Extra parameters, after the ?
FragmentreviewsA position inside the page, after the #

Everything from the scheme through the port identifies where the request goes. The path and query describe what is being asked for. The fragment is a note the browser keeps to itself.

The query string in detail

The query is the part people actually need to read most often. Its grammar is simple: key=value pairs joined by &. From the example above, a parser produces four parameters:

  • colorblue
  • size42
  • qtrail running
  • sort → empty

A few details matter in practice:

  • Repeated keys. A key can appear more than once, as in ?tag=sale&tag=new. There is no single standard meaning: some servers take the last value, some take the first, and many frameworks collect the repeats into an array. Check what your server does rather than assuming.
  • Percent-encoded values. The q=trail%20running value carries an encoded space; the real value is trail running. Any character with structural meaning in a URL arrives encoded, and a parser must decode it before you compare or store it. URL encoding explained covers those rules.
  • Empty values. sort= is a parameter with an empty value, and a bare sort with no = is usually treated the same way. Both are different from the parameter being absent, and code that checks "is this key present" versus "does this key have a value" will treat them differently.
  • Order. Parameter order carries no meaning to a compliant server, but it does change the literal string. Two URLs with the same parameters in a different order can be cached, logged, or deduplicated as different pages.

Gotchas worth knowing

  • The fragment never reaches the server. Everything after # stays in the browser. If your analytics or server logs are missing something after a #, that is by design; move the data into the query if the server needs it.
  • Default ports are omitted. https://example.com/ and https://example.com:443/ point to the same place. Most parsers, including the URL object in JavaScript, hide the port when it matches the scheme's default.
  • Host is case insensitive, path is not. SHOP.Example.COM and shop.example.com are the same host, but /Products and /products can be two different resources depending on the server.
  • Trailing slashes. /products and /products/ are technically distinct paths. Many servers redirect one to the other, but comparing URLs as raw strings will treat them as different.

Where this comes up

Parsing a URL properly is the first step in a handful of everyday tasks: reading UTM parameters out of a marketing link to see which campaign it credits, debugging a redirect chain by comparing the query on each hop, extracting an id or token from a callback URL, or validating a user supplied link by checking its scheme and host before you trust it. In each case, drop the URL into the URL Encoder & Parser and read the parts instead of squinting at the string.