Query String Anatomy
https://example.com/search?q=hello+world&lang=en&page=2
↑ starts with ?
↑──────── key=value pairs, separated by &
The query string begins after ? and ends before # (the fragment). Each parameter is a key=value pair. Values are percent-encoded (with spaces often encoded as + in form data).
URLSearchParams — The Right Way
// Build a query string
const params = new URLSearchParams();
params.append("q", "hello world"); // auto-encodes
params.append("lang", "en");
params.append("page", "2");
params.toString(); // "q=hello+world&lang=en&page=2"
// Or from an object
const params = new URLSearchParams({ q: "hello world", lang: "en" });
// Read from current page URL
const params = new URLSearchParams(window.location.search);
params.get("q"); // "hello world" (decoded)
params.has("lang"); // true
params.getAll("tag"); // array — useful for multi-value params
// Append to existing URL
const url = new URL("https://example.com/search");
url.searchParams.set("q", userInput); // safe — no injection possible
console.log(url.toString());
Multi-Value Parameters
// Multiple values for same key
?tag=javascript&tag=typescript&tag=css
const params = new URLSearchParams("tag=javascript&tag=typescript&tag=css");
params.getAll("tag"); // ["javascript", "typescript", "css"]
// Building multi-value
const params = new URLSearchParams();
["javascript", "typescript"].forEach(t => params.append("tag", t));
Nested Objects in Query Strings
URLSearchParams does not support nested objects natively. For complex structures, libraries use different conventions:
// Common conventions for nested objects:
// Bracket notation (PHP/Rails style)
?filter[status]=active&filter[role]=admin
// Dot notation
?filter.status=active&filter.role=admin
// JSON-encoded value (simple but ugly)
?filter=%7B%22status%22%3A%22active%22%7D
// qs library handles nested objects
import qs from "qs";
qs.stringify({ filter: { status: "active", role: "admin" } });
// "filter%5Bstatus%5D=active&filter%5Brole%5D=admin"
qs.parse("filter[status]=active");
// { filter: { status: "active" } }
In Node.js / Server Frameworks
// Express — req.query is auto-parsed
app.get("/search", (req, res) => {
const { q, page = "1" } = req.query;
// q is already decoded
});
// Node.js built-in
import { parse } from "querystring"; // deprecated
import { URLSearchParams } from "url"; // preferred
Parse & Build Query Strings Instantly
Use ToolsVito's Query String ↔ JSON tool to parse any query string to a JSON object or build a query string from JSON — in your browser.