Query string arrays and repeated params
You need to pass a list of values in a URL, so you put several in the query string, and the other side reads back something you did not expect. The reason is that there is no single standard for how arrays are encoded in a query string. Different conventions exist, and different frameworks parse them differently.
The three common conventions
Say you want to send the values red, green, and blue for a color parameter. You will see all three of these in the wild.
?color=red&color=green&color=blue repeated key
?color[]=red&color[]=green&color[]=blue bracket notation
?color=red,green,blue comma separated
- Repeated key lists the same key multiple times. It is the most widely supported and the only one the URL standard itself describes.
- Bracket notation appends
[]to the key. Popular in PHP and in libraries like qs, but the brackets should be percent encoded and not every parser understands them. - Comma separated packs values into one parameter. Compact, but it breaks the moment a value legitimately contains a comma, and the server has to know to split.
None of these is more correct than the others at the URL level. The query string is just text; the meaning is a convention agreed between client and server.
How URLSearchParams handles repeats
The browser's built in URLSearchParams follows the repeated key convention and gives you two methods for it.
const params = new URLSearchParams("color=red&color=green&color=blue");
params.get("color"); // "red" — first value only
params.getAll("color"); // ["red", "green", "blue"] — the full list
The trap is get, which returns only the first match and silently drops the rest. Use getAll whenever a key may repeat. Note also that URLSearchParams treats color[] as a literal key named color[], with no special meaning, so bracket notation is up to you to parse.
Server frameworks differ
The same query string can arrive as different shapes depending on the stack.
| Convention | Express (qs) | Rails | Go net/url |
|---|---|---|---|
color=red&color=green | array | array | array via Query()["color"] |
color[]=red&color[]=green | array | array | key is literally color[] |
color=red,green | single string | single string | single string |
Express with its default qs parser and Rails both understand bracket notation and build arrays from it. Go's standard library does not treat brackets specially and gives you the repeated key array through Query()["color"]. Comma separated always arrives as one string unless you split it yourself.
Pick one and be explicit
Because there is no universal rule, the safe approach is to agree on a convention and document it. Repeated keys are the most portable, so prefer them unless a framework pushes you toward brackets.
When a URL is not behaving as expected, breaking it apart shows exactly what the query string contains. The URL Tools parse a URL into its parts and list every query parameter, including repeats, entirely in your browser so the URL never leaves your device. For the underlying rules of what characters are legal, see URL encoding explained, and for the full anatomy of a URL, parse a URL into its parts.
The takeaway: arrays in query strings are a convention, not a standard. Choose repeated keys for portability, read them with getAll, and check how your server framework parses before you rely on a shape.