Working with URLs in JavaScript

Master the modern JavaScript URL API for robust, secure, and performant URL manipulation in your web applications.

Why Modern URL APIs Matter

The JavaScript URL API, introduced as part of the Web Platform, offers significant advantages over traditional approaches. Manual string parsing of URLs is notoriously error-prone due to the complexity of URL encoding, varying formats, and edge cases in special characters. The URL API provides a reliable, browser-native solution that handles these complexities correctly.

Beyond reliability, the URL API enhances security by automatically handling URL encoding and preventing common injection vulnerabilities. It also improves performance by optimizing internal operations and reducing the need for external libraries. When building modern web applications with frameworks like Next.js or React, understanding these APIs is essential for implementing proper routing, form handling, and API integrations that perform well and remain secure.

This guide covers everything you need to know about working with URLs in JavaScript, from basic parsing to advanced security patterns. Whether you're building single-page applications or server-rendered experiences, these techniques will help you write cleaner, more maintainable code. For additional URL manipulation techniques, see our guide on getting URLs and URL parts in JavaScript.

Creating URL Objects
1// Absolute URL2const url = new URL('https://example.com/path?query=value#hash');3 4// Relative URL with base5const baseUrl = 'https://example.com/docs';6const relativeUrl = new URL('getting-started', baseUrl);7// Result: https://example.com/docs/getting-started

The URL Constructor: Parsing and Building URLs

URL Properties

The URL object exposes properties for accessing each component of the URL. Each property provides direct access to a specific part of the URL structure, making it easy to read or modify individual components without string manipulation.

The href property returns the complete URL as a fully formatted string, including all components. The protocol property shows the URL scheme (such as "https:" or "http:"), always including the trailing colon. The hostname property contains the domain name without the port, while port explicitly returns the port number if specified in the URL.

The pathname property provides access to the path portion of the URL, which begins with a forward slash and contains the hierarchical structure of the resource. The search property returns the query string including the leading question mark, while hash returns the fragment identifier including the leading hash symbol. Understanding these properties is fundamental to effective URL manipulation in modern web development.

PropertyDescriptionExample
hrefFull URL as string"https://example.com:8080/blog?id=123"
protocolURL protocol"https:"
hostnameDomain name"example.com"
portPort number"8080"
pathnamePath portion'/blog/posts'
searchQuery string with '?''?id=123'
hashFragment with '#''#comments'
Accessing URL Components
1const url = new URL('https://example.com:8080/blog/posts?id=123#comments');2 3console.log(url.protocol); // "https:"4console.log(url.hostname); // "example.com"5console.log(url.port); // "8080"6console.log(url.pathname); // "/blog/posts"7console.log(url.search); // "?id=123"8console.log(url.hash); // "#comments"

Modifying URL Components

One of the most powerful features of the URL API is that modifying any property automatically updates the href. This makes it ideal for building dynamic URLs for navigation, filtering, or API requests. When you change a property like hostname or pathname, the URL object internally recalculates the entire href string, ensuring consistency across all components.

This bidirectional synchronization means you can read from individual properties for clarity and write to them for modification, all while maintaining proper URL formatting. The API handles edge cases like ensuring the pathname always starts with a slash and properly encoding special characters. This approach eliminates bugs that commonly occur when developers attempt to manually concatenate URL strings.

Modifying URL Properties
1const url = new URL('https://example.com/blog');2 3url.protocol = 'https:';4url.hostname = 'api.example.com';5url.pathname = '/v2/articles';6 7console.log(url.href); // "https://api.example.com/v2/articles"

Working with Query Parameters: URLSearchParams

The URLSearchParams interface defines utility methods to work with the query string of a URL. It provides a consistent API for reading, adding, modifying, and deleting query parameters without worrying about proper encoding or delimiter handling.

URLSearchParams handles the complexity of query string manipulation by providing intuitive methods for common operations. Whether you need to read a single parameter value, iterate over all parameters, or build complex query strings with multiple values per parameter, the API has you covered. The interface is also iterable, meaning you can use it directly in for...of loops and spread operators.

This API is particularly valuable when building filter systems, search functionality, or pagination where users interact with URL parameters directly. It integrates seamlessly with the URL interface through the searchParams property, giving you a unified approach to URL manipulation that covers both the path and query portions of your URLs. For SEO-friendly URL structures, proper query parameter handling is essential--learn more about search engine optimization services that leverage clean URL architectures.

URLSearchParams Methods
MethodDescription
get(name)Returns first value for the parameter
getAll(name)Returns array of all values
has(name)Returns true if parameter exists
append(name, value)Adds new parameter (allows duplicates)
set(name, value)Sets parameter value (removes duplicates)
delete(name)Removes parameter
sort()Sorts parameters by key
toString()Returns query string
keys()Iterator of parameter names
values()Iterator of parameter values
entries()Iterator of key-value pairs
URLSearchParams Examples
1// Reading query parameters2const url = new URL('https://example.com/search?q=javascript&page=2');3const params = url.searchParams;4 5console.log(params.get('q')); // "javascript"6console.log(params.get('page')); // "2"7 8// Adding and modifying parameters9url.searchParams.append('filter', 'recent');10url.searchParams.set('sort', 'relevance');11url.searchParams.delete('page');12 13// Iterating over parameters14for (const [key, value] of params) {15 console.log(`${key}: ${value}`);16}

Common Use Cases

Client-Side Routing in SPAs

Single-page applications use the URL API to manage browser history and handle client-side routing without full page reloads. By manipulating the URL while providing a seamless user experience, SPAs can maintain bookmarkable, shareable URLs that reflect the current application state.

