MCPcopy Index your code
hub / github.com/node-fetch/node-fetch

github.com/node-fetch/node-fetch @v3.3.2

repository ↗ · DeepWiki ↗ · release v3.3.2 ↗ · + Follow
144 symbols 362 edges 25 files 21 documented · 15% 153 cross-repo links updated 54d agov2.7.0 · 2023-08-23★ 8,859192 open issues
README
<img src="https://github.com/node-fetch/node-fetch/raw/v3.3.2/docs/media/Banner.svg" alt="Node Fetch"/>

A light-weight module that brings Fetch API to Node.js.

<a href="https://github.com/node-fetch/node-fetch/actions"><img src="https://github.com/node-fetch/node-fetch/workflows/CI/badge.svg?branch=master" alt="Build status"></a>
<a href="https://coveralls.io/github/node-fetch/node-fetch"><img src="https://img.shields.io/coveralls/github/node-fetch/node-fetch" alt="Coverage status"></a>
<a href="https://packagephobia.now.sh/result?p=node-fetch"><img src="https://badgen.net/packagephobia/install/node-fetch" alt="Current version"></a>
<a href="https://www.npmjs.com/package/node-fetch"><img src="https://img.shields.io/npm/v/node-fetch" alt="Install size"></a>
<a href="https://github.com/sindresorhus/awesome-nodejs"><img src="https://awesome.re/mentioned-badge.svg" alt="Mentioned in Awesome Node.js"></a>
<a href="https://discord.gg/Zxbndcm"><img src="https://img.shields.io/discord/619915844268326952?color=%237289DA&label=Discord" alt="Discord"></a>






<b>Consider supporting us on our Open Collective:</b>






<a href="https://opencollective.com/node-fetch"><img src="https://opencollective.com/node-fetch/donate/button.png?color=blue" alt="Open Collective"></a>

You might be looking for the v2 docs

Motivation

Instead of implementing XMLHttpRequest in Node.js to run browser-specific Fetch polyfill, why not go from native http to fetch API directly? Hence, node-fetch, minimal code for a window.fetch compatible API on Node.js runtime.

See Jason Miller's isomorphic-unfetch or Leonardo Quixada's cross-fetch for isomorphic usage (exports node-fetch for server-side, whatwg-fetch for client-side).

Features

  • Stay consistent with window.fetch API.
  • Make conscious trade-off when following [WHATWG fetch spec][whatwg-fetch] and stream spec implementation details, document known differences.
  • Use native promise and async functions.
  • Use native Node streams for body, on both request and response.
  • Decode content encoding (gzip/deflate/brotli) properly, and convert string output (such as res.text() and res.json()) to UTF-8 automatically.
  • Useful extensions such as redirect limit, response size limit, [explicit errors][error-handling.md] for troubleshooting.

Difference from client-side fetch

  • See known differences:
  • If you happen to use a missing feature that window.fetch offers, feel free to open an issue.
  • Pull requests are welcomed too!

Installation

Current stable release (3.x) requires at least Node.js 12.20.0.

npm install node-fetch

Loading and configuring the module

ES Modules (ESM)

import fetch from 'node-fetch';

CommonJS

node-fetch from v3 is an ESM-only module - you are not able to import it with require().

If you cannot switch to ESM, please use v2 which remains compatible with CommonJS. Critical bug fixes will continue to be published for v2.

npm install node-fetch@2

Alternatively, you can use the async import() function from CommonJS to load node-fetch asynchronously:

// mod.cjs
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));

Providing global access

To use fetch() without importing it, you can patch the global object in node:

// fetch-polyfill.js
import fetch, {
  Blob,
  blobFrom,
  blobFromSync,
  File,
  fileFrom,
  fileFromSync,
  FormData,
  Headers,
  Request,
  Response,
} from 'node-fetch'

if (!globalThis.fetch) {
  globalThis.fetch = fetch
  globalThis.Headers = Headers
  globalThis.Request = Request
  globalThis.Response = Response
}

// index.js
import './fetch-polyfill'

// ...

Upgrading

Using an old version of node-fetch? Check out the following files:

Common Usage

