Node.js URL Module

The URL API parses and constructs URLs, giving structured access to hostnames, paths, and query strings through the global URL class and its searchParams object.

Parsing URLs with the WHATWG URL API

Modern Node.js uses the same URL class defined by the WHATWG URL Standard that browsers implement, so you rarely need to require anything—new URL() is available globally. Passing a string to its constructor parses it immediately, throwing a TypeError if the string isn't a valid absolute URL. The resulting object exposes every piece of the URL as a separate, already-decoded property, which is far more reliable than trying to slice the string apart yourself.

Reading URL Properties

Once you've parsed a URL, each meaningful segment is available as its own property, so you never have to write regular expressions to pull out a hostname or a path.

  • protocol — the scheme, including the trailing colon, e.g. 'https:'
  • hostname — the domain name, without the port
  • port — the port number as a string, empty if none was specified
  • pathname — everything after the domain and before the query string
  • search — the raw query string, including the leading '?'
  • hash — the fragment identifier, including the leading '#'
  • searchParams — a URLSearchParams object for reading and editing query parameters

Parsing a URL and reading its properties

const myUrl = new URL('https://shop.example.com:8443/products/42?ref=email#reviews');

console.log(myUrl.protocol);  // https:
console.log(myUrl.hostname);  // shop.example.com
console.log(myUrl.port);      // 8443
console.log(myUrl.pathname);  // /products/42
console.log(myUrl.search);    // ?ref=email
console.log(myUrl.hash);      // #reviews

Working with searchParams

The searchParams property is a URLSearchParams instance, which offers a small, purpose-built API for query strings: get() reads the first value for a key, getAll() reads every value for a key that appears more than once, set() overwrites a key, append() adds a value without removing existing ones, delete() removes a key entirely, and has() checks for its presence. Because URLSearchParams is iterable, you can also loop over every key/value pair with for...of.

Reading and modifying query parameters

const myUrl = new URL('https://shop.example.com/search?q=laptop&sort=price');

console.log(myUrl.searchParams.get('q'));    // laptop
console.log(myUrl.searchParams.has('sort')); // true

myUrl.searchParams.set('sort', 'rating'); // overwrite an existing value
myUrl.searchParams.append('page', '2');   // add a new parameter
myUrl.searchParams.delete('q');           // remove a parameter entirely

for (const [key, value] of myUrl.searchParams) {
  console.log(`${key} = ${value}`);
}

console.log(myUrl.toString());
// https://shop.example.com/search?sort=rating&page=2
PropertyMeaningExample Value
protocolURL scheme'https:'
hostnameDomain name only'shop.example.com'
pathnamePath portion'/products/42'
searchRaw query string'?ref=email'
searchParamsParsed, editable query parametersURLSearchParams { 'ref' => 'email' }

Extracting query parameters from an incoming request URL

function parseRequestUrl(rawUrl) {
  // A base is required for relative URLs like a real request path would be
  const url = new URL(rawUrl, 'http://localhost');

  return {
    path: url.pathname,
    page: Number(url.searchParams.get('page')) || 1,
    limit: Number(url.searchParams.get('limit')) || 20
  };
}

console.log(parseRequestUrl('/api/products?page=3&limit=50'));
// { path: '/api/products', page: 3, limit: 50 }

console.log(parseRequestUrl('/api/products'));
// { path: '/api/products', page: 1, limit: 20 } — falls back to defaults
Note: searchParams.get('key') only ever returns the first matching value, even if the query string repeats that key several times (e.g. '?tag=a&tag=b'). If you need every value, use getAll('key'), which returns an array.

Exercise: Node.js URL Module

What does `new URL(input)` do if `input` is not a valid absolute URL and no base is provided?