`res.send`, `res.json`, `res.status`, `res.redirect`
The Response Object
Everything you need to reply to a request — status codes, headers, bodies, redirects.
What you'll learn
- Use res.send and res.json correctly
- Set status codes and headers
- Redirect and stream
res is the toolkit for replying. Here are the methods you’ll use
every day.
res.send() — Most Things
res.send("Hello"); // text/html
res.send({ name: "Ada" }); // JSON (sets Content-Type)
res.send(Buffer.from("...")); // binary
res.send([1, 2, 3]); // JSON array send picks the right Content-Type for you. Convenient — but
when you specifically want JSON, prefer res.json():
res.json() — Explicit JSON
res.json({ id: 1, name: "Ada" }); Always sets Content-Type: application/json. Use this for API
endpoints — clearer intent than send.
res.status() — Status Codes
Chainable:
res.status(201).json({ id: 1 });
res.status(204).end();
res.status(404).json({ error: "not found" }); Common ones:
| Code | Meaning |
|---|---|
| 200 | OK (default) |
| 201 | Created |
| 204 | No Content |
| 301 / 302 | Redirect |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 409 | Conflict |
| 422 | Unprocessable Entity |
| 500 | Internal Server Error |
res.set() — Headers
res.set("Cache-Control", "max-age=60");
res.set("X-Request-Id", reqId);
res.set({
"Content-Type": "text/plain",
"X-Powered-By": "my-api",
}); res.redirect() — Redirects
res.redirect("/login"); // 302
res.redirect(301, "/new-permanent"); // 301
res.redirect(303, "/check-email"); // 303 res.cookie() and res.clearCookie()
res.cookie("session", token, {
httpOnly: true,
secure: true,
sameSite: "lax",
maxAge: 24 * 60 * 60 * 1000,
});
res.clearCookie("session"); res.sendFile() — Stream a File
import path from "node:path";
res.sendFile(path.resolve("./reports/q3.pdf")); Streams the file with the right Content-Type and Content-Length. Good for downloads.
res.download() — Force Download
res.download("./reports/q3.pdf", "Q3-Report.pdf"); Sets Content-Disposition: attachment so the browser saves rather
than displays.
Don’t res.end() Twice
Once a response is sent, you can’t add to it. Calling another res.*
method after res.json(...) throws. Always return after sending:
if (!user) {
return res.status(404).json({ error: "not found" });
}
res.json(user);