How can I retrieve query string parameters in JavaScript without using plugins?
What is the native JavaScript method to extract URL parameters from the query string? If no native solution exists, what jQuery plugin or alternative JavaScript approach can be used to parse query string values?
The native JavaScript method to extract URL query string parameters is the URLSearchParams API, which was introduced in ES2017 and provides a clean, built-in way to parse query strings without requiring any external libraries. You can access query parameters using new URLSearchParams(window.location.search) and then use methods like get(), getAll(), has(), and entries() to retrieve the values. For older browsers that don’t support URLSearchParams, you can implement a manual parsing function using regular expressions or string manipulation methods.
Contents
- Understanding Query Strings
- Native URLSearchParams API
- Browser Compatibility
- Alternative Native Approaches
- Handling Complex Query Scenarios
- Practical Examples
Understanding Query Strings
A query string is the part of a URL that contains data passed to web applications. It typically appears after the ? character in a URL and consists of key-value pairs separated by & symbols. For example:
https://example.com/page?name=John&age=30&city=New%20York
In this URL:
name=Johnis a parameter with key “name” and value “John”age=30is a parameter with key “age” and value “30”city=New%20Yorkis a parameter with key “city” and value “New York” (URL-encoded)
Modern web applications often need to extract these parameters to:
- Pre-populate forms with user-provided data
- Implement search functionality
- Track user behavior and analytics
- Maintain application state across page reloads
Native URLSearchParams API
The URLSearchParams interface is the most elegant and recommended native solution for working with query strings in modern JavaScript.
Basic Usage
// Get the current page's query string
const queryString = window.location.search;
// Example: "?name=John&age=30&city=New%20York"
// Create a URLSearchParams object
const urlParams = new URLSearchParams(queryString);
// Get individual parameters
const name = urlParams.get('name'); // "John"
const age = urlParams.get('age'); // "30"
const city = urlParams.get('city'); // "New York"
Key Methods
The URLSearchParams API provides several useful methods:
get(name): Returns the first value associated with the given search parametergetAll(name): Returns all values associated with a given search parameter (for multiple values with the same key)has(name): Returns a Boolean indicating if a parameter existsset(name, value): Sets the value for a parameterappend(name, value): Appends a new value to an existing parameterdelete(name): Deletes a parametertoString(): Returns the query stringentries(): Returns an iterator of all key-value pairskeys(): Returns an iterator of all keysvalues(): Returns an iterator of all values
Working with Multiple Values
// URL: ?tags=javascript&tags=web&tags=development
const urlParams = new URLSearchParams(window.location.search);
const tags = urlParams.getAll('tags');
// ["javascript", "web", "development"]
// Iterate through all parameters
for (const [key, value] of urlParams.entries()) {
console.log(`${key}: ${value}`);
}
Browser Compatibility
The URLSearchParams API is widely supported in modern browsers:
- Chrome: 49+ (2016)
- Firefox: 29+ (2014)
- Safari: 10.1+ (2017)
- Edge: 17+ (2018)
- Node.js: 10+ (2018)
For older browsers or environments that don’t support URLSearchParams, you’ll need alternative approaches.
Alternative Native Approaches
Manual Parsing with Regular Expressions
function getQueryParams(url = window.location.search) {
const params = {};
const queryString = url.split('?')[1] || '';
queryString.split('&').forEach(param => {
const [key, value] = param.split('=');
if (key) {
// Decode URI components
const decodedKey = decodeURIComponent(key);
const decodedValue = value ? decodeURIComponent(value) : '';
// Handle multiple values with the same key
if (params[decodedKey]) {
if (Array.isArray(params[decodedKey])) {
params[decodedKey].push(decodedValue);
} else {
params[decodedKey] = [params[decodedKey], decodedValue];
}
} else {
params[decodedKey] = decodedValue;
}
}
});
return params;
}
// Usage
const params = getQueryParams();
const name = params.name; // "John"
String Manipulation Approach
function parseQueryString() {
const queryString = window.location.search.substring(1);
const params = {};
if (queryString) {
const pairs = queryString.split('&');
for (let i = 0; i < pairs.length; i++) {
const pair = pairs[i].split('=');
const key = decodeURIComponent(pair[0]);
const value = pair.length > 1 ? decodeURIComponent(pair[1]) : '';
if (params[key]) {
if (Array.isArray(params[key])) {
params[key].push(value);
} else {
params[key] = [params[key], value];
}
} else {
params[key] = value;
}
}
}
return params;
}
Polyfill for URLSearchParams
For older browsers, you can include a polyfill:
// Simple URLSearchParams polyfill
if (!window.URLSearchParams) {
window.URLSearchParams = function(queryString) {
this.params = {};
if (queryString) {
const pairs = queryString.replace(/^\?/, '').split('&');
pairs.forEach(pair => {
const [key, value] = pair.split('=');
if (key) {
this.params[decodeURIComponent(key)] = value ? decodeURIComponent(value) : '';
}
});
}
};
URLSearchParams.prototype.get = function(name) {
return this.params[name] || null;
};
URLSearchParams.prototype.getAll = function(name) {
return this.params[name] ? [this.params[name]] : [];
};
URLSearchParams.prototype.has = function(name) {
return name in this.params;
};
}
Handling Complex Query Scenarios
URL Encoding/Decoding
Proper handling of URL-encoded characters is crucial:
// URL: ?search=javascript%20tutorial
const urlParams = new URLSearchParams(window.location.search);
const searchTerm = urlParams.get('search'); // "javascript tutorial"
// Manual encoding/decoding
const encodedValue = encodeURIComponent('javascript tutorial'); // "javascript%20tutorial"
const decodedValue = decodeURIComponent('javascript%20tutorial'); // "javascript tutorial"
Fragment Parameters
Parameters in URL fragments (after #) won’t appear in window.location.search:
// URL: https://example.com/#section=about?param=value
const hash = window.location.hash;
const fragmentParams = new URLSearchParams(hash.split('?')[1] || '');
Custom URL Parsing
function parseUrlParams(url) {
try {
const urlObj = new URL(url);
return new URLSearchParams(urlObj.search);
} catch (e) {
// Fallback for invalid URLs or non-browser environments
const searchMatch = url.match(/\?(.+)$/);
if (searchMatch) {
return new URLSearchParams(searchMatch[1]);
}
return new URLSearchParams('');
}
}
// Usage with any URL
const externalUrl = 'https://example.com/page?user=123&lang=en';
const params = parseUrlParams(externalUrl);
Practical Examples
Example 1: Form Pre-population
function populateForm() {
const urlParams = new URLSearchParams(window.location.search);
// Find form elements and populate them
const form = document.getElementById('myForm');
// Get all form inputs
const inputs = form.querySelectorAll('input, select, textarea');
inputs.forEach(input => {
const paramName = input.name || input.id;
const value = urlParams.get(paramName);
if (value !== null) {
if (input.type === 'checkbox' || input.type === 'radio') {
input.checked = input.value === value;
} else {
input.value = value;
}
}
});
}
// Call when DOM is ready
document.addEventListener('DOMContentLoaded', populateForm);
Example 2: Search Filter Implementation
class SearchFilter {
constructor() {
this.urlParams = new URLSearchParams(window.location.search);
this.filters = {};
this.initializeFilters();
this.setupEventListeners();
}
initializeFilters() {
// Extract filters from URL
for (const [key, value] of this.urlParams.entries()) {
this.filters[key] = value;
}
// Apply filters to UI
this.applyFilters();
}
applyFilters() {
// Update UI based on current filters
Object.keys(this.filters).forEach(key => {
const element = document.querySelector(`[data-filter="${key}"]`);
if (element) {
element.value = this.filters[key];
}
});
}
updateUrl() {
// Update URL with current filters
const newUrl = new URL(window.location);
newUrl.search = '';
Object.keys(this.filters).forEach(key => {
if (this.filters[key]) {
newUrl.searchParams.set(key, this.filters[key]);
}
});
// Update URL without reloading page
window.history.pushState({}, '', newUrl);
}
setupEventListeners() {
// Listen for filter changes
document.querySelectorAll('[data-filter]').forEach(element => {
element.addEventListener('change', (e) => {
const filterKey = e.target.dataset.filter;
this.filters[filterKey] = e.target.value;
this.updateUrl();
});
});
}
}
// Initialize the search filter
const searchFilter = new SearchFilter();
Example 3: Analytics and Tracking
class AnalyticsTracker {
constructor() {
this.urlParams = new URLSearchParams(window.location.search);
this.init();
}
init() {
// Track source/medium from UTM parameters
this.trackUTMParams();
// Track campaign parameters
this.trackCampaignParams();
// Track custom parameters
this.trackCustomParams();
}
trackUTMParams() {
const utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'];
utmParams.forEach(param => {
const value = this.urlParams.get(param);
if (value) {
// Send to analytics service
this.sendToAnalytics('utm_parameter', {
parameter: param,
value: value
});
}
});
}
trackCampaignParams() {
const campaignParams = ['gclid', 'fbclid', 'msclkid'];
campaignParams.forEach(param => {
const value = this.urlParams.get(param);
if (value) {
this.sendToAnalytics('tracking_parameter', {
parameter: param,
value: value
});
}
});
}
trackCustomParams() {
// Track any custom parameters that start with 'track_'
for (const [key, value] of this.urlParams.entries()) {
if (key.startsWith('track_')) {
this.sendToAnalytics('custom_parameter', {
parameter: key,
value: value
});
}
}
}
sendToAnalytics(event, data) {
// Implementation depends on your analytics service
console.log('Analytics Event:', event, data);
// Example: Google Analytics 4
if (typeof gtag === 'function') {
gtag('event', event, data);
}
}
}
// Initialize analytics tracking
const analyticsTracker = new AnalyticsTracker();
Sources
- MDN Web Docs - URLSearchParams
- Can I Use - URLSearchParams
- ECMAScript 2017 Specification - URLSearchParams
- Web.dev - Working with URLs in JavaScript
- Google Developers - Best Practices for URLs
Conclusion
The native URLSearchParams API is the recommended approach for extracting query string parameters in modern JavaScript applications, providing a clean, standardized interface without requiring any external dependencies. For older browser support, manual parsing with regular expressions or string manipulation methods can be implemented as alternatives. When working with query strings, remember to properly handle URL encoding/decoding and consider edge cases like multiple parameters with the same key. Modern web applications should leverage these native methods to build robust URL parameter handling that works across different environments while maintaining clean, maintainable code.