An incoming request carries data in three places: the query string, the route path, and the body. Here’s how to read each in Node.js and Express — req.query, req.params, req.body — including how they’re decoded and how to handle webhook payloads safely.
| Source | Example | Express |
|---|---|---|
| Query string | ?q=hello&page=2 | req.query |
| Route params | /users/:id | req.params |
| Request body | POST JSON / form | req.body |
In Express, req.query is already parsed and decoded:
app.get('/search', (req, res) => {
req.query.q; // "hello" (decoded)
req.query.page; // "2"
res.json(req.query);
});
In a raw Node server there’s no req.query — parse it yourself with the URL class:
const http = require('node:http');
http.createServer((req, res) => {
const url = new URL(req.url, `http://${req.headers.host}`);
const q = url.searchParams.get('q'); // one value
const all = Object.fromEntries(url.searchParams); // object
res.end(JSON.stringify(all));
}).listen(3000);
Named segments in the route become req.params. Express decodes them for you:
app.get('/users/:id/posts/:postId', (req, res) => {
req.params.id; // "42"
req.params.postId; // "7"
});
The body isn’t parsed unless you add middleware. For JSON and form bodies:
app.use(express.json()); // application/json
app.use(express.urlencoded({ extended: true })); // x-www-form-urlencoded
app.post('/submit', (req, res) => {
req.body.username; // from JSON or form body
});
By default Express turns ?tag=a&tag=b into an array: req.query.tag === ["a","b"]. If a client sends a single value, it’s a string — so normalize before you rely on it:
const tags = [].concat(req.query.tag || []); // always an array
Incoming webhook parameters are attacker-controllable. Never interpolate them into a shell command, SQL query, or file path unescaped, and verify any signature the sender provides before acting. Our decode-then-validate guide covers hardening request input.
To see how a request’s query string breaks down, paste it into the query string parser.
Written and maintained by the urlencodedecode.com team. Every technical claim on this page is verified against primary sources — the RFCs (3986, 3629, 4648, 7578), the WHATWG URL Standard, and official vendor or language documentation — rather than second-hand summaries. When a source contradicts a common assumption, we follow the source and note the discrepancy. Corrections: contactus@urlencodedecode.com.
In Express, use req.query — it's already parsed and decoded, so req.query.q returns the value of ?q=. In a raw http server, parse req.url with the URL class and read url.searchParams.get(key).
req.query holds the query-string parameters (?q=hello), req.params holds named route segments (/users/:id), and req.body holds the POST body (JSON or form data, once you add express.json or express.urlencoded middleware).
Express doesn't parse the request body by default. Add express.json() for JSON bodies and express.urlencoded({ extended: true }) for form-encoded bodies before your routes, and req.body will be populated.
Express parses repeated keys into an array, so req.query.tag becomes ["a","b"]. A single occurrence stays a string, so normalize with [].concat(req.query.tag || []) when you need to always treat it as an array.
Yes. Express's req.query and the URL class's searchParams both percent-decode values for you, and treat + as a space in the query string. You don't need to call decodeURIComponent yourself.