// Building navigation URLs for SPA routing
function navigateToProduct(productId) {
 const url = new URL(window.location.origin);
 url.pathname = '/products';
 url.searchParams.set('id', productId);

 window.history.pushState({}, '', url);
 renderProduct(productId);
}

// Reading route parameters from current URL
function getCurrentProductId() {
 const url = new URL(window.location.href);
 return url.searchParams.get('id');
}

Form Handling

The URLSearchParams API simplifies form data processing by providing a standardized way to convert form submissions into query strings. This is particularly useful for search forms, filter panels, and any interface where form data should be reflected in the URL for bookmarking or sharing.

// Collect form data into URLSearchParams
function buildQueryString(formElement) {
 const formData = new FormData(formElement);
 const params = new URLSearchParams();

 for (const [key, value] of formData.entries()) {
 params.append(key, value);
 }

 return params.toString();
}

API Request Construction

Building API requests with proper encoding is essential for reliable data transmission. The URL API ensures that all parameter names and values are properly encoded, preventing issues with special characters, spaces, and ampersands in your API calls.

function buildApiUrl(endpoint, options = {}) {
 const url = new URL(`${window.location.origin}/api${endpoint}`);

 if (options.page) url.searchParams.set('page', options.page);
 if (options.limit) url.searchParams.set('limit', options.limit);
 if (options.sortBy) url.searchParams.set('sort', options.sortBy);
 if (options.filters) {
 Object.entries(options.filters).forEach(([key, value]) => {
 url.searchParams.set(`filter[${key}]`, value);
 });
 }

 return url;
}

Security Best Practices

URL Validation

Always validate URLs before using them, especially when dealing with user input. The URL constructor will throw an error if the input is not a valid URL, which you can catch to handle invalid input gracefully. This validation is your first line of defense against malformed URLs that could cause unexpected behavior in your application.

Preventing URL Injection

Open redirect vulnerabilities occur when an application uses user-controllable data to construct redirect URLs without proper validation. Attackers can exploit these vulnerabilities to phish users by making redirect URLs appear to come from your domain while actually directing users to malicious sites. Always validate that redirect URLs remain within your domain and follow allowlist patterns for permitted destinations.

Handling Special Characters

The URL API automatically handles URL encoding for special characters in both parameter names and values. Spaces become "%20", ampersands become "%26", and other special characters are properly encoded. This automatic handling prevents many common injection vulnerabilities, but you should still validate that user input matches expected formats before adding it to URLs.

Safe URL Construction
1// Validate URL before use2function isValidUrl(string) {3 try {4 new URL(string);5 return true;6 } catch {7 return false;8 }9}10 11// Safe redirect with allowlist12function redirectUser(redirectTo, allowedPaths) {13 try {14 const url = new URL(redirectTo, window.location.origin);15 16 // Only allow same-origin redirects17 if (url.origin !== window.location.origin) {18 url.pathname = '/';19 }20 21 // Restrict to specific paths22 if (!allowedPaths.some(path => url.pathname.startsWith(path))) {23 url.pathname = '/dashboard';24 }25 26 window.location.href = url.href;27 } catch {28 window.location.href = '/dashboard';29 }30}

Performance Considerations

URL Object Reuse

Creating URL objects has minimal overhead in modern JavaScript engines, but for frequently accessed URLs, caching can improve performance. This is particularly relevant in applications that repeatedly access the same base URL with different parameters, such as pagination systems or filterable product listings. Consider implementing a simple cache to store parsed URL objects.

Minimizing SearchParams Operations

When modifying multiple parameters, batching operations is more efficient than making individual changes. Each call to set(), append(), or delete() triggers internal updates to the URL's search string. For complex filtering systems with many parameters, building a new URLSearchParams object and assigning it to url.search reduces these intermediate recalculations.

// More efficient - build params separately then set
function updateFiltersEfficient(filters) {
 const url = new URL(window.location.href);
 const params = new URLSearchParams();

 // Build all params at once
 Object.entries(filters).forEach(([key, value]) => {
 params.set(key, value);
 });

 // Single update
 url.search = params.toString();

 return url;
}

Integration with Modern Frameworks

Next.js URL Handling

Next.js uses the URL API internally for routing and provides utilities that build upon these APIs. The useSearchParams hook gives you access to the current query parameters, while useRouter handles navigation. By combining these with URLSearchParams, you can create dynamic, filterable interfaces that update the URL cleanly.

React Router

React Router provides hooks for URL management that work seamlessly with the URL API. The useSearchParams hook returns the current search parameters as a URLSearchParams object, and setSearchParams allows you to update them. This integration makes it straightforward to build URL-driven state management in your React applications.

Next.js URL Management Example
1import { useRouter, useSearchParams } from 'next/navigation';2 3function ProductFilters() {4 const router = useRouter();5 const searchParams = useSearchParams();6 7 const updateFilter = (key, value) => {8 const params = new URLSearchParams(searchParams.toString());9 params.set(key, value);10 params.set('page', '1'); // Reset pagination11 12 router.push(`?${params.toString()}`);13 };14 15 return (16 <div>17 <button onClick={() => updateFilter('category', 'electronics')}>18 Electronics19 </button>20 </div>21 );22}

Browser Support

100%

Chrome Support

100%

Firefox Support

100%

Safari Support

2018

URLSearchParams Available Since

Frequently Asked Questions

Build Robust Web Applications with Digital Thrive

Our team of experienced developers specializes in building modern web applications using the latest JavaScript APIs and frameworks. From single-page applications to server-rendered experiences, we deliver performant solutions that drive business growth.