What is the difference between `req.params`, `req.query`, and `req.body` in Express?
Show answer — try answering out loud first
All three bring data from the client, but from different places in the request:
req.params: the dynamic route segments, defined with:(for example/usuarios/:id→req.params.id).req.query: what comes after the?in the URL (for example?page=2→req.query.page).req.body: the body of the request (the JSON from a POST or PUT). It requires you to enableapp.use(express.json()); otherwise,req.bodyisundefined.
Think of a URL like /usuarios/42?page=2 with a JSON body:
req.params→ the part inside the route. It's used to identify which resource you want: user 42. It's defined in the path with:, like/usuarios/:id. It always arrives as a string.req.query→ the part after the?. It's used for options or filters: pagination, sorting, search...?page=2&orden=nombregives{ page: "2", orden: "nombre" }. It also arrives as a string.req.body→ it doesn't go in the URL, it travels in the request body. It's used to send large or sensitive data: the object you want to create or update. This is typical inPOSTandPUT.
Critical point about the body: Express does not read the body on its own. You need a middleware to parse it. For JSON, that's app.use(express.json()). Without that line, req.body will be undefined even if the client did send data.
Mental summary:
- params = which resource (goes in the route).
- query = how you want it (goes after the
?). - body = what data you send (goes in the body, requires
express.json()).
const express = require("express");
const app = express();
// ESSENTIAL for reading req.body as JSON!
// Without this line, req.body would be undefined.
app.use(express.json());
// Route that uses all THREE at once:
// /usuarios/:id -> req.params.id
// ?notificar=true -> req.query.notificar
// JSON body -> req.body
app.put("/usuarios/:id", (req, res) => {
const id = req.params.id; // route segment (string)
const notificar = req.query.notificar; // option after the ? (string)
const datos = req.body; // JSON body sent
res.json({
mensaje: `Actualizando usuario ${id}`,
notificar: notificar, // "true" (string, not boolean)
datosRecibidos: datos, // { nombre: "Ana Actualizada" }
});
});
// Example of what happens WITHOUT express.json() (to understand the typical error)
app.post("/sin-parser", (req, res) => {
// If you did NOT have app.use(express.json()) above,
// req.body here would be undefined and this would blow up when reading .nombre
res.json({ recibido: req.body });
});
app.listen(3000, () => {
console.log("Servidor en http://localhost:3000");
});
Testing the route that uses all three with curl:
# id=42 (params), notificar=true (query), and a JSON body with the name
curl -X PUT "http://localhost:3000/usuarios/42?notificar=true" \
-H "Content-Type: application/json" \
-d '{"nombre":"Ana Actualizada"}'
# Expected response:
# {
# "mensaje": "Actualizando usuario 42",
# "notificar": "true",
# "datosRecibidos": { "nombre": "Ana Actualizada" }
# }
Forgetting app.use(express.json()) and then wondering why req.body comes out undefined. This is probably the number one mistake juniors make with Express: you send a POST with JSON, try to read req.body.nombre, and the server blows up with "Cannot read properties of undefined". The problem isn't your route, it's that the middleware that parses the body is missing. Another related slip: not sending the Content-Type: application/json header in the request, because express.json() only parses bodies marked as JSON.
"All three bring data from the client but from different places.
req.paramsare the dynamic route segments, the ones I define with a colon, like/usuarios/:id; they're used to identify the resource.req.queryis what comes after the?, like?page=2; I use it for filters and options. Andreq.bodyis the request body, the JSON I send in a POST or PUT. The important thing about the body is that Express doesn't read it on its own: I needapp.use(express.json()), and if I forget that linereq.bodycomes outundefined. Also, params and query always arrive as strings, so if I need a number I convert it."
You have this route and you do a POST with -d '{"nombre":"Ana"}', but in the console req.body comes out undefined. What's missing?
const express = require("express");
const app = express();
app.post("/usuarios", (req, res) => {
console.log(req.body); // undefined
res.json({ creado: req.body });
});
app.listen(3000);
See answer
What's missing is registering the middleware that parses the JSON body. You need to add before the routes:
app.use(express.json());
Express doesn't read the body by default; express.json() is what interprets it and fills req.body. Without it, req.body stays undefined even if the client did send data. (You also need to make sure you send the request with the Content-Type: application/json header, because express.json() only parses bodies marked as JSON.)