Back to Blog
Node.jsURLParsingBackend

Node.js URL Module Guide

Master Node.js URL parsing, construction, and manipulation.

B
Bootspring Team
Engineering
July 27, 2018
6 min read

The URL module provides utilities for URL parsing and manipulation using the WHATWG URL Standard.

URL Class#

1// Create URL object 2const myURL = new URL('https://user:pass@example.com:8080/path/name?query=value#hash'); 3 4console.log(myURL.href); // Full URL 5console.log(myURL.protocol); // 'https:' 6console.log(myURL.username); // 'user' 7console.log(myURL.password); // 'pass' 8console.log(myURL.host); // 'example.com:8080' 9console.log(myURL.hostname); // 'example.com' 10console.log(myURL.port); // '8080' 11console.log(myURL.pathname); // '/path/name' 12console.log(myURL.search); // '?query=value' 13console.log(myURL.hash); // '#hash' 14console.log(myURL.origin); // 'https://example.com:8080' 15 16// Modify URL parts 17myURL.pathname = '/new/path'; 18myURL.hash = 'section'; 19console.log(myURL.href); 20// 'https://user:pass@example.com:8080/new/path?query=value#section'

Relative URLs#

1// Resolve relative URL against base 2const base = new URL('https://example.com/path/page.html'); 3const relative = new URL('../other/file.html', base); 4 5console.log(relative.href); 6// 'https://example.com/other/file.html' 7 8// Various relative paths 9new URL('/absolute', 'https://example.com/path/'); 10// 'https://example.com/absolute' 11 12new URL('relative', 'https://example.com/path/'); 13// 'https://example.com/path/relative' 14 15new URL('./same-level', 'https://example.com/path/'); 16// 'https://example.com/path/same-level' 17 18new URL('../parent-level', 'https://example.com/path/sub/'); 19// 'https://example.com/path/parent-level' 20 21// Protocol-relative 22new URL('//cdn.example.com/file.js', 'https://example.com'); 23// 'https://cdn.example.com/file.js'

URLSearchParams#

1// Parse query string 2const url = new URL('https://example.com?name=John&age=30&hobby=coding&hobby=reading'); 3const params = url.searchParams; 4 5// Get values 6params.get('name'); // 'John' 7params.get('age'); // '30' 8params.get('hobby'); // 'coding' (first value) 9params.getAll('hobby'); // ['coding', 'reading'] 10params.has('name'); // true 11 12// Iterate 13for (const [key, value] of params) { 14 console.log(`${key}: ${value}`); 15} 16 17params.forEach((value, key) => { 18 console.log(`${key}: ${value}`); 19}); 20 21// Keys and values 22[...params.keys()]; // ['name', 'age', 'hobby', 'hobby'] 23[...params.values()]; // ['John', '30', 'coding', 'reading'] 24[...params.entries()]; // [['name', 'John'], ...] 25 26// Modify 27params.set('name', 'Jane'); // Replace value 28params.append('skill', 'js'); // Add new 29params.delete('age'); // Remove 30 31console.log(url.href); 32// 'https://example.com/?name=Jane&hobby=coding&hobby=reading&skill=js'

Creating URLSearchParams#

1// From string 2const params1 = new URLSearchParams('name=John&age=30'); 3 4// From object 5const params2 = new URLSearchParams({ 6 name: 'John', 7 age: '30', 8 active: 'true' 9}); 10 11// From array of pairs 12const params3 = new URLSearchParams([ 13 ['name', 'John'], 14 ['hobby', 'coding'], 15 ['hobby', 'reading'] // Duplicate keys allowed 16]); 17 18// From another URLSearchParams 19const params4 = new URLSearchParams(params1); 20 21// Convert to string 22params2.toString(); // 'name=John&age=30&active=true' 23 24// Sort alphabetically 25params2.sort(); 26params2.toString(); // 'active=true&age=30&name=John'

URL Encoding#

1// URLSearchParams handles encoding 2const params = new URLSearchParams(); 3params.set('query', 'hello world'); 4params.set('special', 'a&b=c'); 5 6params.toString(); 7// 'query=hello+world&special=a%26b%3Dc' 8 9// Manual encoding 10encodeURIComponent('hello world'); // 'hello%20world' 11encodeURI('https://example.com/path with spaces'); 12// 'https://example.com/path%20with%20spaces' 13 14// Decoding 15decodeURIComponent('hello%20world'); // 'hello world' 16decodeURI('https://example.com/path%20with%20spaces'); 17// 'https://example.com/path with spaces'

Building URLs#

1// Build URL programmatically 2function buildUrl(base, path, params = {}) { 3 const url = new URL(path, base); 4 5 Object.entries(params).forEach(([key, value]) => { 6 if (Array.isArray(value)) { 7 value.forEach(v => url.searchParams.append(key, v)); 8 } else if (value !== undefined && value !== null) { 9 url.searchParams.set(key, String(value)); 10 } 11 }); 12 13 return url.href; 14} 15 16const apiUrl = buildUrl('https://api.example.com', '/users', { 17 page: 1, 18 limit: 10, 19 sort: 'name', 20 filter: ['active', 'verified'] 21}); 22 23// 'https://api.example.com/users?page=1&limit=10&sort=name&filter=active&filter=verified' 24 25// URL builder class 26class UrlBuilder { 27 constructor(base) { 28 this.url = new URL(base); 29 } 30 31 path(path) { 32 this.url.pathname = path; 33 return this; 34 } 35 36 query(key, value) { 37 this.url.searchParams.set(key, value); 38 return this; 39 } 40 41 queries(params) { 42 Object.entries(params).forEach(([k, v]) => { 43 this.url.searchParams.set(k, v); 44 }); 45 return this; 46 } 47 48 hash(hash) { 49 this.url.hash = hash; 50 return this; 51 } 52 53 build() { 54 return this.url.href; 55 } 56} 57 58const url = new UrlBuilder('https://example.com') 59 .path('/api/users') 60 .queries({ page: '1', limit: '20' }) 61 .hash('results') 62 .build();

