fetch in Node

The Standard HTTP Client — Same as the Browser

fetch in Node

Node 18+ ships a built-in fetch. Same API as the browser, no `axios` or `node-fetch` needed.

3 min read Level 1/5 #nodejs#fetch#http
What you'll learn
  • Make GET and POST requests
  • Send/receive JSON
  • Handle errors and timeouts

Node 18+ has the same fetch API browsers use. No more axios or node-fetch for outbound HTTP — built-in works.

GET JSON

const res = await fetch("https://api.github.com/users/anthropics");
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
console.log(data.name);

fetch returns a Response. Check res.ok (status 200–299) before parsing.

POST JSON

const res = await fetch("https://api.example.com/users", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ name: "Ada", email: "ada@example.com" }),
});

if (!res.ok) throw new Error(`HTTP ${res.status}`);
const created = await res.json();

Headers + Auth

const res = await fetch(url, {
  headers: {
    "authorization": `Bearer ${token}`,
    "user-agent":    "my-app/1.0",
  },
});

Timeouts

AbortSignal.timeout(ms) is the standard way:

try {
  const res = await fetch(url, { signal: AbortSignal.timeout(5_000) });
} catch (err) {
  if (err.name === "AbortError") console.error("timed out");
  else throw err;
}

Streams

Treat the response body as a stream for large downloads:

import { createWriteStream } from "node:fs";
import { Readable } from "node:stream";

const res = await fetch("https://example.com/huge.zip");
const stream = createWriteStream("huge.zip");
await Readable.fromWeb(res.body).pipe(stream);

fetch body is a Web ReadableStream; Node has Readable.fromWeb to convert.

File Uploads (multipart)

const form = new FormData();
form.append("file", new Blob([fileContent]), "report.pdf");
form.append("title", "Q3");

await fetch("https://api.example.com/upload", { method: "POST", body: form });

FormData and Blob are global in Node 18+. No form-data lib needed.

When You Outgrow fetch

For complex needs (HTTP/2, connection pooling, retries), undici is what powers Node’s built-in fetch — you can use it directly for advanced cases.

HTTPS & TLS →