urlSearchParams.append()
Adds another name-value pair to a query string, keeping any existing pairs with the same name.
urlSearchParams.append(name, value)- Added in Node.js v7.5.0, v6.13.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$name | string | The parameter name. Non-string values are coerced to a string. |
$value | string | The parameter value. Non-string values are coerced to a string. |
Return value
undefinedNothing; the pair is added to the end of the parameter list.
Errors
Throws a TypeError when fewer than two arguments are supplied.
append() pushes a new pair onto the end of the list. It never inspects what is already there, so calling it twice with the same name produces two entries and serializes to name=a&name=b.
append vs set
This is the distinction that matters. set(name, value) replaces every existing pair with that name with a single one; append(name, value) adds one more. Use append for genuinely repeatable parameters — tags, filters, ids, multi-select form fields — and set for single-valued ones such as page or sort.
The subtle part: set on an existing name keeps that name's original position in the list, while append always adds at the end. That only shows up when you care about ordering, for example when building a canonical cache key — call sort() before serializing if you do.
What trips people up
Calling append inside a loop that runs more than once — a retry, a middleware that fires twice — quietly doubles parameters instead of overwriting them. Many APIs then read only the first value and behave as if your update never happened. If a parameter must be unique, use set.
Both arguments are coerced to strings, so append('ids', [1, 2]) stores '1,2' as one value rather than two entries.
Example
When to use it
- Build a multi-select filter such as status=open&status=pending
- Add several tag values to an API request from an array
- Accumulate id parameters for a batch fetch endpoint
- Preserve every value when copying parameters from one URL to another
Frequently asked questions
What is the difference between append and set on URLSearchParams?
append adds another pair and keeps existing ones with the same name, while set removes all existing pairs with that name and inserts a single one. Use append for repeatable filters and set for parameters that must be unique.
How do I pass an array as a query parameter?
Call append once per element so the name repeats, for example status=open&status=pending. Passing the array directly coerces it to a comma-joined string, which most APIs will not parse as a list.
Does append return the URLSearchParams for chaining?
No, it returns undefined, so calls cannot be chained. Call it once per pair, or build the whole collection with the array-of-pairs constructor instead.
More examples
Turning an array into repeated parameters
Appending through url.searchParams rewrites url.href on every call. status repeats three times while per_page is set once — the shape most REST APIs expect for a multi-value filter.
const url = new URL('https://api.example.com/issues');
const statuses = ['open', 'pending', 'blocked'];
for (const s of statuses) url.searchParams.append('status', s);
url.searchParams.set('per_page', '50');
console.log(url.href);
console.log(url.searchParams.getAll('status'));Why appending twice is a bug
The append version produces api_version=2&api_version=2, which some servers reject outright and others silently take the first of. set is idempotent, which is what you want for any helper that might run more than once.
function addApiVersion(params) {
params.append('api_version', '2');
}
const appended = new URLSearchParams('q=node');
addApiVersion(appended);
addApiVersion(appended);
console.log('append twice:', appended.toString());
function setApiVersion(params) {
params.set('api_version', '2');
}
const assigned = new URLSearchParams('q=node');
setApiVersion(assigned);
setApiVersion(assigned);
console.log('set twice:', assigned.toString());Copying parameters between URLs without losing duplicates
Iterating yields one entry per pair, so appending each preserves both tag values. Using set inside the same loop would have kept only 'b'.
const from = new URL('https://old.example.com/search?tag=a&tag=b&page=2');
const to = new URL('https://new.example.com/search');
for (const [name, value] of from.searchParams) {
to.searchParams.append(name, value);
}
console.log(to.href);
console.log('tags carried over:', to.searchParams.getAll('tag'));
Discussion