Anatomy of the Request Object

The fastest way to learn req is to print it. Below is a real Express 5.2.1 24,430 response.

A route that reports what Express parsed out of the requestJavaScript
app.get('/books/:id/reviews/:rid', (req, res) => {
  res.json({ originalUrl: req.originalUrl, baseUrl: req.baseUrl, path: req.path,
             params: req.params, query: req.query, host: req.host,
             hostname: req.hostname, ip: req.ip, xhr: req.xhr });
});
Output
$ curl -s "http://localhost:4331/books/42/reviews/7?fields=title&sort=-year"
{"originalUrl":"/books/42/reviews/7?fields=title&sort=-year","baseUrl":"",
 "path":"/books/42/reviews/7","params":{"id":"42","rid":"7"},
 "query":{"fields":"title","sort":"-year"},"host":"localhost:4331",
 "hostname":"localhost","ip":"::1","xhr":false}

req.url is Node's raw target and is rewritten as a request enters a mounted router, so log req.originalUrl instead. req.baseUrl is the router's mount prefix (empty here, /api/books inside app.use('/api/books', router)) and req.path drops the query string.

The request properties you will use most often
Property What it holds
req.method, req.originalUrl Method; the URL as the client sent it
req.params, req.query Placeholders and query, values are strings
req.body Parsed body, undefined until a parser runs
req.headers, req.get(name) Raw headers; case-insensitive lookup
req.protocol, req.secure "http" or "https"; true under TLS
req.host, req.hostname, req.ip Host with port; without port; client address
req.fresh, req.xhr Validators match; X-Requested-With was set

Two changed in Express 5. req.host used to strip the port and now keeps it, so localhost:4331 is the whole Host header while req.hostname is the port-free form. And req.param(name), which searched params, then body, then query, was removed — it hid where a value came from.

req.query is now a getter, and the default query parser changed from extended to simple, Node's own querystring. Simple parsing collapses repeated keys into an array but builds no nested objects, so ?tag=node&tag=api&page[size]=10 yields {"tag":["node","api"],"page[size]":"10"}; app.set('query parser', 'extended') restores qs parsing and returns "page":{"size":"10"}.