Query string

JSON

Success
Warning

A query string has no types and no nesting — until you add them back

Every value in a query string is text. ?count=3 is not the number 3, it is the two characters 3, and ?active=true is not a boolean, it is the four characters t-r-u-e. That is easy to forget because most HTTP frameworks quietly do the conversion for you somewhere in the routing layer, right up until the day a zero-padded reference code like 0042 comes back as the number 42 and a support ticket gets filed.

Nesting does not exist in the format at all — RFC 3986 §3.4 defines the query component as a flat sequence of pchar, nothing more. Every nested object or array you have ever seen come out of a query string is a convention someone's parser invented on top of that flat text. This page follows the one qs uses, because it is the parser sitting behind Express's req.query and therefore the one most query strings pasted here were probably built to match: user[address][city] nests, tags[] or repeating a bare key builds an array.

The + question is the same one the plain URL Decode page has to answer, and for the same reason — decodeURIComponent reads a + as a literal plus sign, but a query string built from an HTML form reads it as a space, per the WHATWG URL Standard's form-encoding algorithm. Both readings decode without error, so guessing wrong is silent.

Everything runs in your browser. Query strings are where session tokens, API keys and search terms actually travel, so nothing pasted here is sent anywhere.

Parsing a query string

  1. Paste it inA bare query string, one with a leading ?, or a whole URL all work — paste a full address from a browser's address bar or its network tab and only the query part is read.
  2. Pick how + should readChoose A space if the query string came from a submitted HTML form; choose A plus sign — the default — if it was built with encodeURIComponent or copied from an API request you did not write yourself.
  3. Leave value guessing off unless you need itEvery value stays a string by default, because that is what a query string actually contains. Turn on Guess numbers and booleans only when you specifically want page=2 read as a number — it never touches anything that would lose a digit or a leading zero.
  4. Check the note under the outputIt says when bracket notation was found, when a full URL was trimmed down to its query part, and when a duplicate key had to be collapsed into an array. None of these are errors.

A repeated key with no brackets becomes an array tootag=voice&tag=sms and tag[]=voice&tag[]=sms both produce {"tag":["voice","sms"]}. Browsers build query strings the first way when a page has several inputs sharing one name attribute, so do not assume brackets are the only sign of a list.

Nesting and arrays from one query string

A subscriber lookup with a nested device object and a repeated tag — the shape a provisioning API actually sends, not a toy example.

Bracket notation in, nested JSON outqs-compatible
Query stringpasted from a request URL
msisdn=%2B447700900112&device%5Bimsi%5D=234307481234567&tags%5B%5D=voice&tags%5B%5D=sms
JSONnesting and array both reconstructed
{
  "msisdn": "+447700900112",
  "device": { "imsi": "234307481234567" },
  "tags": ["voice", "sms"]
}

When you need this

Reading what the front end actually sent

Copy the query string out of a failing request in your browser's network tab and read it as the object your handler will actually receive, rather than counting ampersands by eye.

Reverse-engineering an undocumented API

Plenty of internal and third-party APIs accept nested filters as bracket-notation query parameters with no written spec anywhere. Pasting a working request here shows you the shape without reading the server's source.

Debugging a parameter that silently vanished

A parameter that never reaches your handler is often a bracket typo — a missing ], or a mix of tags[] in one place and tags in another that ends up on two different keys. Seeing the parsed object side by side with the raw string usually finds it in seconds.

Turning a shared link into something you can diff

Feature flags, saved filters and share links often get serialised straight into the URL. Parsing one to JSON lets you diff it against another link the normal way, instead of eyeballing two long strings for the one character that differs.

Building a request by hand

Sketch the JSON body you want a request to carry, run it through JSON to Query String to get the encoded parameters, then paste the result back in here to confirm it decodes to exactly what you meant.

What this page does

  • Reads bracket notation the way qs and req.query do — nested objects, tags[] arrays, and indexed tags[0] arrays all reconstruct correctly.
  • Detects a full URL and parses only its query part, stripping any #fragment rather than treating it as data.
  • Keeps every value a string unless you explicitly turn on number and boolean guessing, and even then refuses to convert anything that would change value — a 19-digit reference number is never rounded.
  • Collapses a repeated flat key into an array, matching what a browser sends for a group of same-named form inputs.
  • Runs entirely in your browser — nothing you paste is sent anywhere, which matters for a format built to carry session tokens.

Questions people actually ask

Why did two values with the same key turn into an array?

Because a query string can legally repeat a key, and the only sensible reading of a=1&a=2 is a list, not "the second one wins." This matches qs and URLSearchParams's getAll() — see MDN's getAll documentation for the same behaviour from the other direction.

Why is 42 coming out as the string "42" instead of a number?

Because that is what is actually in a query string — there is no number type to read it as. Turn on Guess numbers and booleans if you specifically want numeric-looking values converted; it stays off by default because a reference code like 00042 or a phone number would silently lose its structure if we guessed for you.

My key has brackets but they got treated as a plain key. Why?

Almost certainly an unmatched bracket somewhere in the key — a stray [ with no closing ], most often from copying a URL out of a chat client that line-wrapped it. The output note says when a key like this was kept literally instead of parsed.

Can I paste a whole URL instead of just the query string?

Yes. Paste https://api.example/v1/subscribers?msisdn=... and only the part after the first ? is read, with anything after a # dropped since a fragment is never sent to the server. If you want the rest of the URL broken down too — scheme, host, path — the URL Parser does that.

Does this handle the same query string a PHP backend would build?

For the common cases, yes — PHP's own parse_str uses the same bracket convention for nesting and arrays that qs does, which is why this notation shows up across so many stacks rather than being tied to one framework.

Related tools

Specifications and references