UNPKG

26.3 kBMarkdownView Raw
1<div align="center">
2 <img src="docs/media/Banner.svg" alt="Node Fetch"/>
3 <br>
4 <p>A light-weight module that brings <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">Fetch API</a> to Node.js.</p>
5 <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>
6 <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>
7 <a href="https://packagephobia.now.sh/result?p=node-fetch"><img src="https://badgen.net/packagephobia/install/node-fetch" alt="Current version"></a>
8 <a href="https://www.npmjs.com/package/node-fetch"><img src="https://img.shields.io/npm/v/node-fetch" alt="Install size"></a>
9 <a href="https://github.com/sindresorhus/awesome-nodejs"><img src="https://awesome.re/mentioned-badge.svg" alt="Mentioned in Awesome Node.js"></a>
10 <a href="https://discord.gg/Zxbndcm"><img src="https://img.shields.io/discord/619915844268326952?color=%237289DA&label=Discord" alt="Discord"></a>
11 <br>
12 <br>
13 <b>Consider supporting us on our Open Collective:</b>
14 <br>
15 <br>
16 <a href="https://opencollective.com/node-fetch"><img src="https://opencollective.com/node-fetch/donate/button.png?color=blue" alt="Open Collective"></a>
17</div>
18
19---
20
21**You might be looking for the [v2 docs](https://github.com/node-fetch/node-fetch/tree/2.x#readme)**
22
23<!-- TOC -->
24
25- [Motivation](#motivation)
26- [Features](#features)
27- [Difference from client-side fetch](#difference-from-client-side-fetch)
28- [Installation](#installation)
29- [Loading and configuring the module](#loading-and-configuring-the-module)
30- [Upgrading](#upgrading)
31- [Common Usage](#common-usage)
32 - [Plain text or HTML](#plain-text-or-html)
33 - [JSON](#json)
34 - [Simple Post](#simple-post)
35 - [Post with JSON](#post-with-json)
36 - [Post with form parameters](#post-with-form-parameters)
37 - [Handling exceptions](#handling-exceptions)
38 - [Handling client and server errors](#handling-client-and-server-errors)
39 - [Handling cookies](#handling-cookies)
40- [Advanced Usage](#advanced-usage)
41 - [Streams](#streams)
42 - [Accessing Headers and other Metadata](#accessing-headers-and-other-metadata)
43 - [Extract Set-Cookie Header](#extract-set-cookie-header)
44 - [Post data using a file stream](#post-data-using-a-file-stream)
45 - [Request cancellation with AbortSignal](#request-cancellation-with-abortsignal)
46- [API](#api)
47 - [fetch(url[, options])](#fetchurl-options)
48 - [Options](#options)
49 - [Default Headers](#default-headers)
50 - [Custom Agent](#custom-agent)
51 - [Custom highWaterMark](#custom-highwatermark)
52 - [Insecure HTTP Parser](#insecure-http-parser)
53 - [Class: Request](#class-request)
54 - [new Request(input[, options])](#new-requestinput-options)
55 - [Class: Response](#class-response)
56 - [new Response([body[, options]])](#new-responsebody-options)
57 - [response.ok](#responseok)
58 - [response.redirected](#responseredirected)
59 - [response.type](#responsetype)
60 - [Class: Headers](#class-headers)
61 - [new Headers([init])](#new-headersinit)
62 - [Interface: Body](#interface-body)
63 - [body.body](#bodybody)
64 - [body.bodyUsed](#bodybodyused)
65 - [body.arrayBuffer()](#bodyarraybuffer)
66 - [body.blob()](#bodyblob)
67 - [body.json()](#bodyjson)
68 - [body.text()](#bodytext)
69 - [Class: FetchError](#class-fetcherror)
70 - [Class: AbortError](#class-aborterror)
71- [TypeScript](#typescript)
72- [Acknowledgement](#acknowledgement)
73- [Team](#team)
74 - [Former](#former)
75- [License](#license)
76
77<!-- /TOC -->
78
79## Motivation
80
81Instead of implementing `XMLHttpRequest` in Node.js to run browser-specific [Fetch polyfill](https://github.com/github/fetch), 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.
82
83See Jason Miller's [isomorphic-unfetch](https://www.npmjs.com/package/isomorphic-unfetch) or Leonardo Quixada's [cross-fetch](https://github.com/lquixada/cross-fetch) for isomorphic usage (exports `node-fetch` for server-side, `whatwg-fetch` for client-side).
84
85## Features
86
87- Stay consistent with `window.fetch` API.
88- Make conscious trade-off when following [WHATWG fetch spec][whatwg-fetch] and [stream spec](https://streams.spec.whatwg.org/) implementation details, document known differences.
89- Use native promise and async functions.
90- Use native Node streams for body, on both request and response.
91- Decode content encoding (gzip/deflate/brotli) properly, and convert string output (such as `res.text()` and `res.json()`) to UTF-8 automatically.
92- Useful extensions such as redirect limit, response size limit, [explicit errors][error-handling.md] for troubleshooting.
93
94## Difference from client-side fetch
95
96- See known differences:
97 - [As of v3.x](docs/v3-LIMITS.md)
98 - [As of v2.x](docs/v2-LIMITS.md)
99- If you happen to use a missing feature that `window.fetch` offers, feel free to open an issue.
100- Pull requests are welcomed too!
101
102## Installation
103
104Current stable release (`3.x`) requires at least Node.js 12.20.0.
105
106```sh
107npm install node-fetch
108```
109
110## Loading and configuring the module
111
112### ES Modules (ESM)
113
114```js
115import fetch from 'node-fetch';
116```
117
118### CommonJS
119
120`node-fetch` from v3 is an ESM-only module - you are not able to import it with `require()`.
121
122If you cannot switch to ESM, please use v2 which remains compatible with CommonJS. Critical bug fixes will continue to be published for v2.
123
124```sh
125npm install node-fetch@2
126```
127
128Alternatively, you can use the async `import()` function from CommonJS to load `node-fetch` asynchronously:
129
130```js
131// mod.cjs
132const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
133```
134
135### Providing global access
136
137To use `fetch()` without importing it, you can patch the `global` object in node:
138
139```js
140// fetch-polyfill.js
141import fetch from 'node-fetch';
142
143if (!globalThis.fetch) {
144 globalThis.fetch = fetch;
145 globalThis.Headers = Headers;
146 globalThis.Request = Request;
147 globalThis.Response = Response;
148}
149
150// index.js
151import './fetch-polyfill'
152
153// ...
154```
155
156## Upgrading
157
158Using an old version of node-fetch? Check out the following files:
159
160- [2.x to 3.x upgrade guide](docs/v3-UPGRADE-GUIDE.md)
161- [1.x to 2.x upgrade guide](docs/v2-UPGRADE-GUIDE.md)
162- [Changelog](docs/CHANGELOG.md)
163
164## Common Usage
165
166NOTE: The documentation below is up-to-date with `3.x` releases, if you are using an older version, please check how to [upgrade](#upgrading).
167
168### Plain text or HTML
169
170```js
171import fetch from 'node-fetch';
172
173const response = await fetch('https://github.com/');
174const body = await response.text();
175
176console.log(body);
177```
178
179### JSON
180
181```js
182import fetch from 'node-fetch';
183
184const response = await fetch('https://api.github.com/users/github');
185const data = await response.json();
186
187console.log(data);
188```
189
190### Simple Post
191
192```js
193import fetch from 'node-fetch';
194
195const response = await fetch('https://httpbin.org/post', {method: 'POST', body: 'a=1'});
196const data = await response.json();
197
198console.log(data);
199```
200
201### Post with JSON
202
203```js
204import fetch from 'node-fetch';
205
206const body = {a: 1};
207
208const response = await fetch('https://httpbin.org/post', {
209 method: 'post',
210 body: JSON.stringify(body),
211 headers: {'Content-Type': 'application/json'}
212});
213const data = await response.json();
214
215console.log(data);
216```
217
218### Post with form parameters
219
220`URLSearchParams` is available on the global object in Node.js as of v10.0.0. See [official documentation](https://nodejs.org/api/url.html#url_class_urlsearchparams) for more usage methods.
221
222NOTE: The `Content-Type` header is only set automatically to `x-www-form-urlencoded` when an instance of `URLSearchParams` is given as such:
223
224```js
225import fetch from 'node-fetch';
226
227const params = new URLSearchParams();
228params.append('a', 1);
229
230const response = await fetch('https://httpbin.org/post', {method: 'POST', body: params});
231const data = await response.json();
232
233console.log(data);
234```
235
236### Handling exceptions
237
238NOTE: 3xx-5xx responses are _NOT_ exceptions, and should be handled in `then()`, see the next section.
239
240Wrapping 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.
241
242```js
243import fetch from 'node-fetch';
244
245try {
246 await fetch('https://domain.invalid/');
247} catch (error) {
248 console.log(error);
249}
250```
251
252### Handling client and server errors
253
254It is common to create a helper function to check that the response contains no client (4xx) or server (5xx) error responses:
255
256```js
257import fetch from 'node-fetch';
258
259class HTTPResponseError extends Error {
260 constructor(response, ...args) {
261 super(`HTTP Error Response: ${response.status} ${response.statusText}`, ...args);
262 this.response = response;
263 }
264}
265
266const checkStatus = response => {
267 if (response.ok) {
268 // response.status >= 200 && response.status < 300
269 return response;
270 } else {
271 throw new HTTPResponseError(response);
272 }
273}
274
275const response = await fetch('https://httpbin.org/status/400');
276
277try {
278 checkStatus(response);
279} catch (error) {
280 console.error(error);
281
282 const errorBody = await error.response.text();
283 console.error(`Error body: ${errorBody}`);
284}
285```
286
287### Handling cookies
288
289Cookies are not stored by default. However, cookies can be extracted and passed by manipulating request and response headers. See [Extract Set-Cookie Header](#extract-set-cookie-header) for details.
290
291## Advanced Usage
292
293### Streams
294
295The "Node.js way" is to use streams when possible. You can pipe `res.body` to another stream. This example uses [stream.pipeline](https://nodejs.org/api/stream.html#stream_stream_pipeline_streams_callback) to attach stream error handlers and wait for the download to complete.
296
297```js
298import {createWriteStream} from 'fs';
299import {pipeline} from 'stream';
300import {promisify} from 'util'
301import fetch from 'node-fetch';
302
303const streamPipeline = promisify(pipeline);
304
305const response = await fetch('https://github.githubassets.com/images/modules/logos_page/Octocat.png');
306
307if (!response.ok) throw new Error(`unexpected response ${response.statusText}`);
308
309await streamPipeline(response.body, createWriteStream('./octocat.png'));
310```
311
312In Node.js 14 you can also use async iterators to read `body`; however, be careful to catch
313errors -- the longer a response runs, the more likely it is to encounter an error.
314
315```js
316import fetch from 'node-fetch';
317
318const response = await fetch('https://httpbin.org/stream/3');
319
320try {
321 for await (const chunk of response.body) {
322 console.dir(JSON.parse(chunk.toString()));
323 }
324} catch (err) {
325 console.error(err.stack);
326}
327```
328
329In Node.js 12 you can also use async iterators to read `body`; however, async iterators with streams
330did not mature until Node.js 14, so you need to do some extra work to ensure you handle errors
331directly from the stream and wait on it response to fully close.
332
333```js
334import fetch from 'node-fetch';
335
336const read = async body => {
337 let error;
338 body.on('error', err => {
339 error = err;
340 });
341
342 for await (const chunk of body) {
343 console.dir(JSON.parse(chunk.toString()));
344 }
345
346 return new Promise((resolve, reject) => {
347 body.on('close', () => {
348 error ? reject(error) : resolve();
349 });
350 });
351};
352
353try {
354 const response = await fetch('https://httpbin.org/stream/3');
355 await read(response.body);
356} catch (err) {
357 console.error(err.stack);
358}
359```
360
361### Accessing Headers and other Metadata
362
363```js
364import fetch from 'node-fetch';
365
366const response = await fetch('https://github.com/');
367
368console.log(response.ok);
369console.log(response.status);
370console.log(response.statusText);
371console.log(response.headers.raw());
372console.log(response.headers.get('content-type'));
373```
374
375### Extract Set-Cookie Header
376
377Unlike browsers, you can access raw `Set-Cookie` headers manually using `Headers.raw()`. This is a `node-fetch` only API.
378
379```js
380import fetch from 'node-fetch';
381
382const response = await fetch('https://example.com');
383
384// Returns an array of values, instead of a string of comma-separated values
385console.log(response.headers.raw()['set-cookie']);
386```
387
388### Post data using a file
389
390```js
391import {fileFromSync} from 'fetch-blob/from.js';
392import fetch from 'node-fetch';
393
394const blob = fileFromSync('./input.txt', 'text/plain');
395
396const response = await fetch('https://httpbin.org/post', {method: 'POST', body: blob});
397const data = await response.json();
398
399console.log(data)
400```
401
402node-fetch also supports any spec-compliant FormData implementations such as [formdata-polyfill](https://www.npmjs.com/package/formdata-polyfill). But any other spec-compliant such as [formdata-node](https://github.com/octet-stream/form-data) works too, but we recommend formdata-polyfill because we use this one internally for decoding entries back to FormData.
403
404```js
405import fetch from 'node-fetch';
406import {FormData} from 'formdata-polyfill/esm-min.js';
407
408// Alternative hack to get the same FormData instance as node-fetch
409// const FormData = (await new Response(new URLSearchParams()).formData()).constructor
410
411const form = new FormData();
412form.set('greeting', 'Hello, world!');
413
414const response = await fetch('https://httpbin.org/post', {method: 'POST', body: form});
415const data = await response.json();
416
417console.log(data);
418```
419
420node-fetch also support form-data but it's now discouraged due to not being spec-compliant and needs workarounds to function - which we hope to remove one day
421
422### Request cancellation with AbortSignal
423
424You may cancel requests with `AbortController`. A suggested implementation is [`abort-controller`](https://www.npmjs.com/package/abort-controller).
425
426An example of timing out a request after 150ms could be achieved as the following:
427
428```js
429import fetch from 'node-fetch';
430
431// AbortController was added in node v14.17.0 globally
432const AbortController = globalThis.AbortController || await import('abort-controller')
433
434const controller = new AbortController();
435const timeout = setTimeout(() => {
436 controller.abort();
437}, 150);
438
439try {
440 const response = await fetch('https://example.com', {signal: controller.signal});
441 const data = await response.json();
442} catch (error) {
443 if (error instanceof fetch.AbortError) {
444 console.log('request was aborted');
445 }
446} finally {
447 clearTimeout(timeout);
448}
449```
450
451See [test cases](https://github.com/node-fetch/node-fetch/blob/master/test/) for more examples.
452
453## API
454
455### fetch(url[, options])
456
457- `url` A string representing the URL for fetching
458- `options` [Options](#fetch-options) for the HTTP(S) request
459- Returns: <code>Promise&lt;[Response](#class-response)&gt;</code>
460
461Perform an HTTP(S) fetch.
462
463`url` should be an absolute URL, such as `https://example.com/`. A path-relative URL (`/file/under/root`) or protocol-relative URL (`//can-be-http-or-https.com/`) will result in a rejected `Promise`.
464
465<a id="fetch-options"></a>
466
467### Options
468
469The default values are shown after each option key.
470
471```js
472{
473 // These properties are part of the Fetch Standard
474 method: 'GET',
475 headers: {}, // Request headers. format is the identical to that accepted by the Headers constructor (see below)
476 body: null, // Request body. can be null, or a Node.js Readable stream
477 redirect: 'follow', // Set to `manual` to extract redirect headers, `error` to reject redirect
478 signal: null, // Pass an instance of AbortSignal to optionally abort requests
479
480 // The following properties are node-fetch extensions
481 follow: 20, // maximum redirect count. 0 to not follow redirect
482 compress: true, // support gzip/deflate content encoding. false to disable
483 size: 0, // maximum response body size in bytes. 0 to disable
484 agent: null, // http(s).Agent instance or function that returns an instance (see below)
485 highWaterMark: 16384, // the maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource.
486 insecureHTTPParser: false // Use an insecure HTTP parser that accepts invalid HTTP headers when `true`.
487}
488```
489
490#### Default Headers
491
492If no values are set, the following request headers will be sent automatically:
493
494| Header | Value |
495| ------------------- | ------------------------------------------------------ |
496| `Accept-Encoding` | `gzip,deflate,br` _(when `options.compress === true`)_ |
497| `Accept` | `*/*` |
498| `Connection` | `close` _(when no `options.agent` is present)_ |
499| `Content-Length` | _(automatically calculated, if possible)_ |
500| `Host` | _(host and port information from the target URI)_ |
501| `Transfer-Encoding` | `chunked` _(when `req.body` is a stream)_ |
502| `User-Agent` | `node-fetch` |
503
504
505Note: when `body` is a `Stream`, `Content-Length` is not set automatically.
506
507#### Custom Agent
508
509The `agent` option allows you to specify networking related options which are out of the scope of Fetch, including and not limited to the following:
510
511- Support self-signed certificate
512- Use only IPv4 or IPv6
513- Custom DNS Lookup
514
515See [`http.Agent`](https://nodejs.org/api/http.html#http_new_agent_options) for more information.
516
517In addition, the `agent` option accepts a function that returns `http`(s)`.Agent` instance given current [URL](https://nodejs.org/api/url.html), this is useful during a redirection chain across HTTP and HTTPS protocol.
518
519```js
520import http from 'http';
521import https from 'https';
522
523const httpAgent = new http.Agent({
524 keepAlive: true
525});
526const httpsAgent = new https.Agent({
527 keepAlive: true
528});
529
530const options = {
531 agent: function(_parsedURL) {
532 if (_parsedURL.protocol == 'http:') {
533 return httpAgent;
534 } else {
535 return httpsAgent;
536 }
537 }
538};
539```
540
541<a id="custom-highWaterMark"></a>
542
543#### Custom highWaterMark
544
545Stream on Node.js have a smaller internal buffer size (16kB, aka `highWaterMark`) from client-side browsers (>1MB, not consistent across browsers). Because of that, when you are writing an isomorphic app and using `res.clone()`, it will hang with large response in Node.
546
547The recommended way to fix this problem is to resolve cloned response in parallel:
548
549```js
550import fetch from 'node-fetch';
551
552const response = await fetch('https://example.com');
553const r1 = await response.clone();
554
555const results = await Promise.all([response.json(), r1.text()]);
556
557console.log(results[0]);
558console.log(results[1]);
559```
560
561If for some reason you don't like the solution above, since `3.x` you are able to modify the `highWaterMark` option:
562
563```js
564import fetch from 'node-fetch';
565
566const response = await fetch('https://example.com', {
567 // About 1MB
568 highWaterMark: 1024 * 1024
569});
570
571const result = await res.clone().arrayBuffer();
572console.dir(result);
573```
574
575#### Insecure HTTP Parser
576
577Passed through to the `insecureHTTPParser` option on http(s).request. See [`http.request`](https://nodejs.org/api/http.html#http_http_request_url_options_callback) for more information.
578
579
580<a id="class-request"></a>
581
582### Class: Request
583
584An HTTP(S) request containing information about URL, method, headers, and the body. This class implements the [Body](#iface-body) interface.
585
586Due to the nature of Node.js, the following properties are not implemented at this moment:
587
588- `type`
589- `destination`
590- `mode`
591- `credentials`
592- `cache`
593- `integrity`
594- `keepalive`
595
596The following node-fetch extension properties are provided:
597
598- `follow`
599- `compress`
600- `counter`
601- `agent`
602- `highWaterMark`
603
604See [options](#fetch-options) for exact meaning of these extensions.
605
606#### new Request(input[, options])
607
608<small>_(spec-compliant)_</small>
609
610- `input` A string representing a URL, or another `Request` (which will be cloned)
611- `options` [Options][#fetch-options] for the HTTP(S) request
612
613Constructs a new `Request` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request).
614
615In most cases, directly `fetch(url, options)` is simpler than creating a `Request` object.
616
617<a id="class-response"></a>
618
619### Class: Response
620
621An HTTP(S) response. This class implements the [Body](#iface-body) interface.
622
623The following properties are not implemented in node-fetch at this moment:
624
625- `trailer`
626
627#### new Response([body[, options]])
628
629<small>_(spec-compliant)_</small>
630
631- `body` A `String` or [`Readable` stream][node-readable]
632- `options` A [`ResponseInit`][response-init] options dictionary
633
634Constructs a new `Response` object. The constructor is identical to that in the [browser](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response).
635
636Because Node.js does not implement service workers (for which this class was designed), one rarely has to construct a `Response` directly.
637
638#### response.ok
639
640<small>_(spec-compliant)_</small>
641
642Convenience property representing if the request ended normally. Will evaluate to true if the response status was greater than or equal to 200 but smaller than 300.
643
644#### response.redirected
645
646<small>_(spec-compliant)_</small>
647
648Convenience property representing if the request has been redirected at least once. Will evaluate to true if the internal redirect counter is greater than 0.
649
650#### response.type
651
652<small>_(deviation from spec)_</small>
653
654Convenience property representing the response's type. node-fetch only supports `'default'` and `'error'` and does not make use of [filtered responses](https://fetch.spec.whatwg.org/#concept-filtered-response).
655
656<a id="class-headers"></a>
657
658### Class: Headers
659
660This class allows manipulating and iterating over a set of HTTP headers. All methods specified in the [Fetch Standard][whatwg-fetch] are implemented.
661
662#### new Headers([init])
663
664<small>_(spec-compliant)_</small>
665
666- `init` Optional argument to pre-fill the `Headers` object
667
668Construct a new `Headers` object. `init` can be either `null`, a `Headers` object, an key-value map object or any iterable object.
669
670```js
671// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class
672import {Headers} from 'node-fetch';
673
674const meta = {
675 'Content-Type': 'text/xml',
676 'Breaking-Bad': '<3'
677};
678const headers = new Headers(meta);
679
680// The above is equivalent to
681const meta = [['Content-Type', 'text/xml'], ['Breaking-Bad', '<3']];
682const headers = new Headers(meta);
683
684// You can in fact use any iterable objects, like a Map or even another Headers
685const meta = new Map();
686meta.set('Content-Type', 'text/xml');
687meta.set('Breaking-Bad', '<3');
688const headers = new Headers(meta);
689const copyOfHeaders = new Headers(headers);
690```
691
692<a id="iface-body"></a>
693
694### Interface: Body
695
696`Body` is an abstract interface with methods that are applicable to both `Request` and `Response` classes.
697
698#### body.body
699
700<small>_(deviation from spec)_</small>
701
702- Node.js [`Readable` stream][node-readable]
703
704Data are encapsulated in the `Body` object. Note that while the [Fetch Standard][whatwg-fetch] requires the property to always be a WHATWG `ReadableStream`, in node-fetch it is a Node.js [`Readable` stream][node-readable].
705
706#### body.bodyUsed
707
708<small>_(spec-compliant)_</small>
709
710- `Boolean`
711
712A boolean property for if this body has been consumed. Per the specs, a consumed body cannot be used again.
713
714#### body.arrayBuffer()
715
716#### body.formData()
717
718#### body.blob()
719
720#### body.json()
721
722#### body.text()
723
724<small>_(spec-compliant)_</small>
725
726- Returns: `Promise`
727
728Consume the body and return a promise that will resolve to one of these formats.
729
730<a id="class-fetcherror"></a>
731
732### Class: FetchError
733
734<small>_(node-fetch extension)_</small>
735
736An operational error in the fetching process. See [ERROR-HANDLING.md][] for more info.
737
738<a id="class-aborterror"></a>
739
740### Class: AbortError
741
742<small>_(node-fetch extension)_</small>
743
744An Error thrown when the request is aborted in response to an `AbortSignal`'s `abort` event. It has a `name` property of `AbortError`. See [ERROR-HANDLING.MD][] for more info.
745
746## TypeScript
747
748**Since `3.x` types are bundled with `node-fetch`, so you don't need to install any additional packages.**
749
750For older versions please use the type definitions from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped):
751
752```sh
753npm install --save-dev @types/node-fetch
754```
755
756## Acknowledgement
757
758Thanks to [github/fetch](https://github.com/github/fetch) for providing a solid implementation reference.
759
760## Team
761
762| [![David Frank](https://github.com/bitinn.png?size=100)](https://github.com/bitinn) | [![Jimmy Wärting](https://github.com/jimmywarting.png?size=100)](https://github.com/jimmywarting) | [![Antoni Kepinski](https://github.com/xxczaki.png?size=100)](https://github.com/xxczaki) | [![Richie Bendall](https://github.com/Richienb.png?size=100)](https://github.com/Richienb) | [![Gregor Martynus](https://github.com/gr2m.png?size=100)](https://github.com/gr2m) |
763| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
764| [David Frank](https://bitinn.net/) | [Jimmy Wärting](https://jimmy.warting.se/) | [Antoni Kepinski](https://kepinski.ch) | [Richie Bendall](https://www.richie-bendall.ml/) | [Gregor Martynus](https://twitter.com/gr2m) |
765
766###### Former
767
768- [Timothy Gu](https://github.com/timothygu)
769- [Jared Kantrowitz](https://github.com/jkantr)
770
771## License
772
773[MIT](LICENSE.md)
774
775[whatwg-fetch]: https://fetch.spec.whatwg.org/
776[response-init]: https://fetch.spec.whatwg.org/#responseinit
777[node-readable]: https://nodejs.org/api/stream.html#stream_readable_streams
778[mdn-headers]: https://developer.mozilla.org/en-US/docs/Web/API/Headers
779[error-handling.md]: https://github.com/node-fetch/node-fetch/blob/master/docs/ERROR-HANDLING.md