The URL module provides utilities for URL parsing and manipulation. Here's how to use it.
URL Constructor#
1// Create URL from string
2const url = new URL('https://example.com:8080/path/page?name=value#section');
3
4console.log(url.href); // Full URL string
5console.log(url.protocol); // 'https:'
6console.log(url.host); // 'example.com:8080'
7console.log(url.hostname); // 'example.com'
8console.log(url.port); // '8080'
9console.log(url.pathname); // '/path/page'
10console.log(url.search); // '?name=value'
11console.log(url.hash); // '#section'
12console.log(url.origin); // 'https://example.com:8080'
13
14// With base URL
15const relative = new URL('/api/users', 'https://example.com');
16console.log(relative.href); // 'https://example.com/api/users'
17
18// Resolve relative paths
19const resolved = new URL('../images/photo.jpg', 'https://example.com/pages/about/');
20console.log(resolved.href); // 'https://example.com/pages/images/photo.jpg'Modifying URLs#
1const url = new URL('https://example.com/path');
2
3// Modify properties
4url.pathname = '/new-path';
5url.port = '3000';
6url.hash = '#footer';
7
8console.log(url.href);
9// 'https://example.com:3000/new-path#footer'
10
11// Protocol change
12url.protocol = 'http';
13console.log(url.href);
14// 'http://example.com:3000/new-path#footer'
15
16// Auth (username/password)
17url.username = 'user';
18url.password = 'pass';
19console.log(url.href);
20// 'http://user:pass@example.com:3000/new-path#footer'
21
22// Clear port
23url.port = '';
24console.log(url.host); // 'example.com'URLSearchParams#
1// From URL
2const url = new URL('https://example.com?name=alice&age=30');
3const params = url.searchParams;
4
5// Get values
6console.log(params.get('name')); // 'alice'
7console.log(params.get('age')); // '30'
8console.log(params.get('city')); // null
9
10// Check existence
11console.log(params.has('name')); // true
12console.log(params.has('city')); // false
13
14// Get all values (for repeated params)
15const url2 = new URL('https://example.com?tag=js&tag=css&tag=html');
16console.log(url2.searchParams.getAll('tag'));
17// ['js', 'css', 'html']
18
19// Standalone URLSearchParams
20const params2 = new URLSearchParams('a=1&b=2');
21const params3 = new URLSearchParams({ a: '1', b: '2' });
22const params4 = new URLSearchParams([['a', '1'], ['b', '2']]);Manipulating Query Parameters#
1const params = new URLSearchParams();
2
3// Add parameters
4params.set('name', 'alice');
5params.set('age', '30');
6params.append('hobby', 'reading');
7params.append('hobby', 'coding');
8
9console.log(params.toString());
10// 'name=alice&age=30&hobby=reading&hobby=coding'
11
12// Delete parameter
13params.delete('age');
14
15// Sort alphabetically
16params.sort();
17console.log(params.toString());
18// 'hobby=reading&hobby=coding&name=alice'
19
20// Iterate
21for (const [key, value] of params) {
22 console.log(`${key}: ${value}`);
23}
24
25// Convert to object
26const obj = Object.fromEntries(params);
27// Note: loses duplicate keys
28
29// Get all entries
30const entries = [...params.entries()];
31// [['hobby', 'reading'], ['hobby', 'coding'], ['name', 'alice']]Building URLs#
1// Build URL programmatically
2function buildApiUrl(endpoint, params = {}) {
3 const url = new URL(endpoint, 'https://api.example.com');
4
5 Object.entries(params).forEach(([key, value]) => {
6 if (value !== undefined && value !== null) {
7 url.searchParams.set(key, value);
8 }
9 });
10
11 return url.toString();
12}
13
14const apiUrl = buildApiUrl('/users', {
15 page: 1,
16 limit: 10,
17 sort: 'name',
18});
19// 'https://api.example.com/users?page=1&limit=10&sort=name'
20
21// URL builder class
22class URLBuilder {
23 constructor(base) {
24 this.url = new URL(base);
25 }
26
27 path(segment) {
28 this.url.pathname += segment.startsWith('/') ? segment : `/${segment}`;
29 return this;
30 }
31
32 query(params) {
33 Object.entries(params).forEach(([key, value]) => {
34 this.url.searchParams.set(key, value);
35 });
36 return this;
37 }
38
39 hash(fragment) {
40 this.url.hash = fragment;
41 return this;
42 }
43
44 toString() {
45 return this.url.href;
46 }
47}
48
49const url = new URLBuilder('https://example.com')
50 .path('/api')
51 .path('/users')
52 .query({ page: 1, limit: 10 })
53 .hash('results')
54 .toString();URL Validation#
1// Check if valid URL
2function isValidUrl(string) {
3 try {
4 new URL(string);
5 return true;
6 } catch {
7 return false;
8 }
9}
10
11console.log(isValidUrl('https://example.com')); // true
12console.log(isValidUrl('not-a-url')); // false
13
14// Validate specific protocols
15function isValidHttpUrl(string) {
16 try {
17 const url = new URL(string);
18 return url.protocol === 'http:' || url.protocol === 'https:';
19 } catch {
20 return false;
21 }
22}
23
24// Extract and validate
25function parseUrl(urlString) {
26 try {
27 const url = new URL(urlString);
28 return {
29 valid: true,
30 protocol: url.protocol,
31 hostname: url.hostname,
32 pathname: url.pathname,
33 params: Object.fromEntries(url.searchParams),
34 };
35 } catch (error) {
36 return {
37 valid: false,
38 error: error.message,
39 };
40 }
41}URL Encoding#
1// encodeURIComponent - for values
2const value = 'hello world & more';
3const encoded = encodeURIComponent(value);
4// 'hello%20world%20%26%20more'
5
6// decodeURIComponent - decode values
7const decoded = decodeURIComponent(encoded);
8// 'hello world & more'
9
10// encodeURI - for full URLs (preserves special chars)
11const urlStr = 'https://example.com/path?name=hello world';
12const encodedUrl = encodeURI(urlStr);
13// 'https://example.com/path?name=hello%20world'
14
15// URLSearchParams auto-encodes
16const params = new URLSearchParams();
17params.set('message', 'Hello & Goodbye');
18console.log(params.toString());
19// 'message=Hello+%26+Goodbye'
20
21// File URLs
22const filePath = '/Users/name/Documents/file name.txt';
23const fileUrl = new URL(`file://${filePath}`);
24console.log(fileUrl.href);
25// Encoded properlyPractical Patterns#
1// Parse and modify existing URL
2function addQueryParam(urlString, key, value) {
3 const url = new URL(urlString);
4 url.searchParams.set(key, value);
5 return url.toString();
6}
7
8// Remove query parameters
9function removeQueryParams(urlString, ...keys) {
10 const url = new URL(urlString);
11 keys.forEach(key => url.searchParams.delete(key));
12 return url.toString();
13}
14
15// Get clean URL (no query/hash)
16function getCleanUrl(urlString) {
17 const url = new URL(urlString);
18 return `${url.origin}${url.pathname}`;
19}
20
21// Compare URLs ignoring order of params
22function urlsEqual(url1, url2) {
23 const a = new URL(url1);
24 const b = new URL(url2);
25
26 a.searchParams.sort();
27 b.searchParams.sort();
28
29 return a.href === b.href;
30}
31
32// Merge query parameters
33function mergeQueryParams(urlString, newParams) {
34 const url = new URL(urlString);
35
36 Object.entries(newParams).forEach(([key, value]) => {
37 if (value === null) {
38 url.searchParams.delete(key);
39 } else {
40 url.searchParams.set(key, value);
41 }
42 });
43
44 return url.toString();
45}Common Use Cases#
1// API request builder
2class ApiClient {
3 constructor(baseUrl) {
4 this.baseUrl = new URL(baseUrl);
5 }
6
7 buildUrl(path, params = {}) {
8 const url = new URL(path, this.baseUrl);
9
10 Object.entries(params).forEach(([key, value]) => {
11 if (Array.isArray(value)) {
12 value.forEach(v => url.searchParams.append(key, v));
13 } else if (value !== undefined) {
14 url.searchParams.set(key, String(value));
15 }
16 });
17
18 return url.toString();
19 }
20
21 async get(path, params) {
22 const url = this.buildUrl(path, params);
23 return fetch(url);
24 }
25}
26
27// Pagination URLs
28function paginationUrls(currentUrl, currentPage, totalPages) {
29 const url = new URL(currentUrl);
30
31 return {
32 first: (() => {
33 url.searchParams.set('page', '1');
34 return url.toString();
35 })(),
36 prev: currentPage > 1 ? (() => {
37 url.searchParams.set('page', String(currentPage - 1));
38 return url.toString();
39 })() : null,
40 next: currentPage < totalPages ? (() => {
41 url.searchParams.set('page', String(currentPage + 1));
42 return url.toString();
43 })() : null,
44 last: (() => {
45 url.searchParams.set('page', String(totalPages));
46 return url.toString();
47 })(),
48 };
49}Best Practices#
Parsing:
✓ Use URL constructor for validation
✓ Use URLSearchParams for queries
✓ Handle parsing errors gracefully
✓ Validate protocols when needed
Building:
✓ Use URL for constructing URLs
✓ Let URLSearchParams handle encoding
✓ Build from trusted base URLs
✓ Sanitize user input
Encoding:
✓ Use encodeURIComponent for values
✓ Let URL handle most encoding
✓ Be careful with double-encoding
✓ Test with special characters
Avoid:
✗ String concatenation for URLs
✗ Manual encoding when not needed
✗ Assuming URL structure
✗ Ignoring edge cases
Conclusion#
The URL module provides robust URL parsing and manipulation. Use the URL constructor for validation and modification, URLSearchParams for query string handling, and proper encoding functions for safety. Build URLs programmatically rather than concatenating strings.