query-string
- Version 10.0.0
- Published
- 91.3 kB
- 2 dependencies
- MIT license
Install
npm i query-stringyarn add query-stringpnpm add query-stringOverview
Parse and stringify URL query strings
Index
Type Aliases
type ParsedQuery
type ParsedQuery<T = string> = Record<string, T | null | Array<T | null>>;type ParsedUrl
type ParsedUrl<T = string> = { readonly url: string; readonly query: ParsedQuery<T>;
/** The fragment identifier of the URL.
Present when the `parseFragmentIdentifier` option is `true`. */ readonly fragmentIdentifier?: string;};type ParseOptions
type ParseOptions = { /** Decode the keys and values. A byte that is not valid UTF-8 becomes the replacement character `U+FFFD`, and the bytes around it are still decoded, like the [`URL` parser](https://developer.mozilla.org/en-US/docs/Web/API/URL) and [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) do. A `%` that is not followed by two hexadecimal digits is not an escape and is kept as it is.
@default true */ readonly decode?: boolean;
/** @default 'none'
- `bracket`: Parse arrays with bracket representation:
``` import queryString from 'query-string';
queryString.parse('foo[]=1&foo[]=2&foo[]=3', {arrayFormat: 'bracket'}); //=> {foo: ['1', '2', '3']} ```
- `index`: Parse arrays with index representation:
``` import queryString from 'query-string';
queryString.parse('foo[0]=1&foo[1]=2&foo[3]=3', {arrayFormat: 'index'}); //=> {foo: ['1', '2', '3']} ```
Entries without an index, such as `foo[]`, are appended after the highest index seen so far. Appending after an index greater than or equal to `Number.MAX_SAFE_INTEGER` is unsupported.
- `comma`: Parse arrays with elements separated by comma:
``` import queryString from 'query-string';
queryString.parse('foo=1,2,3', {arrayFormat: 'comma'}); //=> {foo: ['1', '2', '3']}
queryString.parse('foo=1,2&foo=3', {arrayFormat: 'comma'}); //=> {foo: ['1', '2', '3']} ```
A single value has no separator, so it is a plain value, not an array with one element. Use the `types` option to always get an array, or use `bracket-separator`, which marks arrays explicitly.
``` import queryString from 'query-string';
queryString.parse('foo=1', {arrayFormat: 'comma'}); //=> {foo: '1'}
queryString.parse('foo=1', {arrayFormat: 'comma', types: {foo: 'string[]'}}); //=> {foo: ['1']} ```
- `separator`: Parse arrays with elements separated by a custom character:
``` import queryString from 'query-string';
queryString.parse('foo=1|2|3', {arrayFormat: 'separator', arrayFormatSeparator: '|'}); //=> {foo: ['1', '2', '3']} ```
- `bracket-separator`: Parse arrays (that are explicitly marked with brackets) with elements separated by a custom character:
``` import queryString from 'query-string';
queryString.parse('foo[]', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {foo: []}
queryString.parse('foo[]=', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {foo: ['']}
queryString.parse('foo[]=1', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {foo: ['1']}
queryString.parse('foo[]=1|2|3', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {foo: ['1', '2', '3']}
queryString.parse('foo[]=1||3|||6', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {foo: ['1', '', '3', '', '', '6']}
queryString.parse('foo[]=1|2|3&bar=fluffy&baz[]=4', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {bar: 'fluffy', baz: ['4'], foo: ['1', '2', '3']} ```
- `colon-list-separator`: Parse arrays with parameter names that are explicitly marked with `:list`:
``` import queryString from 'query-string';
queryString.parse('foo:list=one&foo:list=two', {arrayFormat: 'colon-list-separator'}); //=> {foo: ['one', 'two']} ```
- `none`: Parse arrays with elements using duplicate keys:
``` import queryString from 'query-string';
queryString.parse('foo=1&foo=2&foo=3'); //=> {foo: ['1', '2', '3']} ``` */ readonly arrayFormat?: | 'bracket' | 'index' | 'comma' | 'separator' | 'bracket-separator' | 'colon-list-separator' | 'none';
/** The character used to separate array elements when using `{arrayFormat: 'separator'}`.
Only a literal separator delimits array elements. A percent-encoded separator (for example, `%2C`) is part of the element, which is how `.stringify()` encodes elements that contain the separator. Because of this, `%` and a hexadecimal digit are unsupported, since those also appear inside percent-encoded elements, and so are `&`, `+`, and `#`, since those already have a meaning in a URL: `&` separates parameters, `+` is decoded as a space, and `#` starts the fragment identifier. Those are handled on a best-effort basis, so the result is undefined. Whitespace cannot work at all, since leading and trailing whitespace is ignored when parsing, and a lone surrogate cannot be percent-encoded, so both throw a `TypeError`.
@example ``` import queryString from 'query-string';
queryString.parse('foo=a%2Cb,c', {arrayFormat: 'comma'}); //=> {foo: ['a,b', 'c']}
queryString.parse('foo[]=a%2Cb,c', {arrayFormat: 'bracket-separator'}); //=> {foo: ['a,b', 'c']} ```
@default , */ readonly arrayFormatSeparator?: string;
/** Supports both `Function` as a custom sorting function or `false` to disable sorting.
If omitted, keys are sorted using `Array#sort`.
@default true
@example ``` import queryString from 'query-string';
const order = ['c', 'a', 'b'];
queryString.parse('?a=one&b=two&c=three', { sort: (itemLeft, itemRight) => order.indexOf(itemLeft) - order.indexOf(itemRight) }); //=> {c: 'three', a: 'one', b: 'two'} ```
@example ``` import queryString from 'query-string';
queryString.parse('?a=one&c=three&b=two', {sort: false}); //=> {a: 'one', c: 'three', b: 'two'} ``` */ readonly sort?: ((itemLeft: string, itemRight: string) => number) | boolean;
/** Parse the value as a number type instead of string type if it's a number.
@default false
@example ``` import queryString from 'query-string';
queryString.parse('foo=1', {parseNumbers: true}); //=> {foo: 1} ``` */ readonly parseNumbers?: boolean;
/** Parse the value as a boolean type instead of string type if it's a boolean.
@default false
@example ``` import queryString from 'query-string';
queryString.parse('foo=true', {parseBooleans: true}); //=> {foo: true} ``` */ readonly parseBooleans?: boolean;
/** Parse the fragment identifier from the URL and add it to result object.
@default false
@example ``` import queryString from 'query-string';
queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true}); //=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'} ``` */ readonly parseFragmentIdentifier?: boolean;
/** Specifies a schema for parsing query values with explicit type declarations. When defined, the types provided here take precedence over general parsing options such as `parseNumbers`, `parseBooleans`, and `arrayFormat`.
Use this option to explicitly define the type of a specific parameter—particularly useful in cases where the type might otherwise be ambiguous (e.g., phone numbers or IDs).
You can also provide a custom function to transform the value. The function will receive the raw string and should return the desired parsed result. When used with array formats (like `comma`, `separator`, `bracket`, etc.), the function is applied to each array element individually.
NOTE: With `arrayFormat: 'none'`, array types (`string[]`, `number[]`) do not turn a single value into an array. The value stays a string, and `parseNumbers` and `parseBooleans` do not apply to it. A repeated key is still an array, and its items are parsed with the element type.
@default {}
@example Parse `phoneNumber` as a string, overriding the `parseNumbers` option: ``` import queryString from 'query-string';
queryString.parse('?phoneNumber=%2B380951234567&id=1', { parseNumbers: true, types: { phoneNumber: 'string', } }); //=> {id: 1, phoneNumber: '+380951234567'} ```
@example Parse `items` as an array of strings, overriding the `parseNumbers` option: ``` import queryString from 'query-string';
queryString.parse('?age=20&items=1,2,3', { arrayFormat: 'comma', parseNumbers: true, types: { items: 'string[]', } }); //=> {age: 20, items: ['1', '2', '3']} ```
@example Force `age` to be parsed as a number even when `parseNumbers` is false: ``` import queryString from 'query-string';
queryString.parse('?age=20&id=01234&zipcode=90210', { types: { age: 'number', } }); //=> {age: 20, id: '01234', zipcode: '90210'} ```
@example Use a custom parser function to transform the value of `age`: ``` import queryString from 'query-string';
queryString.parse('?age=20&id=01234&zipcode=90210', { types: { age: value => value * 2, } }); //=> {age: 40, id: '01234', zipcode: '90210'} ```
@example Custom functions are applied to each array element when using array formats: ``` import queryString from 'query-string';
// With arrays, the function is applied to each element queryString.parse('?scores=10,20,30', { arrayFormat: 'comma', types: { scores: value => Number(value) * 2, } }); //=> {scores: [20, 40, 60]} ```
@example Array types do not split a single value when `arrayFormat` is set to `'none'`: ``` queryString.parse('ids=001,002,003&foods=apple,orange,mango', { arrayFormat: 'none', types: { ids: 'number[]', foods: 'string[]', }, }); //=> {foods: 'apple,orange,mango', ids: '001,002,003'} ```
@example Parse a query using multiple type definitions: ``` import queryString from 'query-string';
queryString.parse('?ids=001,002,003&items=1,2,3&price=22.00&numbers=1,2,3&double=5&number=20', { arrayFormat: 'comma', types: { ids: 'string', items: 'string[]', price: 'string', numbers: 'number[]', double: value => value * 2, number: 'number', }, }); //=> {double: 10, ids: '001,002,003', items: ['1', '2', '3'], number: 20, numbers: [1, 2, 3], price: '22.00'} ```
@example Force `flagged` to be parsed as a boolean even when `parseBooleans` is false: ``` queryString.parse('?isAdmin=true&flagged=true&isOkay=0', { parseBooleans: false, types: { flagged: 'boolean', isOkay: 'boolean', }, }); //=> {flagged: true, isAdmin: 'true', isOkay: false} ```
Note: The `'boolean'` type also converts `'0'` and `'1'` to booleans, and treats valueless keys (e.g. `?flag`) as `true`. */ readonly types?: Record< string, | 'boolean' | 'number' | 'string' | 'string[]' | 'number[]' | ((value: string) => unknown) >;};type Stringifiable
type Stringifiable = string | boolean | number | bigint | null | undefined;Supported value types for query string parameters.
Note:
Symbol, functions, and objects (except arrays) are not supported and will throw an error when stringified.
type StringifiableRecord
type StringifiableRecord = Record<string, Stringifiable | readonly Stringifiable[]>;A record of stringifiable values.
type StringifyOptions
type StringifyOptions = { /** Strictly encode URI components. It uses [`encodeURIComponent`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) if set to `false`. You probably [don't care](https://github.com/sindresorhus/query-string/issues/42) about this option.
@default true */ readonly strict?: boolean;
/** [URL encode](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) the keys and values.
A lone surrogate, which cannot be percent-encoded, is replaced with the replacement character U+FFFD, like `URLSearchParams` does.
@default true */ readonly encode?: boolean;
/** @default 'none'
- `bracket`: Serialize arrays using bracket representation:
``` import queryString from 'query-string';
queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'bracket'}); //=> 'foo[]=1&foo[]=2&foo[]=3' ```
- `index`: Serialize arrays using index representation:
``` import queryString from 'query-string';
queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'index'}); //=> 'foo[0]=1&foo[1]=2&foo[2]=3' ```
- `comma`: Serialize arrays by separating elements with comma:
``` import queryString from 'query-string';
queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'comma'}); //=> 'foo=1,2,3'
queryString.stringify({foo: [1, null, '']}, {arrayFormat: 'comma'}); //=> 'foo=1,,' // Note that typing information for null values is lost // and `.parse('foo=1,,', {arrayFormat: 'comma'})` would return `{foo: ['1', '', '']}`. ```
- `separator`: Serialize arrays by separating elements with character:
``` import queryString from 'query-string';
queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'separator', arrayFormatSeparator: '|'}); //=> 'foo=1|2|3' ```
- `bracket-separator`: Serialize arrays by explicitly post-fixing array names with brackets and separating elements with a custom character:
``` import queryString from 'query-string';
queryString.stringify({foo: []}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'foo[]'
queryString.stringify({foo: ['']}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'foo[]='
queryString.stringify({foo: [1]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'foo[]=1'
queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'foo[]=1|2|3'
queryString.stringify({foo: [1, '', 3, null, null, 6]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'foo[]=1||3|||6'
queryString.stringify({foo: [1, '', 3, null, null, 6]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|', skipNull: true}); //=> 'foo[]=1||3|6'
queryString.stringify({foo: [1, 2, 3], bar: 'fluffy', baz: [4]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'bar=fluffy&baz[]=4&foo[]=1|2|3' ```
- `colon-list-separator`: Serialize arrays with parameter names that are explicitly marked with `:list`:
```js import queryString from 'query-string';
queryString.stringify({foo: ['one', 'two']}, {arrayFormat: 'colon-list-separator'}); //=> 'foo:list=one&foo:list=two' ```
- `none`: Serialize arrays by using duplicate keys:
``` import queryString from 'query-string';
queryString.stringify({foo: [1, 2, 3]}); //=> 'foo=1&foo=2&foo=3' ``` */ readonly arrayFormat?: | 'bracket' | 'index' | 'comma' | 'separator' | 'bracket-separator' | 'colon-list-separator' | 'none';
/** The character used to separate array elements when using `{arrayFormat: 'separator'}`.
A separator inside an element is percent-encoded, so `.parse()` can tell it apart from the separator between elements. With `comma` and `separator`, a plain value that contains the separator is percent-encoded the same way, so it does not turn into an array. Because of this, `%` and a hexadecimal digit are unsupported, since those also appear inside percent-encoded elements, and so are `&`, `+`, and `#`, since those already have a meaning in a URL: `&` separates parameters, `+` is decoded as a space, and `#` starts the fragment identifier. Those are handled on a best-effort basis, so the result is undefined. Whitespace cannot work at all, since leading and trailing whitespace is ignored when parsing, and a lone surrogate cannot be percent-encoded, so both throw a `TypeError`.
@default , */ readonly arrayFormatSeparator?: string;
/** Supports both `Function` as a custom sorting function or `false` to disable sorting.
If omitted, keys are sorted using `Array#sort`.
@default true
@example ``` import queryString from 'query-string';
const order = ['c', 'a', 'b'];
queryString.stringify({a: 1, b: 2, c: 3}, { sort: (itemLeft, itemRight) => order.indexOf(itemLeft) - order.indexOf(itemRight) }); //=> 'c=3&a=1&b=2' ```
@example ``` import queryString from 'query-string';
queryString.stringify({b: 1, c: 2, a: 3}, {sort: false}); //=> 'b=1&c=2&a=3' ``` */ readonly sort?: ((itemLeft: string, itemRight: string) => number) | boolean;
/** Skip keys with `null` as the value.
Note that keys with `undefined` as the value are always skipped.
@default false
@example ``` import queryString from 'query-string';
queryString.stringify({a: 1, b: undefined, c: null, d: 4}, { skipNull: true }); //=> 'a=1&d=4'
queryString.stringify({a: undefined, b: null}, { skipNull: true }); //=> '' ``` */ readonly skipNull?: boolean;
/** Skip keys with an empty string as the value.
@default false
@example ``` import queryString from 'query-string';
queryString.stringify({a: 1, b: '', c: '', d: 4}, { skipEmptyString: true }); //=> 'a=1&d=4' ```
@example ``` import queryString from 'query-string';
queryString.stringify({a: '', b: ''}, { skipEmptyString: true }); //=> '' ``` */ readonly skipEmptyString?: boolean;
/** A function that transforms key-value pairs before stringification.
Similar to the `replacer` parameter of `JSON.stringify()`, this function is called for each key-value pair and can be used to transform values before they are stringified.
The function receives the key and value, and should return the transformed value. Returning `undefined` will omit the key-value pair from the resulting query string. The `skipNull` and `skipEmptyString` options apply to the returned value.
This is useful for custom serialization of non-primitive types like `Date`:
@example ``` import queryString from 'query-string';
queryString.stringify({ date: new Date('2024-01-15T10:30:00Z'), name: 'John' }, { replacer: (key, value) => { if (value instanceof Date) { return value.toISOString(); }
return value; } }); //=> 'date=2024-01-15T10%3A30%3A00.000Z&name=John' ```
@example ``` import queryString from 'query-string';
// Omit keys with null values using replacer instead of skipNull queryString.stringify({ a: 1, b: null, c: 3 }, { replacer: (key, value) => value === null ? undefined : value }); //=> 'a=1&c=3' ``` */ readonly replacer?: (key: string, value: unknown) => unknown;};type UrlObject
type UrlObject = { /** The URL to stringify. Leading and trailing whitespace is ignored. */ readonly url: string;
/** Overrides queries in the `url` property. */ // TODO: Use the below instead when the following TS issues are fixed: // - https://github.com/microsoft/TypeScript/issues/15300 // - https://github.com/microsoft/TypeScript/issues/42021 // Context: https://github.com/sindresorhus/query-string/issues/298 // readonly query?: StringifiableRecord; readonly query?: Record<string, any>;
/** Overrides the fragment identifier in the `url` property.
The fragment identifier without the leading `#`. An empty string removes the fragment identifier from the URL.
Like the query values, it is a decoded value and is percent-encoded when `encode` is `true`, so `.parseUrl()` reads it back unchanged. `/`, `?`, and `#` are kept as-is, so hash routes like `#/users?id=1` work. When `encode` is `false`, it is written as-is.
@example ``` import queryString from 'query-string';
queryString.stringifyUrl({url: 'https://foo.bar', fragmentIdentifier: '100%'}); //=> 'https://foo.bar#100%25'
queryString.stringifyUrl({url: 'https://foo.bar', fragmentIdentifier: '/users?id=1'}); //=> 'https://foo.bar#/users?id=1' ``` */ readonly fragmentIdentifier?: string;};Namespaces
namespace default
module 'base.d.ts' {}Decode the keys and values. A byte that is not valid UTF-8 becomes the replacement character
U+FFFD, and the bytes around it are still decoded, like the [URLparser](https://developer.mozilla.org/en-US/docs/Web/API/URL) and [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) do. A%that is not followed by two hexadecimal digits is not an escape and is kept as it is.true
function exclude
exclude: { ( url: string, keys: readonly string[], options?: ParseOptions & StringifyOptions ): string; <Options extends ParseOptions & StringifyOptions>( url: string, filter: ( key: string, value: ParsedValue<Options> | ParsedValue<Options>[] ) => boolean, options?: KnownOptions<Options> ): string;};Exclude query parameters from a URL. Like
.pick()but reversed.Parameter url
The URL containing the query parameters to exclude. Leading and trailing whitespace is ignored.
Parameter keys
The names of the query parameters to remove. All other query parameters will remain in the URL.
Parameter filter
A filter predicate that will be provided the name of each query parameter and its value. The
parseNumbers,parseBooleans, andtypesoptions also affectvalue. They only affect the value passed to the filter. The query parameters are written back to the URL from the plain string values, so a value like007is not rewritten as7. The query is decoded only whenencodeistrue, so a value likea%20bis not percent-encoded a second time. Withencode: false, the filter receives the key and value as they are in the URL. Thedecodeoption is ignored. The stringify options apply to the output, soskipNullandskipEmptyStringalso drop a parameter that the filter kept.Parameter options
The parse and stringify options, which also apply to the filter.
sort: falsekeeps the original parameter order in the output.Returns
The URL without the excluded query parameters. The query parameters are sorted, like with
.stringify(). Passsort: falsein the options to keep their order. With sorting disabled, integer-index keys come first in ascending numeric order, following JavaScript object enumeration. Repeated keys are grouped together.Example 1
queryString.exclude('https://foo.bar?foo=1&bar=2#hello', ['foo']);//=> 'https://foo.bar?bar=2#hello'queryString.exclude('https://foo.bar?foo=1&bar=2#hello', (name, value) => value === 2, {parseNumbers: true});//=> 'https://foo.bar?foo=1#hello'
function extract
extract: (url: string) => string;Extract a query string from a URL that can be passed into
.parse().Example 1
import queryString from 'query-string';queryString.extract('https://foo.bar?foo=bar');//=> 'foo=bar'
function parse
parse: <Options extends ParseOptions>( query: string, options?: KnownOptions<Options>) => ParsedQuery<ParsedValue<Options>>;Parse a query string into an object. Leading
?or#are ignored, so you can passlocation.searchorlocation.hashdirectly.The returned object is created with [
Object.create(null)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create) and thus does not have aprototype.Parameter query
The query string to parse.
function parseUrl
parseUrl: <Options extends ParseOptions>( url: string, options?: KnownOptions<Options>) => ParsedUrl<ParsedValue<Options>>;Extract the URL and the query string as an object. Leading and trailing whitespace is ignored.
Parameter url
The URL to parse.
Returns
An object with a
urlandqueryproperty.If the
parseFragmentIdentifieroption istrue, the object will also contain afragmentIdentifierproperty.Example 1
import queryString from 'query-string';queryString.parseUrl('https://foo.bar?foo=bar');//=> {url: 'https://foo.bar', query: {foo: 'bar'}}queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true});//=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'}
function pick
pick: { ( url: string, keys: readonly string[], options?: ParseOptions & StringifyOptions ): string; <Options extends ParseOptions & StringifyOptions>( url: string, filter: ( key: string, value: ParsedValue<Options> | ParsedValue<Options>[] ) => boolean, options?: KnownOptions<Options> ): string;};Pick query parameters from a URL.
Parameter url
The URL containing the query parameters to pick. Leading and trailing whitespace is ignored.
Parameter keys
The names of the query parameters to keep. All other query parameters will be removed from the URL.
Parameter filter
A filter predicate that will be provided the name of each query parameter and its value. The
parseNumbers,parseBooleans, andtypesoptions also affectvalue. They only affect the value passed to the filter. The query parameters are written back to the URL from the plain string values, so a value like007is not rewritten as7. The query is decoded only whenencodeistrue, so a value likea%20bis not percent-encoded a second time. Withencode: false, the filter receives the key and value as they are in the URL. Thedecodeoption is ignored. The stringify options apply to the output, soskipNullandskipEmptyStringalso drop a parameter that the filter kept.Parameter options
The parse and stringify options, which also apply to the filter.
sort: falsekeeps the original parameter order in the output.Returns
The URL with the picked query parameters. The query parameters are sorted, like with
.stringify(). Passsort: falsein the options to keep their order. With sorting disabled, integer-index keys come first in ascending numeric order, following JavaScript object enumeration. Repeated keys are grouped together.Example 1
queryString.pick('https://foo.bar?foo=1&bar=2#hello', ['foo']);//=> 'https://foo.bar?foo=1#hello'queryString.pick('https://foo.bar?foo=1&bar=2#hello', (name, value) => value === 2, {parseNumbers: true});//=> 'https://foo.bar?bar=2#hello'
function stringify
stringify: (object: Record<string, any>, options?: StringifyOptions) => string;Stringify an object into a query string and sorting the keys.
Parameter object
Object to stringify. Supported value types are:
string,number,bigint,boolean,null,undefined, and arrays of these types. Other types likeSymbol, functions, or objects (except arrays) will throw an error.Example 1
import queryString from 'query-string';queryString.stringify({foo: 'bar', baz: 42, qux: true});//=> 'baz=42&foo=bar&qux=true'
function stringifyUrl
stringifyUrl: (object: UrlObject, options?: StringifyOptions) => string;Stringify an object into a URL with a query string and sorting the keys. The inverse of [
.parseUrl()](https://github.com/sindresorhus/query-string#parseurlstring-options)The
optionsare the same as for.stringify().Returns
A string with the URL and a query string.
Query items in the
queryproperty overrides queries in theurlproperty. The query in theurlproperty is written back from its plain string values, soparseNumbers,parseBooleans, andtypesdo not rewrite it when the options are shared with.parseUrl().With
encode: false, an array marker in an existing parameter name is only treated as a marker when it is literal, such asa[], so a percent-encoded marker such asa%5B%5Dis not overridden by the plain key. The existing parameter is kept as-is, so overridingaalongside an existinga%5B%5Din the URL writes botha=2&a%5B%5D=1.The
fragmentIdentifierproperty overrides the fragment identifier in theurlproperty.Example 1
queryString.stringifyUrl({url: 'https://foo.bar', query: {foo: 'bar'}});//=> 'https://foo.bar?foo=bar'queryString.stringifyUrl({url: 'https://foo.bar?foo=baz', query: {foo: 'bar'}});//=> 'https://foo.bar?foo=bar'queryString.stringifyUrl({url: 'https://foo.bar',query: {top: 'foo'},fragmentIdentifier: 'bar'});//=> 'https://foo.bar?top=foo#bar'
type ParsedQuery
type ParsedQuery<T = string> = Record<string, T | null | Array<T | null>>;type ParsedUrl
type ParsedUrl<T = string> = { readonly url: string; readonly query: ParsedQuery<T>;
/** The fragment identifier of the URL.
Present when the `parseFragmentIdentifier` option is `true`. */ readonly fragmentIdentifier?: string;};type ParseOptions
type ParseOptions = { /** Decode the keys and values. A byte that is not valid UTF-8 becomes the replacement character `U+FFFD`, and the bytes around it are still decoded, like the [`URL` parser](https://developer.mozilla.org/en-US/docs/Web/API/URL) and [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) do. A `%` that is not followed by two hexadecimal digits is not an escape and is kept as it is.
@default true */ readonly decode?: boolean;
/** @default 'none'
- `bracket`: Parse arrays with bracket representation:
``` import queryString from 'query-string';
queryString.parse('foo[]=1&foo[]=2&foo[]=3', {arrayFormat: 'bracket'}); //=> {foo: ['1', '2', '3']} ```
- `index`: Parse arrays with index representation:
``` import queryString from 'query-string';
queryString.parse('foo[0]=1&foo[1]=2&foo[3]=3', {arrayFormat: 'index'}); //=> {foo: ['1', '2', '3']} ```
Entries without an index, such as `foo[]`, are appended after the highest index seen so far. Appending after an index greater than or equal to `Number.MAX_SAFE_INTEGER` is unsupported.
- `comma`: Parse arrays with elements separated by comma:
``` import queryString from 'query-string';
queryString.parse('foo=1,2,3', {arrayFormat: 'comma'}); //=> {foo: ['1', '2', '3']}
queryString.parse('foo=1,2&foo=3', {arrayFormat: 'comma'}); //=> {foo: ['1', '2', '3']} ```
A single value has no separator, so it is a plain value, not an array with one element. Use the `types` option to always get an array, or use `bracket-separator`, which marks arrays explicitly.
``` import queryString from 'query-string';
queryString.parse('foo=1', {arrayFormat: 'comma'}); //=> {foo: '1'}
queryString.parse('foo=1', {arrayFormat: 'comma', types: {foo: 'string[]'}}); //=> {foo: ['1']} ```
- `separator`: Parse arrays with elements separated by a custom character:
``` import queryString from 'query-string';
queryString.parse('foo=1|2|3', {arrayFormat: 'separator', arrayFormatSeparator: '|'}); //=> {foo: ['1', '2', '3']} ```
- `bracket-separator`: Parse arrays (that are explicitly marked with brackets) with elements separated by a custom character:
``` import queryString from 'query-string';
queryString.parse('foo[]', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {foo: []}
queryString.parse('foo[]=', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {foo: ['']}
queryString.parse('foo[]=1', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {foo: ['1']}
queryString.parse('foo[]=1|2|3', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {foo: ['1', '2', '3']}
queryString.parse('foo[]=1||3|||6', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {foo: ['1', '', '3', '', '', '6']}
queryString.parse('foo[]=1|2|3&bar=fluffy&baz[]=4', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> {bar: 'fluffy', baz: ['4'], foo: ['1', '2', '3']} ```
- `colon-list-separator`: Parse arrays with parameter names that are explicitly marked with `:list`:
``` import queryString from 'query-string';
queryString.parse('foo:list=one&foo:list=two', {arrayFormat: 'colon-list-separator'}); //=> {foo: ['one', 'two']} ```
- `none`: Parse arrays with elements using duplicate keys:
``` import queryString from 'query-string';
queryString.parse('foo=1&foo=2&foo=3'); //=> {foo: ['1', '2', '3']} ``` */ readonly arrayFormat?: | 'bracket' | 'index' | 'comma' | 'separator' | 'bracket-separator' | 'colon-list-separator' | 'none';
/** The character used to separate array elements when using `{arrayFormat: 'separator'}`.
Only a literal separator delimits array elements. A percent-encoded separator (for example, `%2C`) is part of the element, which is how `.stringify()` encodes elements that contain the separator. Because of this, `%` and a hexadecimal digit are unsupported, since those also appear inside percent-encoded elements, and so are `&`, `+`, and `#`, since those already have a meaning in a URL: `&` separates parameters, `+` is decoded as a space, and `#` starts the fragment identifier. Those are handled on a best-effort basis, so the result is undefined. Whitespace cannot work at all, since leading and trailing whitespace is ignored when parsing, and a lone surrogate cannot be percent-encoded, so both throw a `TypeError`.
@example ``` import queryString from 'query-string';
queryString.parse('foo=a%2Cb,c', {arrayFormat: 'comma'}); //=> {foo: ['a,b', 'c']}
queryString.parse('foo[]=a%2Cb,c', {arrayFormat: 'bracket-separator'}); //=> {foo: ['a,b', 'c']} ```
@default , */ readonly arrayFormatSeparator?: string;
/** Supports both `Function` as a custom sorting function or `false` to disable sorting.
If omitted, keys are sorted using `Array#sort`.
@default true
@example ``` import queryString from 'query-string';
const order = ['c', 'a', 'b'];
queryString.parse('?a=one&b=two&c=three', { sort: (itemLeft, itemRight) => order.indexOf(itemLeft) - order.indexOf(itemRight) }); //=> {c: 'three', a: 'one', b: 'two'} ```
@example ``` import queryString from 'query-string';
queryString.parse('?a=one&c=three&b=two', {sort: false}); //=> {a: 'one', c: 'three', b: 'two'} ``` */ readonly sort?: ((itemLeft: string, itemRight: string) => number) | boolean;
/** Parse the value as a number type instead of string type if it's a number.
@default false
@example ``` import queryString from 'query-string';
queryString.parse('foo=1', {parseNumbers: true}); //=> {foo: 1} ``` */ readonly parseNumbers?: boolean;
/** Parse the value as a boolean type instead of string type if it's a boolean.
@default false
@example ``` import queryString from 'query-string';
queryString.parse('foo=true', {parseBooleans: true}); //=> {foo: true} ``` */ readonly parseBooleans?: boolean;
/** Parse the fragment identifier from the URL and add it to result object.
@default false
@example ``` import queryString from 'query-string';
queryString.parseUrl('https://foo.bar?foo=bar#xyz', {parseFragmentIdentifier: true}); //=> {url: 'https://foo.bar', query: {foo: 'bar'}, fragmentIdentifier: 'xyz'} ``` */ readonly parseFragmentIdentifier?: boolean;
/** Specifies a schema for parsing query values with explicit type declarations. When defined, the types provided here take precedence over general parsing options such as `parseNumbers`, `parseBooleans`, and `arrayFormat`.
Use this option to explicitly define the type of a specific parameter—particularly useful in cases where the type might otherwise be ambiguous (e.g., phone numbers or IDs).
You can also provide a custom function to transform the value. The function will receive the raw string and should return the desired parsed result. When used with array formats (like `comma`, `separator`, `bracket`, etc.), the function is applied to each array element individually.
NOTE: With `arrayFormat: 'none'`, array types (`string[]`, `number[]`) do not turn a single value into an array. The value stays a string, and `parseNumbers` and `parseBooleans` do not apply to it. A repeated key is still an array, and its items are parsed with the element type.
@default {}
@example Parse `phoneNumber` as a string, overriding the `parseNumbers` option: ``` import queryString from 'query-string';
queryString.parse('?phoneNumber=%2B380951234567&id=1', { parseNumbers: true, types: { phoneNumber: 'string', } }); //=> {id: 1, phoneNumber: '+380951234567'} ```
@example Parse `items` as an array of strings, overriding the `parseNumbers` option: ``` import queryString from 'query-string';
queryString.parse('?age=20&items=1,2,3', { arrayFormat: 'comma', parseNumbers: true, types: { items: 'string[]', } }); //=> {age: 20, items: ['1', '2', '3']} ```
@example Force `age` to be parsed as a number even when `parseNumbers` is false: ``` import queryString from 'query-string';
queryString.parse('?age=20&id=01234&zipcode=90210', { types: { age: 'number', } }); //=> {age: 20, id: '01234', zipcode: '90210'} ```
@example Use a custom parser function to transform the value of `age`: ``` import queryString from 'query-string';
queryString.parse('?age=20&id=01234&zipcode=90210', { types: { age: value => value * 2, } }); //=> {age: 40, id: '01234', zipcode: '90210'} ```
@example Custom functions are applied to each array element when using array formats: ``` import queryString from 'query-string';
// With arrays, the function is applied to each element queryString.parse('?scores=10,20,30', { arrayFormat: 'comma', types: { scores: value => Number(value) * 2, } }); //=> {scores: [20, 40, 60]} ```
@example Array types do not split a single value when `arrayFormat` is set to `'none'`: ``` queryString.parse('ids=001,002,003&foods=apple,orange,mango', { arrayFormat: 'none', types: { ids: 'number[]', foods: 'string[]', }, }); //=> {foods: 'apple,orange,mango', ids: '001,002,003'} ```
@example Parse a query using multiple type definitions: ``` import queryString from 'query-string';
queryString.parse('?ids=001,002,003&items=1,2,3&price=22.00&numbers=1,2,3&double=5&number=20', { arrayFormat: 'comma', types: { ids: 'string', items: 'string[]', price: 'string', numbers: 'number[]', double: value => value * 2, number: 'number', }, }); //=> {double: 10, ids: '001,002,003', items: ['1', '2', '3'], number: 20, numbers: [1, 2, 3], price: '22.00'} ```
@example Force `flagged` to be parsed as a boolean even when `parseBooleans` is false: ``` queryString.parse('?isAdmin=true&flagged=true&isOkay=0', { parseBooleans: false, types: { flagged: 'boolean', isOkay: 'boolean', }, }); //=> {flagged: true, isAdmin: 'true', isOkay: false} ```
Note: The `'boolean'` type also converts `'0'` and `'1'` to booleans, and treats valueless keys (e.g. `?flag`) as `true`. */ readonly types?: Record< string, | 'boolean' | 'number' | 'string' | 'string[]' | 'number[]' | ((value: string) => unknown) >;};type Stringifiable
type Stringifiable = string | boolean | number | bigint | null | undefined;Supported value types for query string parameters.
Note:
Symbol, functions, and objects (except arrays) are not supported and will throw an error when stringified.
type StringifiableRecord
type StringifiableRecord = Record<string, Stringifiable | readonly Stringifiable[]>;A record of stringifiable values.
type StringifyOptions
type StringifyOptions = { /** Strictly encode URI components. It uses [`encodeURIComponent`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) if set to `false`. You probably [don't care](https://github.com/sindresorhus/query-string/issues/42) about this option.
@default true */ readonly strict?: boolean;
/** [URL encode](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) the keys and values.
A lone surrogate, which cannot be percent-encoded, is replaced with the replacement character U+FFFD, like `URLSearchParams` does.
@default true */ readonly encode?: boolean;
/** @default 'none'
- `bracket`: Serialize arrays using bracket representation:
``` import queryString from 'query-string';
queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'bracket'}); //=> 'foo[]=1&foo[]=2&foo[]=3' ```
- `index`: Serialize arrays using index representation:
``` import queryString from 'query-string';
queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'index'}); //=> 'foo[0]=1&foo[1]=2&foo[2]=3' ```
- `comma`: Serialize arrays by separating elements with comma:
``` import queryString from 'query-string';
queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'comma'}); //=> 'foo=1,2,3'
queryString.stringify({foo: [1, null, '']}, {arrayFormat: 'comma'}); //=> 'foo=1,,' // Note that typing information for null values is lost // and `.parse('foo=1,,', {arrayFormat: 'comma'})` would return `{foo: ['1', '', '']}`. ```
- `separator`: Serialize arrays by separating elements with character:
``` import queryString from 'query-string';
queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'separator', arrayFormatSeparator: '|'}); //=> 'foo=1|2|3' ```
- `bracket-separator`: Serialize arrays by explicitly post-fixing array names with brackets and separating elements with a custom character:
``` import queryString from 'query-string';
queryString.stringify({foo: []}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'foo[]'
queryString.stringify({foo: ['']}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'foo[]='
queryString.stringify({foo: [1]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'foo[]=1'
queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'foo[]=1|2|3'
queryString.stringify({foo: [1, '', 3, null, null, 6]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'foo[]=1||3|||6'
queryString.stringify({foo: [1, '', 3, null, null, 6]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|', skipNull: true}); //=> 'foo[]=1||3|6'
queryString.stringify({foo: [1, 2, 3], bar: 'fluffy', baz: [4]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'}); //=> 'bar=fluffy&baz[]=4&foo[]=1|2|3' ```
- `colon-list-separator`: Serialize arrays with parameter names that are explicitly marked with `:list`:
```js import queryString from 'query-string';
queryString.stringify({foo: ['one', 'two']}, {arrayFormat: 'colon-list-separator'}); //=> 'foo:list=one&foo:list=two' ```
- `none`: Serialize arrays by using duplicate keys:
``` import queryString from 'query-string';
queryString.stringify({foo: [1, 2, 3]}); //=> 'foo=1&foo=2&foo=3' ``` */ readonly arrayFormat?: | 'bracket' | 'index' | 'comma' | 'separator' | 'bracket-separator' | 'colon-list-separator' | 'none';
/** The character used to separate array elements when using `{arrayFormat: 'separator'}`.
A separator inside an element is percent-encoded, so `.parse()` can tell it apart from the separator between elements. With `comma` and `separator`, a plain value that contains the separator is percent-encoded the same way, so it does not turn into an array. Because of this, `%` and a hexadecimal digit are unsupported, since those also appear inside percent-encoded elements, and so are `&`, `+`, and `#`, since those already have a meaning in a URL: `&` separates parameters, `+` is decoded as a space, and `#` starts the fragment identifier. Those are handled on a best-effort basis, so the result is undefined. Whitespace cannot work at all, since leading and trailing whitespace is ignored when parsing, and a lone surrogate cannot be percent-encoded, so both throw a `TypeError`.
@default , */ readonly arrayFormatSeparator?: string;
/** Supports both `Function` as a custom sorting function or `false` to disable sorting.
If omitted, keys are sorted using `Array#sort`.
@default true
@example ``` import queryString from 'query-string';
const order = ['c', 'a', 'b'];
queryString.stringify({a: 1, b: 2, c: 3}, { sort: (itemLeft, itemRight) => order.indexOf(itemLeft) - order.indexOf(itemRight) }); //=> 'c=3&a=1&b=2' ```
@example ``` import queryString from 'query-string';
queryString.stringify({b: 1, c: 2, a: 3}, {sort: false}); //=> 'b=1&c=2&a=3' ``` */ readonly sort?: ((itemLeft: string, itemRight: string) => number) | boolean;
/** Skip keys with `null` as the value.
Note that keys with `undefined` as the value are always skipped.
@default false
@example ``` import queryString from 'query-string';
queryString.stringify({a: 1, b: undefined, c: null, d: 4}, { skipNull: true }); //=> 'a=1&d=4'
queryString.stringify({a: undefined, b: null}, { skipNull: true }); //=> '' ``` */ readonly skipNull?: boolean;
/** Skip keys with an empty string as the value.
@default false
@example ``` import queryString from 'query-string';
queryString.stringify({a: 1, b: '', c: '', d: 4}, { skipEmptyString: true }); //=> 'a=1&d=4' ```
@example ``` import queryString from 'query-string';
queryString.stringify({a: '', b: ''}, { skipEmptyString: true }); //=> '' ``` */ readonly skipEmptyString?: boolean;
/** A function that transforms key-value pairs before stringification.
Similar to the `replacer` parameter of `JSON.stringify()`, this function is called for each key-value pair and can be used to transform values before they are stringified.
The function receives the key and value, and should return the transformed value. Returning `undefined` will omit the key-value pair from the resulting query string. The `skipNull` and `skipEmptyString` options apply to the returned value.
This is useful for custom serialization of non-primitive types like `Date`:
@example ``` import queryString from 'query-string';
queryString.stringify({ date: new Date('2024-01-15T10:30:00Z'), name: 'John' }, { replacer: (key, value) => { if (value instanceof Date) { return value.toISOString(); }
return value; } }); //=> 'date=2024-01-15T10%3A30%3A00.000Z&name=John' ```
@example ``` import queryString from 'query-string';
// Omit keys with null values using replacer instead of skipNull queryString.stringify({ a: 1, b: null, c: 3 }, { replacer: (key, value) => value === null ? undefined : value }); //=> 'a=1&c=3' ``` */ readonly replacer?: (key: string, value: unknown) => unknown;};type UrlObject
type UrlObject = { /** The URL to stringify. Leading and trailing whitespace is ignored. */ readonly url: string;
/** Overrides queries in the `url` property. */ // TODO: Use the below instead when the following TS issues are fixed: // - https://github.com/microsoft/TypeScript/issues/15300 // - https://github.com/microsoft/TypeScript/issues/42021 // Context: https://github.com/sindresorhus/query-string/issues/298 // readonly query?: StringifiableRecord; readonly query?: Record<string, any>;
/** Overrides the fragment identifier in the `url` property.
The fragment identifier without the leading `#`. An empty string removes the fragment identifier from the URL.
Like the query values, it is a decoded value and is percent-encoded when `encode` is `true`, so `.parseUrl()` reads it back unchanged. `/`, `?`, and `#` are kept as-is, so hash routes like `#/users?id=1` work. When `encode` is `false`, it is written as-is.
@example ``` import queryString from 'query-string';
queryString.stringifyUrl({url: 'https://foo.bar', fragmentIdentifier: '100%'}); //=> 'https://foo.bar#100%25'
queryString.stringifyUrl({url: 'https://foo.bar', fragmentIdentifier: '/users?id=1'}); //=> 'https://foo.bar#/users?id=1' ``` */ readonly fragmentIdentifier?: string;};Package Files (2)
Dependencies (2)
Dev Dependencies (5)
Peer Dependencies (0)
No peer dependencies.
Badge
To add a badge like this oneto your package's README, use the codes available below.
You may also use Shields.io to create a custom badge linking to https://www.jsdocs.io/package/query-string.
- Markdown[](https://www.jsdocs.io/package/query-string)
- HTML<a href="https://www.jsdocs.io/package/query-string"><img src="https://img.shields.io/badge/jsDocs.io-reference-blue" alt="jsDocs.io"></a>
- Updated .
Package analyzed in 3412 ms. - Missing or incorrect documentation? Open an issue for this package.