Validating URLs#

1// Check if string is valid URL 2function isValidUrl(string) { 3 try { 4 new URL(string); 5 return true; 6 } catch { 7 return false; 8 } 9} 10 11isValidUrl('https://example.com'); // true 12isValidUrl('not a url'); // false 13isValidUrl('example.com'); // false (no protocol) 14 15// Validate with constraints 16function isValidHttpUrl(string) { 17 try { 18 const url = new URL(string); 19 return url.protocol === 'http:' || url.protocol === 'https:'; 20 } catch { 21 return false; 22 } 23} 24 25// Extract domain 26function getDomain(urlString) { 27 try { 28 const url = new URL(urlString); 29 return url.hostname; 30 } catch { 31 return null; 32 } 33} 34 35getDomain('https://www.example.com/path'); // 'www.example.com'

URL Comparison#

1// URLs are normalized 2const url1 = new URL('HTTPS://Example.COM/path/'); 3const url2 = new URL('https://example.com/path/'); 4 5url1.href === url2.href; // true (both normalized) 6 7// Compare specific parts 8function isSameOrigin(url1, url2) { 9 const a = new URL(url1); 10 const b = new URL(url2); 11 return a.origin === b.origin; 12} 13 14isSameOrigin( 15 'https://example.com/path1', 16 'https://example.com/path2' 17); // true 18 19isSameOrigin( 20 'https://example.com', 21 'https://api.example.com' 22); // false (different subdomain) 23 24// Check if URL matches pattern 25function matchesPattern(url, pattern) { 26 const urlObj = new URL(url); 27 const patternObj = new URL(pattern); 28 29 return ( 30 urlObj.hostname === patternObj.hostname && 31 urlObj.pathname.startsWith(patternObj.pathname) 32 ); 33}

File URLs#

1import { fileURLToPath, pathToFileURL } from 'url'; 2import { dirname } from 'path'; 3 4// Convert file URL to path 5const filePath = fileURLToPath(import.meta.url); 6// /Users/user/project/file.js 7 8// Get directory name (ESM equivalent of __dirname) 9const __dirname = dirname(fileURLToPath(import.meta.url)); 10 11// Convert path to file URL 12const url = pathToFileURL('/path/to/file.js'); 13// file:///path/to/file.js 14 15// Works with import() 16const config = await import(pathToFileURL('./config.js'));

Legacy URL Module#

1import { parse, format, resolve } from 'url'; 2 3// Legacy parse (deprecated but still works) 4const parsed = parse('https://example.com/path?query=value', true); 5console.log(parsed.query); // { query: 'value' } as object 6 7// Legacy format 8const formatted = format({ 9 protocol: 'https', 10 hostname: 'example.com', 11 pathname: '/path', 12 query: { key: 'value' } 13}); 14// 'https://example.com/path?key=value' 15 16// Legacy resolve 17resolve('https://example.com/path/', '../other'); 18// 'https://example.com/other' 19 20// Prefer WHATWG URL class for new code

Common Patterns#

1// Extract pathname segments 2function getPathSegments(urlString) { 3 const url = new URL(urlString); 4 return url.pathname.split('/').filter(Boolean); 5} 6 7getPathSegments('https://example.com/api/v1/users'); 8// ['api', 'v1', 'users'] 9 10// Add/update single query parameter 11function setQueryParam(urlString, key, value) { 12 const url = new URL(urlString); 13 url.searchParams.set(key, value); 14 return url.href; 15} 16 17// Remove query parameter 18function removeQueryParam(urlString, key) { 19 const url = new URL(urlString); 20 url.searchParams.delete(key); 21 return url.href; 22} 23 24// Get clean URL (no query, no hash) 25function getCleanUrl(urlString) { 26 const url = new URL(urlString); 27 url.search = ''; 28 url.hash = ''; 29 return url.href; 30} 31 32// Parse hash parameters (for SPAs) 33function parseHashParams(urlString) { 34 const url = new URL(urlString); 35 const hashParams = new URLSearchParams(url.hash.slice(1)); 36 return Object.fromEntries(hashParams); 37} 38 39parseHashParams('https://example.com#access_token=abc&expires_in=3600'); 40// { access_token: 'abc', expires_in: '3600' }

Best Practices#

URL Class: ✓ Use WHATWG URL class (new URL) ✓ Handle URL construction errors ✓ Use searchParams for query strings ✓ Normalize URLs for comparison Security: ✓ Validate URLs before use ✓ Check protocol (http/https) ✓ Sanitize user-provided URLs ✓ Use URL encoding for parameters Patterns: ✓ Create URL builders for complex URLs ✓ Use relative URLs when possible ✓ Extract common URL operations ✓ Handle edge cases Avoid: ✗ String concatenation for URLs ✗ Manual query string building ✗ Forgetting to encode values ✗ Using deprecated url.parse

Conclusion#

The Node.js URL module provides robust URL parsing and manipulation following the WHATWG URL Standard. Use the URL class for parsing and constructing URLs, URLSearchParams for query string handling, and fileURLToPath/pathToFileURL for file system integration. Always validate URLs and use proper encoding. The modern URL class should be preferred over the legacy url.parse function.

Share this article

Help spread the word about Bootspring