Skip to content

Express Request Body

Whenever a client sends data with a POST, PUT, or PATCH request, that data arrives as the request body. This lesson explains how Express exposes it through req.body, and why it doesn't work automatically.

Why req.body Needs Middleware

At the network level, a request body is just a raw stream of bytes. Express does not parse this stream into a usable JavaScript object by default, you must register body-parsing middleware, most commonly express.json() for JSON bodies, before your routes can read req.body.

Without that middleware, req.body is undefined, and attempting to read a property off it (req.body.email) throws a runtime error.

const express = require('express');
const app = express();

app.use(express.json()); // parses application/json bodies

app.post('/users', (req, res) => {
  console.log(req.body); // { email: 'ada@example.com' }
  res.status(201).json(req.body);
});

express.json() reads the raw request stream, parses it as JSON, and attaches the resulting object to req.body before your route runs.

Registering Body Parsers

app.use(express.json());                 // Content-Type: application/json
app.use(express.urlencoded({ extended: true })); // form submissions
app.use(express.text());                 // plain text bodies
app.use(express.raw());                  // raw Buffer bodies
  • Register body parsers before any route that needs to read req.body.
  • express.json() and express.urlencoded() have shipped inside Express itself since version 4.16.
  • The Content-Type header determines which body a client is sending, and which parser applies.
  • You can register multiple parsers together to support several content types.

Request Body Cheatsheet

Body parsers and the content types they handle.

Content-Type Middleware req.body Result
application/json express.json() Parsed JS object
application/x-www-form-urlencoded express.urlencoded({ extended: true }) Parsed JS object
text/plain express.text() String
application/octet-stream express.raw() Buffer
multipart/form-data Neither, use multer Not parsed by built-ins

Reading and Validating the Body

Even once req.body is populated, it is still client-provided data and should never be trusted blindly. Always check required fields exist before using them (or use a validation library, covered in the Validation lesson).

app.post('/users', (req, res) => {
  const { email, password } = req.body;

  if (!email || !password) {
    return res.status(400).json({ error: 'email and password are required' });
  }

  res.status(201).json({ email });
});

Limiting Body Size

By default, Express limits JSON and urlencoded body size to 100kb, protecting your server from excessively large payloads. You can adjust this per project needs, but should rarely raise it without good reason.

app.use(express.json({ limit: '1mb' }));

Common Mistakes

  • Reading req.body before registering express.json()/express.urlencoded().
  • Sending JSON from the client but forgetting the Content-Type: application/json header, causing Express to skip parsing it.
  • Trusting req.body fields without validating their presence or type.
  • Raising the body size limit far beyond what the endpoint actually needs, opening the door to abuse.

Key Takeaways

  • req.body requires explicit parsing middleware, it is not populated automatically.
  • express.json() and express.urlencoded() cover the two most common content types.
  • The client's Content-Type header determines which parser actually processes the body.
  • Always validate body fields before trusting or persisting them.

Pro Tip

If req.body is unexpectedly undefined in a POST route, check three things in order: is express.json() registered before the route, is the client sending the right Content-Type header, and is the body actually valid JSON.