@smithy/querystring-builder vs qs vs query-string vs querystring-es3 vs url-search-params-polyfill
Parsing and Building URL Query Strings in JavaScript
@smithy/querystring-builderqsquery-stringquerystring-es3url-search-params-polyfillSimilar Packages:

Parsing and Building URL Query Strings in JavaScript

These libraries handle converting URL query parameters into JavaScript objects and vice versa. They differ in how they handle nested data, encoding standards, and legacy browser support. Some are general-purpose tools, while others are polyfills for native APIs or specific to cloud SDKs.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
@smithy/querystring-builder032716.8 kB94a month agoApache-2.0
qs08,940375 kB7625 days agoBSD-3-Clause
query-string06,90959.3 kB322 days agoMIT
querystring-es3019-212 years ago-
url-search-params-polyfill059917.4 kB33 years agoMIT

Parsing and Building URL Query Strings: A Technical Deep Dive

Handling URL query parameters is a common task in web development, but the tools available vary widely in capability and intent. Packages like qs, query-string, and @smithy/querystring-builder solve similar problems but target different environments and use cases. Meanwhile, querystring-es3 and url-search-params-polyfill address legacy compatibility. Let's compare how they handle real-world scenarios.

📥 Parsing Query Parameters

Reading query strings from a URL and turning them into usable objects is the first step in many workflows. The approach differs based on whether you need nested data support or just simple key-value pairs.

qs provides deep parsing capabilities, turning nested strings into objects automatically.

import qs from 'qs';

const obj = qs.parse('user[name]=john&user[age]=30');
// Result: { user: { name: 'john', age: '30' } }

query-string parses flat structures by default but can handle arrays with options.

import queryString from 'query-string';

const obj = queryString.parse('user=john&age=30');
// Result: { user: 'john', age: '30' }

@smithy/querystring-builder does not support parsing.

// @smithy/querystring-builder
// No parse method available. This package is build-only.
// You must use a different library for parsing input.

querystring-es3 mimics the old Node.js core module behavior.

import querystring from 'querystring-es3';

const obj = querystring.parse('user=john&age=30');
// Result: { user: 'john', age: '30' }

url-search-params-polyfill enables the native API in old environments.

import 'url-search-params-polyfill';

const params = new URLSearchParams('user=john&age=30');
const obj = Object.fromEntries(params.entries());
// Result: { user: 'john', age: '30' }

📤 Building Query Strings

Turning JavaScript objects back into a URL-safe string is equally important, especially for generating links or API requests. Encoding rules vary slightly between tools.

qs handles complex objects and arrays with precision.

import qs from 'qs';

const str = qs.stringify({ user: { name: 'john' } });
// Result: 'user%5Bname%5D=john'

query-string creates clean, readable strings suitable for browsers.

import queryString from 'query-string';

const str = queryString.stringify({ user: 'john' });
// Result: 'user=john'

@smithy/querystring-builder builds strings for AWS protocol requirements.

import { buildQueryString } from '@smithy/querystring-builder';

const str = buildQueryString({ name: 'john' });
// Result: '?name=john' (includes leading question mark)

querystring-es3 uses the legacy Node.js encoding style.

import querystring from 'querystring-es3';

const str = querystring.stringify({ user: 'john' });
// Result: 'user=john'

url-search-params-polyfill uses the standard Web API constructor.

import 'url-search-params-polyfill';

const params = new URLSearchParams();
params.append('user', 'john');
const str = params.toString();
// Result: 'user=john'

🪆 Handling Nested Objects

One of the biggest differences between these libraries is how they treat nested data structures. Some flatten everything, while others preserve hierarchy.

qs is the strongest here, supporting deep nesting and arrays out of the box.

import qs from 'qs';

const data = { filter: { type: 'book', status: 'new' } };
const str = qs.stringify(data);
// Result: 'filter%5Btype%5D=book&filter%5Bstatus%5D=new'

query-string requires manual handling for nested data.

import queryString from 'query-string';

// Nested objects are stringified to '[object Object]' without help
const str = queryString.stringify({ filter: { type: 'book' } });
// Result: 'filter=%5Bobject+Object%5D' (Usually unwanted)

@smithy/querystring-builder expects flat key-value pairs primarily.

import { buildQueryString } from '@smithy/querystring-builder';

// Nested objects must be flattened before passing
const str = buildQueryString({ 'filter.type': 'book' });
// Result: '?filter.type=book'

querystring-es3 does not support nested objects natively.

import querystring from 'querystring-es3';

const str = querystring.stringify({ filter: { type: 'book' } });
// Result: 'filter=%5Bobject+Object%5D'

url-search-params-polyfill follows the native spec, which is flat only.

