The node:querystring module provides utilities for parsing and formatting URL query strings. It’s optimized for performance but is not a standardized API.
For new applications, consider using URLSearchParams for standards compliance. Use querystring when performance is critical or working with legacy code.
Installation
import querystring from 'node:querystring';
// or
const querystring = require('node:querystring');
Parsing Query Strings
querystring.parse(str[, sep[, eq[, options]]])
Parses a URL query string into an object of key-value pairs.
Parameters:
str - The URL query string to parse
sep - Delimiter for key-value pairs (default: '&')
eq - Delimiter between keys and values (default: '=')
options
decodeURIComponent - Custom decoding function (default: querystring.unescape())
maxKeys - Maximum number of keys to parse (default: 1000, use 0 for unlimited)
Returns: - Parsed object
Examples:
import querystring from 'node:querystring';
// Basic parsing
const parsed = querystring.parse('foo=bar&abc=xyz&abc=123');
console.log(parsed);
// { foo: 'bar', abc: ['xyz', '123'] }
// Multiple values for same key
const multi = querystring.parse('name=John&age=30&name=Jane');
console.log(multi);
// { name: ['John', 'Jane'], age: '30' }
// Custom separators
const custom = querystring.parse('foo:bar;baz:qux', ';', ':');
console.log(custom);
// { foo: 'bar', baz: 'qux' }
querystring.decode()
Alias for querystring.parse().
const decoded = querystring.decode('key=value');
// Same as querystring.parse('key=value')
querystring.stringify(obj[, sep[, eq[, options]]])
Serializes an object into a URL query string.
Parameters:
obj - The object to serialize
sep - Delimiter for key-value pairs (default: '&')
eq - Delimiter between keys and values (default: '=')
options
encodeURIComponent - Custom encoding function (default: querystring.escape())
Returns: - URL query string
Supported types: string, number, bigint, boolean, and arrays of these types
Examples:
import querystring from 'node:querystring';
// Basic stringification
const str = querystring.stringify({ foo: 'bar', baz: 'qux' });
console.log(str);
// 'foo=bar&baz=qux'
// Array values
const arr = querystring.stringify({ colors: ['red', 'blue', 'green'] });
console.log(arr);
// 'colors=red&colors=blue&colors=green'
// Custom separators
const custom = querystring.stringify(
{ foo: 'bar', baz: 'qux' },
';',
':'
);
console.log(custom);
// 'foo:bar;baz:qux'
// Empty values
const empty = querystring.stringify({ foo: '', bar: 'value' });
console.log(empty);
// 'foo=&bar=value'
querystring.encode()
Alias for querystring.stringify().
const encoded = querystring.encode({ key: 'value' });
// Same as querystring.stringify({ key: 'value' })
Encoding and Decoding
querystring.escape(str)
Performs URL percent-encoding optimized for query strings.
Parameters:
Returns: - Percent-encoded string
Example:
const escaped = querystring.escape('hello world!');
console.log(escaped);
// 'hello%20world!'
const specialChars = querystring.escape('foo=bar&baz');
console.log(specialChars);
// 'foo%3Dbar%26baz'
querystring.unescape(str)
Decodes URL percent-encoded characters.
Parameters:
Returns: - Decoded string
Example:
const unescaped = querystring.unescape('hello%20world');
console.log(unescaped);
// 'hello world'
const decoded = querystring.unescape('foo%3Dbar%26baz');
console.log(decoded);
// 'foo=bar&baz'
Common Use Cases
Parsing URL Query Parameters
import querystring from 'node:querystring';
import { parse } from 'node:url';
const url = 'https://example.com/search?q=nodejs&page=2&sort=date';
const parsedUrl = parse(url);
const params = querystring.parse(parsedUrl.query);
console.log(params);
// { q: 'nodejs', page: '2', sort: 'date' }
console.log(params.q); // 'nodejs'
console.log(params.page); // '2'
Building URLs with Query Parameters
import querystring from 'node:querystring';
function buildApiUrl(baseUrl, params) {
const query = querystring.stringify(params);
return `${baseUrl}?${query}`;
}
const url = buildApiUrl('https://api.example.com/users', {
page: 1,
limit: 10,
sort: 'name'
});
console.log(url);
// 'https://api.example.com/users?page=1&limit=10&sort=name'
import querystring from 'node:querystring';
// Parse form submission
const formData = 'username=john&email=john%40example.com&age=30';
const fields = querystring.parse(formData);
console.log(fields);
// { username: 'john', email: '[email protected]', age: '30' }
// Create form data
const userData = {
username: 'jane',
email: '[email protected]',
age: 25
};
const encoded = querystring.stringify(userData);
console.log(encoded);
// 'username=jane&email=jane%40example.com&age=25'
Custom Encoding for Special Characters
import querystring from 'node:querystring';
// Custom encoding function
function customEncode(str) {
return encodeURIComponent(str).replace(/%20/g, '+');
}
const data = { search: 'hello world', filter: 'type:article' };
const encoded = querystring.stringify(data, null, null, {
encodeURIComponent: customEncode
});
console.log(encoded);
// 'search=hello+world&filter=type%3Aarticle'
Limiting Number of Keys
import querystring from 'node:querystring';
// Limit to prevent DoS attacks
const maliciousInput = 'a=1&b=2&c=3&d=4&e=5';
const limited = querystring.parse(maliciousInput, null, null, {
maxKeys: 3
});
console.log(limited);
// { a: '1', b: '2', c: '3' }
// Keys d and e are ignored
// Unlimited parsing (use with caution)
const unlimited = querystring.parse(maliciousInput, null, null, {
maxKeys: 0
});
console.log(unlimited);
// { a: '1', b: '2', c: '3', d: '4', e: '5' }
querystring vs URLSearchParams
import querystring from 'node:querystring';
// querystring (faster, Node.js specific)
const qs = querystring.parse('foo=bar&baz=qux');
// URLSearchParams (standard, works in browsers)
const params = new URLSearchParams('foo=bar&baz=qux');
const obj = Object.fromEntries(params);
When to Use Each
Use querystring when:
- Performance is critical
- Working with legacy Node.js code
- Need custom separators
- Building high-performance APIs
Use URLSearchParams when:
- Need browser compatibility
- Want standards compliance
- Building isomorphic/universal apps
- Performance is not critical
Best Practices
- Validate input - Always validate and sanitize parsed query strings
- Set maxKeys - Prevent DoS attacks by limiting keys
- Handle arrays - Check if values are arrays when needed
- Type conversion - Remember all values are strings; convert as needed
- Encoding - Ensure proper encoding of special characters
Security Considerations
import querystring from 'node:querystring';
// Always set maxKeys for untrusted input
function parseUserInput(query) {
return querystring.parse(query, null, null, {
maxKeys: 100 // Reasonable limit
});
}
// Validate and sanitize
function sanitizeParams(params) {
const safe = {};
for (const [key, value] of Object.entries(params)) {
// Whitelist allowed parameters
if (['page', 'limit', 'sort'].includes(key)) {
safe[key] = Array.isArray(value) ? value[0] : value;
}
}
return safe;
}
- URL - URL parsing and manipulation
- http - HTTP server and client
- URLSearchParams - Web standard query string API