npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

faster-qs

v0.3.0

Published

Fast, zero-dependency query string parser with most features of `qs`

Readme

faster-qs

Fast query string parser with nested keys and most features of qs. Zero dependencies.

Install

npm install faster-qs

Usage

import parse from 'faster-qs'

parse('a=1&b=2&c[]=3&c[]=4&d[a][b][c]=5')
// { a: '1', b: '2', c: ['3', '4'], d: { a: { b: { c: '5' } } } }

parse('user[name]=John+Doe&tags[0]=x&tags[1]=y&q=%E4%B8%AD%E6%96%87')
// { user: { name: 'John Doe' }, tags: ['x', 'y'], q: '中文' }

// Nesting is limited by `depth` (default 5); the remainder becomes a literal key
parse('a[b][c][d][e][f][g]=1')
// { a: { b: { c: { d: { e: { f: { '[g]': '1' } } } } } } }

// Explicit indices above `arrayLimit` (default 20) are stored as object keys
parse('a[21]=x')
// { a: { '21': 'x' } }
parse('a[21]=x', 5, Infinity)
// { a: [ <21 empty items>, 'x' ] }
parse(str: string, depth?: number, arrayLimit?: number): ParsedObject

TypeScript definitions are included.

Behaviour

  • Repeated keys become arrays (a=1&a=2{ a: ['1', '2'] }); a[] appends, a[2] sets an index.
  • An index larger than arrayLimit turns the container into a plain object, like qs. This keeps a crafted a[4294967294]=1 from allocating a huge sparse array.
  • + decodes to a space and %XX sequences decode as UTF-8. Malformed sequences are kept as-is instead of throwing.
  • Keys named after Object.prototype properties (__proto__, constructor, toString, …) are dropped at every level, so the result can never pollute prototypes.
  • Non-string input returns {}.

Benchmark

> node benchmark/index.mjs

cpu: AMD RYZEN AI MAX+ 395 w/ Radeon 8060S
runtime: node v24.13.0 (x64-linux)

benchmark                         time (avg)             (min … max)       p75       p99      p999
-------------------------------------------------------------------- -----------------------------
• simple
-------------------------------------------------------------------- -----------------------------
faster-qs                      64.86 ns/iter      (60.3 ns … 270 ns)  63.18 ns  76.49 ns    122 ns
qs                             1'260 ns/iter   (1'251 ns … 1'441 ns)  1'258 ns  1'408 ns  1'441 ns
fast-querystring (no nested)   48.24 ns/iter     (43.44 ns … 106 ns)  46.81 ns   59.5 ns  80.87 ns

summary for simple
  faster-qs
   1.34x slower than fast-querystring (no nested)
   19.43x faster than qs

• array
-------------------------------------------------------------------- -----------------------------
faster-qs                        167 ns/iter       (157 ns … 348 ns)    172 ns    193 ns    316 ns
qs                             2'278 ns/iter   (2'254 ns … 2'458 ns)  2'276 ns  2'458 ns  2'458 ns
fast-querystring (no nested)     139 ns/iter       (128 ns … 296 ns)    145 ns    165 ns    222 ns

summary for array
  faster-qs
   1.2x slower than fast-querystring (no nested)
   13.61x faster than qs

• deep object
-------------------------------------------------------------------- -----------------------------
faster-qs                      1'237 ns/iter   (1'218 ns … 1'548 ns)  1'236 ns  1'339 ns  1'548 ns
qs                             6'460 ns/iter   (6'402 ns … 6'908 ns)  6'461 ns  6'859 ns  6'908 ns
fast-querystring (no nested)     416 ns/iter       (406 ns … 473 ns)    422 ns    448 ns    473 ns

summary for deep object
  faster-qs
   2.97x slower than fast-querystring (no nested)
   5.22x faster than qs

• indexed array
-------------------------------------------------------------------- -----------------------------
faster-qs                        774 ns/iter     (748 ns … 1'158 ns)    778 ns  1'022 ns  1'158 ns
qs                             4'426 ns/iter   (4'395 ns … 4'599 ns)  4'434 ns  4'548 ns  4'599 ns
fast-querystring (no nested)     336 ns/iter       (324 ns … 496 ns)    340 ns    363 ns    496 ns

summary for indexed array
  faster-qs
   2.3x slower than fast-querystring (no nested)
   5.72x faster than qs

• form
-------------------------------------------------------------------- -----------------------------
faster-qs                        822 ns/iter     (798 ns … 1'084 ns)    824 ns  1'017 ns  1'084 ns
qs                             4'087 ns/iter   (4'060 ns … 4'407 ns)  4'090 ns  4'379 ns  4'407 ns
fast-querystring (no nested)     470 ns/iter       (456 ns … 767 ns)    474 ns    537 ns    767 ns

summary for form
  faster-qs
   1.75x slower than fast-querystring (no nested)
   4.97x faster than qs

• typical url
-------------------------------------------------------------------- -----------------------------
faster-qs                        324 ns/iter       (310 ns … 501 ns)    329 ns    351 ns    501 ns
qs                             2'476 ns/iter   (2'445 ns … 2'916 ns)  2'477 ns  2'845 ns  2'916 ns
fast-querystring (no nested)     320 ns/iter       (313 ns … 553 ns)    320 ns    345 ns    553 ns

summary for typical url
  faster-qs
   1.01x slower than fast-querystring (no nested)
   7.65x faster than qs

• encoded
-------------------------------------------------------------------- -----------------------------
faster-qs                        557 ns/iter       (528 ns … 845 ns)    566 ns    620 ns    845 ns
qs                             1'747 ns/iter   (1'727 ns … 1'859 ns)  1'753 ns  1'844 ns  1'859 ns
fast-querystring (no nested)     654 ns/iter       (640 ns … 803 ns)    657 ns    732 ns    803 ns

summary for encoded
  faster-qs
   1.17x faster than fast-querystring (no nested)
   3.13x faster than qs

License

MIT. The percent-decoder is derived from fast-decode-uri-component and the pair scanner from fast-querystring, both MIT.