Query string parsing

URLSearchParams and the URL constructor

Baseline widely available

URLSearchParams reads and writes query strings, handles percent-encoding in both directions, and gives you get, getAll, set, append and delete. new URL() does the same job for a whole address, so the hostname, the pathname and the search params come apart without a regular expression. Both have been in every browser since 2017 and in Node for as long, and both are what these libraries call underneath once you strip the option handling.

When this applies

Reading or building a query string, or pulling a URL apart.

The native approach

const url = new URL("/search?tag=css&tag=html&page=2", location.origin);

url.searchParams.getAll("tag"); // ["css", "html"]
url.searchParams.get("page"); // "2", a string
url.searchParams.set("page", "3");

// Build one from scratch.
new URLSearchParams({ q: "scroll snap", page: "1" }).toString();
// "q=scroll+snap&page=1"

MDN reference

When the dependency is still right

An answer that always says "the platform covers it" is worse than no answer. These are the cases where this one does not hold.

  • You parse nested objects or arrays from bracket syntax such as filter[status][]=open. That is the reason qs exists, and URLSearchParams has no equivalent.
  • You round-trip typed data through the query string. Every value comes back as a string, so numbers, booleans and null need converting at each read site.
  • You depend on the library's options: a custom array format, a configurable delimiter, sorted output, or comma-separated values parsed into arrays.
  • You parse untrusted input on a server and rely on qs's depth and parameterLimit guards against prototype pollution. URLSearchParams applies no limits of its own.
  • You need Node's legacy querystring semantics, where a repeated key gives an array rather than needing getAll().
  • Your support target reaches below Chrome 49, Firefox 29 or Safari 10.1. The URL constructor arrived earlier than URLSearchParams, so a browser having one is not proof it has the other.

Packages this covers