Menu

Express req.params, req.query and req.body Explained

req.params holds the named parts of the path (/users/:id), req.query the query string (?sort=new), and req.body the parsed request body, which is undefined until you add a body parser such as express.json().

This page includes runnable editors. Edit, run, and see output instantly.

In Express, req.params holds the values of named segments in the route path (/users/:id gives req.params.id), req.query holds the query string after the ? (/search?q=node gives req.query.q), and req.body holds the data sent in the request body. req.params and req.query are filled on every request, but req.body stays undefined until a body parser such as app.use(express.json()) reads it. Values in params and query are always strings.

The first request answers {"params":{"userId":"7"},"query":{"sort":"new","limit":"2"}}. Note the quotes: 7 and 2 are strings, so convert them with Number() before you do math or compare with numbers. Now switch the method to POST, keep the path /users/7/posts and send the body {"title": "Hello", "draft": true}: the answer is 201 with "body":{"title":"Hello","draft":true}, where true is a real boolean because it came from JSON.

req.params vs req.query vs req.body

req.paramsreq.queryreq.body
Comes fromThe path, /users/:idThe query string, ?sort=newThe request body
Example URL or body/users/7/users?sort=new{"name": "Ada"}
Value{ id: '7' }{ sort: 'new' }{ name: 'Ada' }
TypesStringsStrings and arrays of stringsWhatever the JSON holds
Needs setupA :name in the routeNothingapp.use(express.json())
Typical useWhich resourceFilter, sort, pageData to create or update

A route can have several parameters, and each name becomes a key of req.params: /teams/:teamId/members/:memberId gives both ids. A hyphen or a dot also separates them, so /flights/:from-:to turns /flights/LAX-SFO into { from: 'LAX', to: 'SFO' }.

req.query with repeated and missing keys

A key that appears twice becomes an array, and a key that is missing is undefined, so give options a default:

The answer is {"page":1,"tags":["red","sale"],"raw":{"tag":["red","sale"]}}. Send GET /products?tag=red&page=3 and tags is still an array, ["red"], because [].concat() turns one string or an array into an array. Express 5 parses query strings with Node's simple parser, so ?filter[size]=m gives the key "filter[size]", not a nested object; Express 4 nested it.

req.body needs express.json()

Node delivers the body as a stream of bytes. express.json() reads it, parses it, and sets req.body, but only when the request has Content-Type: application/json. HTML forms send application/x-www-form-urlencoded, which needs express.urlencoded() instead.

Send POST /signup with the body {"email": "ada@example.com"} and you get 201 with {"email":"ada@example.com","name":"anonymous"}. Send an empty body and you get 400. The ?? {} matters: without it, destructuring undefined throws a TypeError on any request that has no JSON body. For real validation of the shape and types, use a schema library such as zod.

req.headers and req.get()

req.headers is an object of every request header, with lowercase names. req.get(name) reads one header and ignores case, so req.get('Content-Type') and req.get('content-type') return the same value. A few other properties you will use:

path is /whoami and originalUrl is /whoami?debug=1. Add the header Authorization: Bearer abc in the request bar and send it again: token becomes "Bearer abc". Inside a router mounted with app.use('/api', router), req.path loses the /api prefix while req.originalUrl keeps it (Express routing explains mounting).

Common mistakes

Reading req.body on a GET request. Browsers and most clients send no body with GET. Put GET options in the query string.

Testing a query flag for truthiness. ?admin=false gives the string 'false', which is truthy, so if (req.query.admin) passes. Compare strings: req.query.admin === 'true'.

Sending JSON without the header. A client that posts JSON as text/plain gets req.body === undefined. Set Content-Type: application/json on the client.

Frequently Asked Questions

How do I get the client's IP address in Express?

Read req.ip. Behind a proxy or load balancer it is the proxy's address until you set app.set('trust proxy', 1), which makes Express read the X-Forwarded-For header instead.

How do I get the full URL of a request in Express?

req.originalUrl is the path plus the query string as the client sent it. Build the absolute URL with `${req.protocol}://${req.get('host')}${req.originalUrl}`.

How do I handle file uploads in Express?

File uploads arrive as multipart/form-data, which express.json() and express.urlencoded() do not parse. Use a package such as multer, which puts the files in req.file or req.files and the other fields in req.body.

How do I read a cookie from the request?

The raw header is in req.get('cookie'). To get an object in req.cookies, install the cookie-parser package and add app.use(cookieParser()).

Coddy programming languages illustration

Learn to code with Coddy

Get started