NOTE: The documentation below is up-to-date with 3.x releases, if you are using an older version, please check how to upgrade.

Plain text or HTML

import fetch from 'node-fetch';

const response = await fetch('https://github.com/');
const body = await response.text();

console.log(body);

JSON

import fetch from 'node-fetch';

const response = await fetch('https://api.github.com/users/github');
const data = await response.json();

console.log(data);

Simple Post

import fetch from 'node-fetch';

const response = await fetch('https://httpbin.org/post', {method: 'POST', body: 'a=1'});
const data = await response.json();

console.log(data);

Post with JSON

import fetch from 'node-fetch';

const body = {a: 1};

const response = await fetch('https://httpbin.org/post', {
    method: 'post',
    body: JSON.stringify(body),
    headers: {'Content-Type': 'application/json'}
});
const data = await response.json();

console.log(data);

Post with form parameters

URLSearchParams is available on the global object in Node.js as of v10.0.0. See official documentation for more usage methods.

NOTE: The Content-Type header is only set automatically to x-www-form-urlencoded when an instance of URLSearchParams is given as such:

import fetch from 'node-fetch';

const params = new URLSearchParams();
params.append('a', 1);

const response = await fetch('https://httpbin.org/post', {method: 'POST', body: params});
const data = await response.json();

console.log(data);

Handling exceptions

NOTE: 3xx-5xx responses are NOT exceptions, and should be handled in then(), see the next section.

Wrapping the fetch function into a try/catch block will catch all exceptions, such as errors originating from node core libraries, like network errors, and operational errors which are instances of FetchError. See the [error handling document][error-handling.md] for more details.

import fetch from 'node-fetch';

try {
    await fetch('https://domain.invalid/');
} catch (error) {
    console.log(error);
}

Handling client and server errors

It is common to create a helper function to check that the response contains no client (4xx) or server (5xx) error responses:

import fetch from 'node-fetch';

class HTTPResponseError extends Error {
    constructor(response) {
        super(`HTTP Error Response: ${response.status} ${response.statusText}`);
        this.response = response;
    }
}

const checkStatus = response => {
    if (response.ok) {
        // response.status >= 200 && response.status < 300
        return response;
    } else {
        throw new HTTPResponseError(response);
    }
}

const response = await fetch('https://httpbin.org/status/400');

try {
    checkStatus(response);
} catch (error) {
    console.error(error);

    const errorBody = await error.response.text();
    console.error(`Error body: ${errorBody}`);
}

Handling cookies

Cookies are not stored by default. However, cookies can be extracted and passed by manipulating request and response headers. See Extract Set-Cookie Header for details.

Advanced Usage

Streams

The "Node.js way" is to use streams when possible. You can pipe res.body to another stream. This example uses stream.pipeline to attach stream error handlers and wait for the download to complete.

import {createWriteStream} from 'node:fs';
import {pipeline} from 'node:stream';
import {promisify} from 'node:util'
import fetch from 'node-fetch';

const streamPipeline = promisify(pipeline);

const response = await fetch('https://github.githubassets.com/images/modules/logos_page/Octocat.png');

if (!response.ok) throw new Error(`unexpected response ${response.statusText}`);

await streamPipeline(response.body, createWriteStream('./octocat.png'));

In Node.js 14 you can also use async iterators to read body; however, be careful to catch errors -- the longer a response runs, the more likely it is to encounter an error.

import fetch from 'node-fetch';

const response = await fetch('https://httpbin.org/stream/3');

try {
    for await (const chunk of response.body) {
        console.dir(JSON.parse(chunk.toString()));
    }
} catch (err) {
    console.error(err.stack);
}

In Node.js 12 you can also use async iterators to read body; however, async iterators with streams did not mature until Node.js 14, so you need to do some extra work to ensure you handle errors directly from the stream and wait on it response to fully close.

import fetch from 'node-fetch';

const read = async body => {
    let error;
    body.on('error', err => {
        error = err;
    });

    for await (const chunk of body) {
        console.dir(JSON.parse(chunk.toString()));
    }

    return new Promise((resolve, reject) => {
        body.on('close', () => {
            error ? reject(error) : resolve();
        });
    });
};

