A comprehensive polyfill for JavaScript's URLSearchParams class with cross-browser compatibility
npx @tessl/cli install tessl/npm-url-search-params-polyfill@8.2.0A comprehensive polyfill for JavaScript's URLSearchParams class that provides consistent behavior across all browsers (including IE8+) and Node.js environments. This library intelligently detects existing browser support and only polyfills when necessary, while maintaining full feature parity with the native implementation.
npm install url-search-params-polyfillFor ES2015+ and Babel:
import 'url-search-params-polyfill';For ES5/CommonJS:
require('url-search-params-polyfill');For browser environments:
<script src="index.js"></script>Note: This polyfill modifies the global URLSearchParams object. After importing/loading, use URLSearchParams directly as you would with the native implementation.
// Import the polyfill (global URLSearchParams becomes available)
require('url-search-params-polyfill');
// Create from empty
const params1 = new URLSearchParams();
// Create from string
const params2 = new URLSearchParams('id=1&name=hello&active=true');
// Create from object
const params3 = new URLSearchParams({ id: 1, name: 'hello', active: true });
// Basic operations
params1.append('key', 'value');
params1.set('id', '123');
console.log(params1.get('id')); // '123'
console.log(params1.toString()); // 'key=value&id=123'The polyfill uses intelligent feature detection to determine the level of native URLSearchParams support:
Key features include proper encoding/decoding of special characters, support for multiple values per key, and iterator protocol implementation for modern JavaScript compatibility.
Creates a new URLSearchParams instance from various input formats.
/**
* Creates a new URLSearchParams instance
* @param {string|object|URLSearchParams|Array<[string, string]>} init - Initial data
*/
new URLSearchParams(init?)Constructor Variations:
// Empty instance
new URLSearchParams()
// From query string (with or without leading "?")
new URLSearchParams(string)
// From plain object
new URLSearchParams(object)
// From another URLSearchParams instance (copy constructor)
new URLSearchParams(URLSearchParams)
// From sequence of key-value pairs
new URLSearchParams(Array<[string, string]>)Usage Examples:
// Empty
const empty = new URLSearchParams();
// From string
const fromString = new URLSearchParams('?id=1&name=test');
const fromStringNoQ = new URLSearchParams('id=1&name=test');
// From object
const fromObject = new URLSearchParams({ id: 1, name: 'test', active: true });
// From another instance
const copy = new URLSearchParams(fromString);
// From sequence
const fromArray = new URLSearchParams([['id', '1'], ['name', 'test']]);Appends a key/value pair as a new search parameter.
/**
* Appends a key/value pair as a new search parameter
* @param {string} name - Parameter name
* @param {string} value - Parameter value
* @returns {void}
*/
append(name, value)Deletes all occurrences of the given search parameter.
/**
* Deletes all occurrences of the given search parameter
* @param {string} name - Parameter name to delete
* @returns {void}
*/
delete(name)Sets the value associated with a search parameter, replacing all existing values.
/**
* Sets the value associated with a search parameter
* @param {string} name - Parameter name
* @param {string} value - Parameter value
* @returns {void}
*/
set(name, value)Usage Examples:
const params = new URLSearchParams();
// Add multiple values for same key
params.append('id', '1');
params.append('id', '2');
console.log(params.toString()); // 'id=1&id=2'
// Replace all values for a key
params.set('id', '3');
console.log(params.toString()); // 'id=3'
// Delete all values for a key
params.delete('id');
console.log(params.toString()); // ''Returns the first value associated with the given search parameter.
/**
* Returns the first value associated with the given search parameter
* @param {string} name - Parameter name
* @returns {string|null} First value or null if not found
*/
get(name)Returns all values associated with the given search parameter.
/**
* Returns all values associated with the given search parameter
* @param {string} name - Parameter name
* @returns {Array<string>} Array of all values (empty array if not found)
*/
getAll(name)Returns whether the given search parameter exists.
/**
* Returns whether the given search parameter exists
* @param {string} name - Parameter name
* @returns {boolean} True if parameter exists
*/
has(name)Usage Examples:
const params = new URLSearchParams('id=1&id=2&name=test');
console.log(params.get('id')); // '1' (first value)
console.log(params.getAll('id')); // ['1', '2'] (all values)
console.log(params.has('name')); // true
console.log(params.has('age')); // false
console.log(params.get('age')); // nullReturns a query string suitable for use in a URL.
/**
* Returns a query string suitable for use in a URL
* @returns {string} Query string representation
*/
toString()Usage Examples:
const params = new URLSearchParams({ name: 'hello world', active: true });
console.log(params.toString()); // 'name=hello+world&active=true'
// Use in URLs
const url = 'https://api.example.com/search?' + params.toString();Executes a callback function for each name/value pair.
/**
* Executes a callback function for each name/value pair
* @param {function} callback - Function to execute for each pair
* @param {object} thisArg - Optional object to use as 'this' in callback
* @returns {void}
*/
forEach(callback, thisArg?)Callback signature:
/**
* @param {string} value - Parameter value
* @param {string} key - Parameter name
* @param {URLSearchParams} searchParams - The URLSearchParams instance
*/
callback(value, key, searchParams)Sorts all name-value pairs by their names.
/**
* Sorts all name-value pairs by their names
* @returns {void}
*/
sort()Usage Examples:
const params = new URLSearchParams('z=3&a=1&b=2&a=4');
// Iterate over all pairs
params.forEach((value, key) => {
console.log(`${key}: ${value}`);
});
// Output: z: 3, a: 1, b: 2, a: 4
// Sort parameters alphabetically
params.sort();
console.log(params.toString()); // 'a=1&a=4&b=2&z=3'Returns an iterator for all parameter names.
/**
* Returns an iterator for all parameter names
* @returns {Iterator<string>} Iterator of parameter names
*/
keys()Returns an iterator for all parameter values.
/**
* Returns an iterator for all parameter values
* @returns {Iterator<string>} Iterator of parameter values
*/
values()Returns an iterator for all name-value pairs.
/**
* Returns an iterator for all name-value pairs
* @returns {Iterator<[string, string]>} Iterator of [name, value] pairs
*/
entries()Makes URLSearchParams iterable with for...of loops (same as entries()).
/**
* Symbol.iterator implementation for for...of loops
* @returns {Iterator<[string, string]>} Iterator of [name, value] pairs
*/
[Symbol.iterator]()Usage Examples:
const params = new URLSearchParams('a=1&b=2&a=3');
// Iterate over keys
for (const key of params.keys()) {
console.log(key); // 'a', 'b', 'a'
}
// Iterate over values
for (const value of params.values()) {
console.log(value); // '1', '2', '3'
}
// Iterate over entries
for (const [key, value] of params.entries()) {
console.log(`${key}=${value}`); // 'a=1', 'b=2', 'a=3'
}
// Direct iteration (same as entries)
for (const [key, value] of params) {
console.log(`${key}=${value}`); // 'a=1', 'b=2', 'a=3'
}Returns the total number of search parameter entries.
/**
* Total number of search parameter entries
* @type {number}
*/
readonly sizeUsage Examples:
const params = new URLSearchParams('a=1&b=2&a=3');
console.log(params.size); // 3 (counts all entries, including duplicates)
const empty = new URLSearchParams();
console.log(empty.size); // 0Boolean property indicating this is the polyfill implementation.
/**
* Always true - indicates this is the polyfill implementation
* @type {boolean}
*/
URLSearchParams.prototype.polyfillUsage Examples:
require('url-search-params-polyfill');
const params = new URLSearchParams();
console.log(params.polyfill); // true (when polyfill is active)/**
* URLSearchParams constructor options
*/
type URLSearchParamsInit =
| string
| object
| URLSearchParams
| Array<[string, string]>
| undefined;
/**
* Callback function for forEach method
*/
type ForEachCallback = (
value: string,
key: string,
searchParams: URLSearchParams
) => void;
/**
* Iterator types
*/
type KeyIterator = Iterator<string>;
type ValueIterator = Iterator<string>;
type EntryIterator = Iterator<[string, string]>;The polyfill may throw the following errors:
/**
* Thrown when sequence initializer contains invalid elements
*/
TypeError: "Failed to construct 'URLSearchParams': Sequence initializer must only contain pair elements"Occurs when: Array elements are not 2-element arrays:
// This will throw
new URLSearchParams([['key1'], ['key2', 'value2', 'extra']]);
// This works
new URLSearchParams([['key1', 'value1'], ['key2', 'value2']]);/**
* Thrown when size getter is called incorrectly
*/
TypeError: "Illegal invocation at URLSearchParams.invokeGetter"Occurs when: Accessing size property on the prototype directly:
// This will throw
console.log(URLSearchParams.prototype.size);
// This works
const params = new URLSearchParams();
console.log(params.size);When using this polyfill with the fetch API in browsers that support fetch but not URLSearchParams (Edge 14-16, Chrome 40-48, Opera 27-35), you may need to manually set the Content-Type header:
function safeFetch(url, options = {}) {
const { headers = {}, body } = options;
const finalHeaders = headers instanceof Headers ? headers : new Headers(headers);
if (body instanceof URLSearchParams) {
finalHeaders.set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
}
return fetch(url, { ...options, headers: finalHeaders, body });
}The polyfill correctly handles encoding/decoding of special characters:
+ in the query string+) in values are properly encoded as %2B!, ', (, ), ~ are percent-encoded&) in values are properly encoded as %26