HTTP and Fetch
Built-in HTTP server and fetch client patterns for APIs and microservices. Results appear in the same fence: same-line // comments when short, multiline // blocks below the sample when not.
Search across all documentation pages
Built-in HTTP server and fetch client patterns for APIs and microservices. Results appear in the same fence: same-line // comments when short, multiline // blocks below the sample when not.
Minimal HTTP server with the built-in module.
import http from "node:http";
const server = http.createServer((req, res) => {
res.writeHead(200, { "content-type": "text/plain" });
res.end("ok");
});
// server.listen(3000) -> GET / responds "ok"
typeof server.listen // "function"Global fetch (undici) is available in modern Node for outbound HTTP.
const res = await fetch("data:application/json,{\"ok\":true}");
res.ok // true
await res.json()
// { ok: true }Send JSON with method, headers, and stringified body.
const body = JSON.stringify({ name: "Ada" });
JSON.parse(body).name // "Ada"
// await fetch(url, {
// method: "POST",
// headers: { "content-type": "application/json" },
// body,
// });Read incoming headers on the server; treat them as lowercase names.
import http from "node:http";
// inside createServer:
// const auth = req.headers.authorization;
const headers = { authorization: "Bearer x" };
headers.authorization // "Bearer x"Use the WHATWG URL API for paths and search params.
const u = new URL("/items?page=2", "http://localhost");
u.pathname // "/items"
u.searchParams.get("page") // "2"Cancel slow clients with AbortSignal timeouts.
const signal = AbortSignal.timeout(5_000);
signal.aborted // false
// await fetch(url, { signal });Consume a fetch body as text, JSON, or arrayBuffer.
const res = await fetch("data:text/plain,hello");
await res.text() // "hello"Set multiple cookies by calling append on Headers.
const headers = new Headers();
headers.append("set-cookie", "a=1; Path=/");
headers.append("set-cookie", "b=2; Path=/");
headers.getSetCookie?.().length ?? [...headers].filter(([k]) => k === "set-cookie").length
// 2Use https or fetch for TLS; configure certs via env or undici options when needed.
import https from "node:https";
typeof https.get // "function"
// https.get("https://example.com", (res) => res.pipe(process.stdout));Read and parse a JSON body from an IncomingMessage carefully with size limits in production.
async function readJson(chunks: Buffer[]) {
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
}
await readJson([Buffer.from('{"a":1}')])
// { a: 1 }Always end the response; use correct status codes for errors.
const payload = JSON.stringify({ error: "not_found" });
payload // '{"error":"not_found"}'
// res.writeHead(404, { "content-type": "application/json" });
// res.end(payload);HTTP keep-alive is default - set timeouts for hanging sockets.
import http from "node:http";
const server = http.createServer();
server.keepAliveTimeout = 5_000;
server.headersTimeout = 6_000;
server.keepAliveTimeout // 5000Multipart uploads use FormData with fetch.
const form = new FormData();
form.set("name", "Ada");
form.get("name") // "Ada"
// form.set("file", new Blob([buf]), "a.bin");
// await fetch(url, { method: "POST", body: form });Tune connection pooling via undici Agent for high-volume clients when defaults are insufficient.
// import { Agent, setGlobalDispatcher } from "undici";
// setGlobalDispatcher(new Agent({ connections: 32 }));
// pools keep-alive connections to the same hostWebSockets are available via undici/ws ecosystems - pick one stack and stick to it.
// const ws = new WebSocket("ws://localhost:3000");
// ws.addEventListener("message", (ev) => console.log(ev.data));
typeof WebSocket !== "undefined" // true on modern NodeStack versions: Node.js 24.18.0 (LTS line 24) · TypeScript 5.6+ · npm 10+
Reviewed by Chris St. John·Last updated Jul 18, 2026