The url Module
Parsing URLs by hand with string splitting is a reliable source of bugs. node:url — and specifically the WHATWG URL class, the same one browsers use — does it correctly: percent-encoding, ports, query strings, and relative resolution all handled to spec. Modern Node makes URL a global, so you usually don't even import it.
The URL class
// URL is a global — no import needed
const u = new URL('https://user:pass@example.com:8080/path/page?q=node&n=2#sec')
u.protocol // 'https:'
u.hostname // 'example.com'
u.port // '8080'
u.pathname // '/path/page'
u.search // '?q=node&n=2'
u.hash // '#sec'
u.username // 'user'Property | Holds |
|---|---|
| The full URL string (also what |
|
|
| Scheme with trailing colon — |
| With port / without port |
| The path, percent-decoded for display |
| Raw query string / parsed |
| The |
Parsing the query string
url.searchParams is a live URLSearchParams object — iterate it, read, add, and delete params, with encoding handled automatically:
const u = new URL('https://api.example.com/search?q=node+js&page=2&tag=a&tag=b')
u.searchParams.get('q') // 'node js' (decoded)
u.searchParams.get('page') // '2'
u.searchParams.getAll('tag') // ['a', 'b'] (repeated keys)
u.searchParams.has('page') // true
u.searchParams.set('page', '3')
u.searchParams.append('tag', 'c')
console.log(u.href) // ...&page=3&tag=a&tag=b&tag=cResolving relative URLs
Pass a base as the second argument and URL resolves relative references exactly like a browser following a link:
new URL('/about', 'https://example.com/blog/').href
// → 'https://example.com/about' (absolute path replaces)
new URL('../faq', 'https://example.com/blog/posts/').href
// → 'https://example.com/blog/faq' (relative climbs)
new URL('page.html', 'https://example.com/blog/').href
// → 'https://example.com/blog/page.html'Converting between file paths and URLs
ESM gives you import.meta.url as a file:// URL, not a path. url provides the conversions — essential for the __dirname reconstruction pattern:
import { fileURLToPath, pathToFileURL } from 'node:url'
import { dirname } from 'node:path'
const __filename = fileURLToPath(import.meta.url) // → '/home/app/index.js'
const __dirname = dirname(__filename) // → '/home/app'
pathToFileURL('/home/app/data.json').href // 'file:///home/app/data.json'