URLs often carry useful information in their query string: a search term, a page number, a filter, or a campaign tag. In JavaScript, URLSearchParams gives you a built-in way to read and change those values without manually splitting strings or encoding each parameter yourself. This tutorial walks through common operations, duplicate parameters, encoding, and practical browser examples.
Key takeaways
- Use the
URLconstructor to work with a complete URL and access its.searchParamsproperty. - Use
get()to read one value,getAll()to read repeated values, andhas()to check whether a parameter exists. - Use
set()to replace a parameter's values,append()to add another value, anddelete()to remove values. URLSearchParamshandles query-string encoding and serialization, but it does not validate input or make sensitive data safe to place in a URL.
Start with a URL object
URLSearchParams represents the parameters in a URL's query string. The simplest way to use it with a full URL is to construct a URL and access .searchParams:
const url = new URL("https://example.com/products?category=tea&page=2");
const params = url.searchParams;
console.log(params.get("category")); // "tea"
console.log(params.get("page")); // "2"
Values returned by get() are strings. Convert them when your code needs a number, and validate the result before using it:
const pageValue = Number(params.get("page"));
const page = Number.isInteger(pageValue) && pageValue > 0 ? pageValue : 1;
console.log(page); // 2
A URL can be relative when you supply a base URL. This is useful in browser code:
const url = new URL("/search?q=chai", window.location.origin);
console.log(url.searchParams.get("q")); // "chai"
In Node.js, provide an absolute URL or a base explicitly; there is no browser window.location by default.
Read query parameters
Get a value or check for a parameter
get(name) returns the first matching value, or null when the parameter is absent. has(name) checks whether at least one matching parameter exists.
const params = new URL("https://example.com/search?q=chai&page=2").searchParams;
if (params.has("q")) {
console.log(params.get("q")); // "chai"
}
console.log(params.get("sort")); // null
A missing parameter and an empty parameter are different:
const params = new URL("https://example.com/search?q=").searchParams;
console.log(params.has("q")); // true
console.log(params.get("q")); // ""
If your application treats an empty value as missing, check for both null and the empty string.
Handle repeated parameters
A query string can contain the same name more than once, such as ?tag=javascript&tag=web. get() returns the first value; use getAll() when all values matter.
const params = new URL("https://example.com/?tag=javascript&tag=web").searchParams;
console.log(params.get("tag")); // "javascript"
console.log(params.getAll("tag")); // ["javascript", "web"]
This pattern is useful for multi-select filters. Do not assume a parameter is unique unless your application defines and enforces that rule.
Modify URL parameters
Set or replace a value
set(name, value) creates the parameter if it does not exist. If it already appears multiple times, set() replaces those entries with one value.
const url = new URL("https://example.com/products?category=tea&page=1");
url.searchParams.set("page", "2");
url.searchParams.set("sort", "price");
console.log(url.toString());
// https://example.com/products?category=tea&page=2&sort=price
Pass numbers as values when convenient; they are converted to strings. For clarity, the example uses string values explicitly.
Append another value
Use append() when you intentionally want another occurrence of a parameter, such as adding a selected tag:
const url = new URL("https://example.com/search?tag=javascript");
url.searchParams.append("tag", "web");
console.log(url.searchParams.getAll("tag"));
// ["javascript", "web"]
Unlike set(), append() does not replace existing values.
Delete a parameter
delete(name) removes every entry with that name:
const url = new URL("https://example.com/search?q=chai&page=2");
url.searchParams.delete("page");
console.log(url.toString()); // https://example.com/search?q=chai
Work with a query string by itself
If you already have only the query string, pass it to URLSearchParams. A leading ? is optional. This constructor expects query data, not a complete URL.
const params = new URLSearchParams("?q=masala%20chai&page=2");
console.log(params.get("q")); // "masala chai"
console.log(params.toString());
To inspect or edit a full link before using it, you can edit query parameters with the TidyURLs query editor. For JavaScript code, prefer the URL APIs when you need to make changes programmatically.
Encoding and serialization
URLSearchParams encodes values when it serializes them with toString() or when you assign the parameters back to a URL. This avoids manually concatenating raw values into a query string.
const params = new URLSearchParams();
params.set("q", "chai & snacks");
params.set("city", "मुंबई");
console.log(params.toString());
// q=chai+%26+snacks&city=%E0%A4%AE%E0%A5%81%E0%A4%82%E0%A4%AC%E0%A4%88
When a URL is serialized, spaces in form-style query data are represented as +. Reading the parameters decodes the values again. The exact serialized form can differ from the original spelling of an equivalent query string, so avoid comparing raw query strings when you mean to compare parameter values.
Another common source of confusion is + in a query value. In form-style query parsing, + is interpreted as a space. If you need a literal plus sign, add the value through URLSearchParams so it is encoded correctly:
const params = new URLSearchParams();
params.set("code", "A+B");
console.log(params.toString()); // code=A%2BB
console.log(params.get("code")); // "A+B"
Update the browser's current URL
Changing a URL object changes that object, not the browser's address bar. To update the address without a full page navigation, use the History API. This example keeps the current path and hash while changing a query parameter:
const url = new URL(window.location.href);
url.searchParams.set("page", "2");
window.history.replaceState({}, "", url);
replaceState() replaces the current history entry. Use pushState() instead if the change should create a new entry that users can return to with the Back button. If your application uses a client-side router, follow that router's navigation API so its state stays in sync.
Common mistakes and pitfalls
- Treating values as numbers automatically:
get()returns a string. Convert and validate values before using them in calculations or application logic. - Using
get()for a multi-value parameter: It returns only the first matching entry. UsegetAll()when duplicates are meaningful. - Confusing
set()withappend():set()replaces existing values of that name;append()adds another one. - Passing a full URL to
URLSearchParams: It parses query data, not the URL's path and host. Usenew URL(fullUrl).searchParamsfor a complete link. - Building query strings by concatenation: Raw values may contain spaces, ampersands, or non-ASCII characters. Set parameters through the API rather than assembling encoded strings by hand.
- Assuming edits update the address bar: They do not. Update browser history explicitly if that is the intended behavior.
- Putting secrets in query parameters: URLs can appear in browser history, logs, copied links, and other places. Do not use query strings as a place for passwords or other sensitive values.
A practical workflow
When reading or updating a query string in an application:
- Create a
URLfrom the complete link, providing a base if the input is relative. - Read parameters with
get(),getAll(), orhas()according to whether duplicates are allowed. - Validate values and apply sensible defaults; parsing a URL does not validate your application's rules.
- Make changes with
set(),append(), ordelete(). - Use the resulting URL as needed, and update browser history only when that is part of the user experience.
Conclusion
URLSearchParams makes query-string work safer and clearer than manual string splitting. Pair it with the URL constructor for full links, remember that values are strings, and choose between set() and append() based on whether duplicates should be replaced or retained. Validate data for your application and keep sensitive information out of URLs.
