URLs often carry useful data in their query string: a search term, a page number, or a filter. In JavaScript, the built-in URLSearchParams API makes it easier to read and update those parameters without manually splitting strings or encoding values. This tutorial covers common operations, encoding behavior, and mistakes to avoid.
Key takeaways
- Use
URLSearchParamsto read and modify query-string parameters. - Use
getAll()when a parameter may appear more than once;get()returns only its first value. - Use the
URLobject when you need to preserve and update the rest of a URL. set()replaces values for a key, whileappend()adds another value.- Query parameters are user-controlled input, so validate values before relying on them.
Create URLSearchParams and read values
You can construct URLSearchParams from a query string. The initial ? is optional:
const params = new URLSearchParams("?q=javascript&page=2");
console.log(params.get("q")); // "javascript"
console.log(params.get("page")); // "2"
console.log(params.has("q")); // true
console.log(params.has("sort")); // false
Values returned by get() are strings. Convert them when your application needs a number, and validate the result rather than assuming it is usable:
const params = new URLSearchParams("page=3");
const rawPage = params.get("page");
const page = Number(rawPage);
if (rawPage !== null && Number.isInteger(page) && page > 0) {
console.log(`Show page ${page}`);
} else {
console.log("Use the default page");
}
get() returns null if the key is absent. An empty value, such as ?q=, is different: get("q") returns an empty string.
Read parameters from a full URL or the current page
URLSearchParams handles a query string, not an entire URL. For a complete URL, create a URL object and access its searchParams property:
const url = new URL("https://example.com/products?category=books&page=2");
console.log(url.searchParams.get("category")); // "books"
console.log(url.searchParams.get("page")); // "2"
In a browser, use the current page URL's search parameters:
const params = new URLSearchParams(window.location.search);
const searchTerm = params.get("q");
console.log(searchTerm);
For a relative URL such as /products?page=2, provide a base when constructing a URL:
const url = new URL("/products?page=2", window.location.origin);
console.log(url.searchParams.get("page")); // "2"
For a quick visual check of a query string, you can also use the TidyURLs query editor. Treat any values you inspect there, or receive in your application, as input that may need validation.
Handle repeated parameters
A query string can contain the same key more than once, for example ?tag=javascript&tag=web. get() returns the first value; use getAll() to retrieve every value:
const params = new URLSearchParams("tag=javascript&tag=web");
console.log(params.get("tag")); // "javascript"
console.log(params.getAll("tag")); // ["javascript", "web"]
This distinction matters when a page supports multiple selections or when an API expects repeated keys. Check the receiving application's expected format before choosing between repeated parameters and a single delimited value.
Modify parameters with set, append, and delete
Use set() to create a key or replace its existing values. If that key occurs multiple times, set() leaves one value for it. Use append() when you intentionally want an additional occurrence. Use delete() to remove a key:
const params = new URLSearchParams("tag=javascript&tag=web&page=1");
params.set("page", "2");
params.append("tag", "accessibility");
params.delete("page");
console.log(params.toString());
// "tag=javascript&tag=web&tag=accessibility"
To update a full URL while preserving its other components, work through URL.searchParams:
const url = new URL("https://example.com/search?q=old&page=1");
url.searchParams.set("q", "URL parameters");
url.searchParams.set("page", "2");
console.log(url.href);
// "https://example.com/search?q=URL+parameters&page=2"
URLSearchParams handles query-string serialization for you. If you need to inspect the resulting encoding, toString() returns the serialized query without a leading ?.
Encode and serialize values safely
Pass unencoded values to set() or append() and let the API serialize them. Avoid encoding a value first with encodeURIComponent(), which can lead to double encoding:
const params = new URLSearchParams();
params.set("q", "red shoes & socks");
console.log(params.toString());
// "q=red+shoes+%26+socks"
When reading values, URLSearchParams decodes them. In form-style query serialization, spaces are represented as +; encoded plus signs are represented differently. Do not treat a query string's raw spelling as its decoded value.
You can also provide an object of simple string values:
const params = new URLSearchParams({
q: "javascript",
page: "2"
});
console.log(params.toString()); // "q=javascript&page=2"
If a value is an array, this object form does not automatically create repeated keys for each array element. Use append() when repeated keys are required.
A practical workflow for updating a link
Use this pattern when building a link from an existing URL:
- Parse the URL with
new URL()and provide a base if it is relative. - Read existing values through
url.searchParams. - Validate values that came from users or external sources.
- Update parameters with
set(),append(), ordelete()as appropriate. - Use
url.hreffor the complete serialized URL.
function buildSearchUrl(input, baseUrl) {
const url = new URL(input, baseUrl);
const pageValue = url.searchParams.get("page");
const page = Number(pageValue);
if (pageValue !== null && (!Number.isInteger(page) || page < 1)) {
url.searchParams.delete("page");
}
url.searchParams.set("source", "site-search");
return url.href;
}
const result = buildSearchUrl(
"/search?q=books&page=2",
"https://example.com"
);
console.log(result);
This example normalizes an invalid page value and adds a source parameter. In a real application, adapt validation and allowed values to the requirements of the feature.
Common mistakes and pitfalls
Passing a complete URL to URLSearchParams
new URLSearchParams("https://example.com/?q=test") does not parse the URL into its components. Parse the complete URL with new URL() first, then use url.searchParams.
Assuming all values are numbers or booleans
Query parameters are text. Convert and validate values explicitly. For booleans, define which strings your application accepts, such as "true" and "false", instead of relying on JavaScript truthiness.
Losing repeated values with set()
set() replaces the existing values for a key. Use append() to add another value, and getAll() to read repeated values.
Comparing serialized strings without considering normalization
Different query-string spellings can represent the same decoded value, and serialization may normalize their encoding. Compare parsed names and values when that is the intended comparison rather than assuming the raw strings will be identical.
Treating URL parsing as input validation
Parsing a query parameter does not establish that it is safe, authorized, or appropriate for a particular operation. Validate against the application's expected type, range, and allowed values. If a value is later used in a sensitive operation, apply the security controls required for that operation as well.
Conclusion
URLSearchParams provides a straightforward way to read, serialize, and modify query parameters in JavaScript. Use URL for complete URLs, choose getAll() or append() when repeated keys matter, and validate values before using them. These habits make query-string handling clearer and less error-prone.
