Query String Parser

Read every parameter in a link — or build a query string from a JSON object — without leaving the page.

Runs on your deviceDeveloperWorkingNo account needed

What this tool does

Query String Parser takes everything after the first ? in whatever you paste — a whole URL, a bare querystring, or a fragment lifted out of a server log — splits it on &, percent-decodes each name and each value, and lists the result as a two-column table in the order the link wrote them. A name that appears twice gets two rows rather than one, and a name written with no = at all is listed as (no value), so the difference between flag= and flag is on screen instead of guessed at.

Three settings shape the parse, and only one of them changes the table. Treat + as a space is on by default: form-encoded links write news+letter where a URL-encoded one writes news%20letter, and only you know which convention produced the link in front of you. Expand bracket notation and Repeated keys act on a structured object the parse builds behind the table and the page does not display. Brackets show up indirectly, in that filter[price][max] and filter[colour] then count as one distinct key in the summary line rather than two. The Repeated keys choice between an array, the first value and the last changes nothing visible at all: the table lists every occurrence either way, and the distinct-key count is the same for all three.

Switch Direction to JSON object → query string and it runs the other way. Paste a flat object such as {"q":"flat white","tag":["a","b"],"page":2} and you get q=flat%20white&tag=a&tag=b&page=2: array values repeat the name, numbers and booleans become their text, and null becomes an empty value. Encoding is percent escapes throughout, so a space is always %20 and never +, and the string comes back with no leading ? so it can be appended to whatever you already have. One level of nesting is handled — {"a":{"b":"c"}} is written as a%5Bb%5D=c, which this tool reads back as nesting — but a second level is not: the inner object is stringified before escaping, so the value arrives as %5Bobject%20Object%5D. Flatten before you paste.

The work happens in this browser tab and nothing is uploaded, which counts for more here than it looks: query strings are where session tokens, signed expiry parameters, email addresses and internal hostnames end up. Three details decide whether the rows you see are the whole story. Only & separates pairs, so the older semicolon convention is not recognised and a;b=1 is read as one parameter named a;b. A # ends the query, but only when a ? came before it — in a hash-routed address such as /#/dashboard?tab=2 the first ? sits inside the fragment, so those parameters are parsed like any others and no fragment is reported. And a value that is not valid percent-encoding, a stray %zz say, is left exactly as it stands rather than stopping the run.

How to use it

  1. Paste the link or the query string. A whole URL, or just the part after the ?. Press Load sample for a link carrying a repeated name, a bracketed filter and a + used as a space.
  2. Set + handling to match the source. Leave Treat + as a space on for form-encoded links. Turn it off when a genuine plus sign belongs to the value, as it does in an email address.
  3. Adjust the structure options if the count matters. Expand bracket notation folds filter[price][max] and filter[colour] into a single distinct key in the summary. Repeated keys shapes the object behind the table, so it moves no number you can read.
  4. Read the rows, or copy them as CSV. Parameters come back one row each, in the order written. Copy hands you those same rows as comma-separated text, which pastes straight into a spreadsheet or a ticket.
  5. Run it backwards when you need to. Switch Direction to JSON object → query string, paste a flat object, and the output pane holds the encoded string ready to append to a path.

Processing & privacy

Runs on your device. Your file is processed directly in this browser.

Common use cases

Debugging a campaign link

utm_source, utm_medium and utm_campaign are easy to duplicate or misspell. One row per parameter shows the tag that got written twice with two different values.

Reading a redirect or callback URL

OAuth and payment returns pack state, a nonce and an encoded destination into one line. Decoding turns %3A%2F%2F back into :// so the nested address becomes readable.

Checking what a GET form actually submitted

The url params are the whole request. The table shows which fields arrived empty, which arrived twice, and which never arrived at all.

Assembling a request by hand

Build direction takes an object you already have in a test fixture and returns the encoded string, without hand-escaping every space and ampersand.

Questions

Does the link get uploaded?
No. Parsing and building both run in this browser tab, so a link carrying a session token, a signed expiry or a customer's email address is not transmitted, logged or stored, and the tool goes on working with the network disconnected.
Why does it say no query string was found?
Because there was nothing after the ? — either the address carries no query at all, or it stops at the ?. A bare query string is fine on its own: a=1&b=2 parses with no ? in front of it, and a line with neither a ? nor a scheme is read as one parameter with no value.
Does the Repeated keys setting change the table?
No, and it changes nothing else you can see either. Every occurrence is listed in the order written, so tag=a&tag=b is two rows whichever option you pick, and the summary reports one distinct key for all three. The setting shapes the structured object the parse builds internally, which this page does not show.
Are numbers returned as numbers?
No. A query string carries text and nothing else, so page=2 is the two-character string 2 and flag=false is the word false. Nothing is coerced, because guessing a type wrong is worse than leaving the conversion to you.
What happens to a fragment?
Everything from a # onwards is cut off and quoted in the summary rather than parsed, so a=1#b=2 lists one parameter and reports the fragment b=2. The exception is an address whose only ? sits inside the fragment, as hash-routed apps write it: there the ? is read as the start of the query and the parameters after it are listed normally.
Can it build nested parameters?
One level only. {"a":{"b":"c"}} is encoded as a%5Bb%5D=c, which this tool reads back as nesting while Expand bracket notation is on. A second level is not encoded at all — the inner object is stringified first, so the value arrives as %5Bobject%20Object%5D — meaning deeper structures have to be flattened before building.
How is this different from URL Parser?
URL Parser splits a whole address into scheme, host, port, path and fragment and lists the parameters flat beneath them. This one starts at the ?, so it suits the case where the query itself is what you are debugging, and it also runs in reverse to turn a JSON object back into an encoded string.

Related tools