<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
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).
window.fetch API.res.text() and res.json()) to UTF-8 automatically.window.fetch offers, feel free to open an issue.Current stable release (3.x) requires at least Node.js 12.20.0.
npm install node-fetch
import fetch from 'node-fetch';
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));
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'
// ...
Using an old version of node-fetch? Check out the following files:
NOTE: The documentation below is up-to-date with 3.x releases, if you are using an older version, please check how to upgrade.
import fetch from 'node-fetch';
const response = await fetch('https://github.com/');
const body = await response.text();
console.log(body);
import fetch from 'node-fetch';
const response = await fetch('https://api.github.com/users/github');
const data = await response.json();
console.log(data);
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);
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);
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);
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);
}
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}`);
}
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.
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);
}
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'));
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']);
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]) },
$ claude mcp add node-fetch \
-- python -m otcore.mcp_server <graph>