import 'url-search-params-polyfill';

const params = new URLSearchParams();
// Must manually flatten nested data
params.append('filter.type', 'book');
const str = params.toString();
// Result: 'filter.type=book'

🕰️ Legacy and Native Support

Choosing the right tool often depends on the environments you must support. Modern browsers have built-in APIs, while older systems need help.

qs works everywhere but requires bundling.

import qs from 'qs';
// Works in Node.js and bundled browser code
// No native dependency

query-string is designed for modern browsers and bundlers.

import queryString from 'query-string';
// Optimized for web environments
// Requires bundler for Node.js usage

@smithy/querystring-builder is part of a modern TypeScript SDK.

import { buildQueryString } from '@smithy/querystring-builder';
// Requires modern JavaScript environment
// Used within AWS SDK v3 stack

querystring-es3 targets very old JavaScript engines.

import querystring from 'querystring-es3';
// Specifically for ES3 environments (IE8 and older)
// Heavy polyfill overhead for modern apps

url-search-params-polyfill adds native API to old browsers.

import 'url-search-params-polyfill';
// Patches window.URLSearchParams if missing
// Unnecessary in evergreen browsers

⚠️ Deprecation and Maintenance Status

Some of these packages are no longer recommended for new development. Knowing which ones are legacy helps avoid technical debt.

qs is actively maintained and widely trusted.

// Safe for long-term use in production
import qs from 'qs';

query-string is actively maintained by a prominent open-source developer.

// Safe for modern frontend projects
import queryString from 'query-string';

@smithy/querystring-builder is maintained as part of AWS SDK v3.

// Safe within AWS ecosystems
import { buildQueryString } from '@smithy/querystring-builder';

querystring-es3 is effectively deprecated due to Node.js core changes.

// AVOID: Node.js 'querystring' module is deprecated
// Use only for legacy maintenance
import querystring from 'querystring-es3';

url-search-params-polyfill is less needed due to native support.

// AVOID: Native URLSearchParams is now standard
// Use only for specific legacy browser requirements
import 'url-search-params-polyfill';

📊 Summary: Key Differences

PackagePrimary UseNested DataLegacy SupportStatus
qsGeneral Purpose✅ Excellent❌ No✅ Active
query-stringFrontend Web❌ Limited❌ No✅ Active
@smithy/querystring-builderAWS SDK❌ Flat Only❌ No✅ Active
querystring-es3Legacy Node❌ No✅ ES3⚠️ Legacy
url-search-params-polyfillLegacy Browser❌ Flat Only✅ Old Browsers⚠️ Legacy

💡 The Big Picture

qs is the heavy-duty choice 🏋️ — ideal for backends and complex data structures where nesting matters. It handles the edge cases that break other tools.

query-string is the frontend favorite 🎨 — perfect for React apps and simple URL manipulation where readability and ease of use are priorities.

@smithy/querystring-builder is the specialist 🛡️ — designed for AWS SDK internal work or strict protocol compliance. It is not a general-purpose tool.

querystring-es3 and url-search-params-polyfill are the legacy bridges 🌉 — use them only when you have no choice but to support outdated environments. For all new projects, prefer native APIs or modern libraries like qs and query-string.

Final Thought: Match the tool to your environment. If you are building a modern web app, start with query-string or native URLSearchParams. If you are building an API or handling complex filters, reach for qs. Avoid legacy polyfills unless absolutely necessary.

How to Choose: @smithy/querystring-builder vs qs vs query-string vs querystring-es3 vs url-search-params-polyfill

  • @smithy/querystring-builder:

    Choose this package if you are working within the AWS SDK v3 ecosystem or need strict RFC compliance for cloud request signing. It is specialized for building query strings for HTTP requests rather than general web parsing. Do not use it for general-purpose browser query parameter handling.

  • qs:

    Choose qs if you need robust support for deeply nested objects and arrays in your query parameters. It is the industry standard for Node.js backends and complex data serialization where accuracy matters. It handles edge cases better than most alternatives.

  • query-string:

    Choose query-string if you want a simple, modern API for browser-based applications. It works well with React and other frontend frameworks where you need to read or update URL parameters quickly. It is lighter and easier to use for flat data structures.

  • querystring-es3:

    Choose querystring-es3 only if you must support very old browsers like Internet Explorer that lack modern JavaScript features. This package is effectively legacy technology and should be avoided in new projects. Use it only for maintaining older codebases.

  • url-search-params-polyfill:

    Choose url-search-params-polyfill only if you need the native URLSearchParams API in older browsers that do not support it. Like querystring-es3, this is a legacy solution as native support is now widespread. Prefer native APIs in modern development.