The Request Object
Express's req object extends Node's raw IncomingMessage with a wealth of convenient properties and helper methods — parsed params, query, body, cookies, content negotiation, and more. Everything the raw object had is still there; Express just adds the conveniences you'd otherwise build yourself. This page is the reference tour.
The most-used properties
Property | What it holds |
|---|---|
| Route parameters — |
| Parsed query string — |
| Parsed body (needs body-parser middleware) |
| 'GET', 'POST', … |
| Path without query string — |
| Full original URL incl. query |
| All request headers (lowercased) |
| Parsed cookies (needs |
| Client IP address |
| 'http' or 'https' |
| Host from the |
req.body needs middleware
app.use(express.json()) // JSON bodies → req.body
app.use(express.urlencoded({ extended: true }))// form bodies → req.body
app.post('/users', (req, res) => {
const { name } = req.body // now populated
res.status(201).json({ name })
})Helper methods
Method | Returns |
|---|---|
| A header value (case-insensitive) |
| Best matching type the client accepts, or false |
| Whether the request's Content-Type matches |
| Look up params/body/query (legacy — avoid) |
req.get('Content-Type') // 'application/json'
req.get('user-agent') // case-insensitive header lookup
// Content negotiation — serve JSON or HTML based on what the client wants:
if (req.accepts('html')) {
res.render('user', user)
} else if (req.accepts('json')) {
res.json(user)
}
req.is('application/json') // truthy if the body is JSONClient IP and proxies
// Trust the first proxy in front of the app:
app.set('trust proxy', 1)
// Or trust specific networks. Then req.ip reflects X-Forwarded-For:
app.get('/whoami', (req, res) => res.json({ ip: req.ip, ips: req.ips }))Cookies
import cookieParser from 'cookie-parser' // npm i cookie-parser
app.use(cookieParser())
app.get('/dashboard', (req, res) => {
const sessionId = req.cookies.sessionId // parsed from the Cookie header
res.json({ sessionId })
})Extending req in middleware
A core pattern: middleware attaches computed data to req so later handlers can use it. This is how authentication exposes the current user:
async function authenticate(req, res, next) {
const token = req.get('authorization')?.replace('Bearer ', '')
const user = await verifyToken(token)
if (!user) return res.status(401).json({ error: 'Unauthorized' })
req.user = user // ← downstream handlers read req.user
next()
}
app.use(authenticate)
app.get('/me', (req, res) => res.json(req.user))