fetch

fetch() performs HTTP requests and returns a Promise for a Response. Together with the Headers, Request, and Response classes it provides the WHATWG Fetch API for talking to HTTP services.

  • fetch(url, options) starts a request. Common options: method, headers, body, signal (an AbortSignal).
  • Response exposes status, statusText, headers, and body readers: text(), json(), blob(), bytes(), arrayBuffer().
  • Request describes an outgoing request and can be passed directly to fetch().
  • Headers is a case-insensitive, ordered map of header names and values. getSetCookie() returns individual Set-Cookie values.

Usage#

A JSON API call:

const response = await fetch("https://api.example.com/users/1");
if (!response.ok) {
  throw new Error(`HTTP ${response.status}`);
}
const user = await response.json();

Posting a JSON body:

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

Custom headers and error handling:

const response = await fetch("https://api.example.com/feed", {
  headers: new Headers({ authorization: `Bearer ${token}` }),
});
console.log(response.headers.get("content-type"));

Options beyond method/headers/body/signal:

const response = await fetch("https://example.com/api", {
  redirect: "follow", // "follow" | "error" | "manual"
  follow: 20, // maximum redirects to follow
  compress: true, // decompress gzip, deflate, br responses
});

Cancelling a request with an AbortController:

const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
const response = await fetch("https://api.example.com/slow", {
  signal: controller.signal,
});

A request body that is a ReadableStream requires duplex: "half":

const body = new ReadableStream({
  start(controller) {
    controller.enqueue(new TextEncoder().encode("streamed"));
    controller.close();
  },
});

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

Streaming a response body chunk by chunk:

const response = await fetch("https://example.com/large.txt");
for await (const chunk of response.body) {
  // chunk is a Uint8Array
  total += chunk.byteLength;
}

Handling errors#

Network failures reject with TypeError("Failed to fetch"). The underlying cause, such as a DNS failure or refused connection, is not exposed.

Aborting rejects with a DOMException named "AbortError". Check err.name === "AbortError".

Differences from the standard#

  • URLs must be absolute. Scripts do not run in a page, so there is no base URL for resolving a relative path. Only http: and https: URLs are supported; relative and data: URLs reject.
  • Response headers expose Set-Cookie values. GearTrain jobs run on the server, where scripts commonly need to inspect cookies; browsers hide this header from scripts.
  • A run can make at most 50 fetch calls. The counter resets each run.
  • Response body chunks are batched, so chunk boundaries are not guaranteed. Do not assume one server write per reader.read(); split on your own delimiters.
  • Requests time out after 30 seconds of inactivity. Use an AbortController for custom timeouts.
  • Requests to private or internal IP addresses, localhost, and cloud metadata endpoints are blocked to protect internal networks.
  • BYOB readers are not available for every body source. Use a default reader unless the body is an in-memory buffer.
  • The redirect, follow, and compress options are extensions and not part of the standard.

Documentation#