Skip to content
JavaScript Basics: Match URL Components with URLPattern

JavaScript Basics: Match URL Components with URLPattern

October 27, 2026

A route check should distinguish a URL path from its host and protocol. URLPattern matches components and exposes named groups. Build a fixed HTTPS origin pattern, then test matching, rejection, and an encoded path segment.

Prepare a scratch directory

Tested on Linux with Node.js v24.19.0. You need the named runtime, Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. The .mjs extension selects ES modules. Assertions check the demonstrated behavior; no npm packages or remote services are needed.

Keep using the same terminal. Stop if setup fails, before saving the source:

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

Run the example

Save this as demonstrate-url-pattern.mjs:

import assert from 'node:assert/strict';
import { URLPattern } from 'node:url';

const route = new URLPattern({
  protocol: 'https',
  hostname: 'example.com',
  port: '',
  pathname: '/reports/:id',
});
const matched = route.exec('https://example.com/reports/42?view=compact');
assert.ok(matched);
assert.equal(matched.pathname.groups.id, '42');
console.log('Report ID:', matched.pathname.groups.id);
assert.equal(route.test('https://other.example/reports/42'), false);
assert.equal(route.test('http://example.com/reports/42'), false);
assert.equal(route.test('https://example.com/reports/42/extra'), false);
console.log('Wrong host, protocol, or extra path: rejected');

const encoded = route.exec('https://example.com/reports/team%20one');
assert.ok(encoded);
assert.equal(encoded.pathname.groups.id, 'team%20one');
console.log('Raw group:', encoded.pathname.groups.id);
console.log('Decoded group:', decodeURIComponent(encoded.pathname.groups.id));
assert.equal(route.exec('https://example.com/other'), null);
console.log('Unmatched exec result:', null);

Run it:

node demonstrate-url-pattern.mjs

Observed output:

Report ID: 42
Wrong host, protocol, or extra path: rejected
Raw group: team%20one
Decoded group: team one
Unmatched exec result: null

Read the result

The object form makes component boundaries explicit. :id captures a single path segment, and exec returns groups only after a match. The query is unconstrained because no search component is specified. The encoded segment stays percent-encoded in the captured group; decoding is a separate operation. test provides a Boolean when groups are not needed.

Apply it carefully

This example requires Node 24 and was tested on the version below. URLPattern is still marked experimental in Node 24 documentation. Matching is routing logic, not authorization, DNS validation, or a complete defense for server-side fetching. Treat captured strings as input and validate them before filesystem or database use. Decoding arbitrary input can throw or expose separators, so a successful match is not permission to use a value as a path.

The official reference describes the API and its options. The checks above cover the specific fixture, not every possible input or environment.

Clean up

Remove the source and then the empty practice directory:

rm -- demonstrate-url-pattern.mjs
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

If the directory is not empty, inspect the remaining files rather than deleting unknown contents.

Acknowledgements

This post was created with assistance from AI.

Last updated on