try {
    const response = await fetch('https://httpbin.org/stream/3');
    await read(response.body);
} catch (err) {
    console.error(err.stack);
}

Accessing Headers and other Metadata

import fetch from 'node-fetch';

const response = await fetch('https://github.com/');

console.log(response.ok);
console.log(response.status);
console.log(response.statusText);
console.log(response.headers.raw());
console.log(response.headers.get('content-type'));

Extract Set-Cookie Header

Unlike browsers, you can access raw Set-Cookie headers manually using Headers.raw(). This is a node-fetch only API.

import fetch from 'node-fetch';

const response = await fetch('https://example.com');

// Returns an array of values, instead of a string of comma-separated values
console.log(response.headers.raw()['set-cookie']);

Post data using a file

import fetch, {
  Blob,
  blobFrom,
  blobFromSync,
  File,
  fileFrom,
  fileFromSync,
} from 'node-fetch'

const mimetype = 'text/plain'
const blob = fileFromSync('./input.txt', mimetype)
const url = 'https://httpbin.org/post'

const response = await fetch(url, { method: 'POST', body: blob })
const data = await response.json()

console.log(data)

node-fetch comes with a spec-compliant [FormData] implementations for posting multipart/form-data payloads

import fetch, { FormData, File, fileFrom } from 'node-fetch'

const httpbin = 'https://httpbin.org/post'
const formData = new FormData()
const binary = new Uint8Array([ 97, 98, 99 ])
const abc = new File([binary], 'abc.txt', { type: 'text/plain' })

formData.set('greeting', 'Hello, world!')
formData.set('file-upload', abc, 'new name.txt')

const response = await fetch(httpbin, { method: 'POST', body: formData })
const data = await response.json()

console.log(data)

If you for some reason need to post a stream coming from any arbitrary place, then you can append a [Blob] or a [File] look-a-like item.

The minimum requirement is that it has: 1. A Symbol.toStringTag getter or property that is either Blob or File 2. A known size. 3. And either a stream() method or a arrayBuffer() method that returns a ArrayBuffer.

The stream() must return any async iterable object as long as it yields Uint8Array (or Buffer) so Node.Readable streams and whatwg streams works just fine.

```js formData.append('upload', { [Symbol.toStringTag]: 'Blob', size: 3, *stream() { yield new Uint8Array([97, 98, 99]) },

Extension points exported contracts — how you extend this code

RequestInit (Interface)
(no doc)
@types/index.d.ts
ResponseInit (Interface)
(no doc)
@types/index.d.ts
Body (Interface)
(no doc)
@types/index.d.ts

Core symbols most depended-on inside this repo

fetch
called by 182
src/index.js
get
called by 91
src/headers.js
json
called by 74
src/body.js
text
called by 69
src/body.js
end
called by 58
src/utils/multipart-parser.js
toString
called by 25
src/headers.js
arrayBuffer
called by 25
src/body.js
clone
called by 12
src/request.js

Shape

Method 61
Function 46
Class 34
Interface 3

Languages

TypeScript100%

Modules by API surface

src/utils/multipart-parser.js17 symbols
src/response.js16 symbols
src/body.js16 symbols
@types/index.d.ts15 symbols
src/request.js14 symbols
src/headers.js13 symbols
test/main.js9 symbols
test/utils/server.js8 symbols
src/index.js7 symbols
src/utils/referrer.js6 symbols
src/utils/is.js5 symbols
src/errors/base.js5 symbols

Dependencies from manifests, versioned

abort-controller3.0.0 · 1×
abortcontroller-polyfill1.7.1 · 1×
busboy1.4.0 · 1×
c87.7.2 · 1×
chai4.3.4 · 1×
chai-as-promised7.1.1 · 1×
chai-iterator3.0.2 · 1×
chai-string1.5.0 · 1×
coveralls3.1.0 · 1×
data-uri-to-buffer4.0.0 · 1×
fetch-blob3.1.4 · 1×
form-data4.0.0 · 1×

For agents

$ claude mcp add node-fetch \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact