make-fetch-happen
make-fetch-happen is an opinionated, robust Node.js HTTP client that extends the standard `fetch` API with critical features for real-world applications. Currently stable at version 15.0.5, it maintains a fairly active release cadence, with minor/patch updates occurring every few months and major versions roughly annually, aligning with Node.js LTS updates. It distinguishes itself by wrapping `minipass-fetch` and augmenting it with capabilities like automatic HTTP-semantics-aware request retries, comprehensive HTTP caching (`Cache-Control`, `ETag`, `304`s, offline fallback), request pooling, transparent gzip/deflate, and support for proxies (HTTP, HTTPS, SOCKS). Additionally, it provides Subresource Integrity (SRI) verification and integrates Node.js Stream support, making it a highly reliable and performant choice for network operations within the Node.js ecosystem, particularly for tools like `npm` itself.
Common errors
-
Error: make-fetch-happen requires Node.js version X or higher.
cause The installed Node.js version does not meet the minimum engine requirement specified by make-fetch-happen.fixUpgrade your Node.js environment to the version specified in the error message or the package's `engines` field (e.g., `nvm install 20` and `nvm use 20`). -
SRI Mismatch
cause The Subresource Integrity (SRI) hash provided in the fetch options does not match the hash of the downloaded resource, indicating potential tampering or an incorrect hash.fixVerify the integrity hash (`opts.integrity`) against the actual resource's hash. If the resource has changed, generate a new SRI hash. If fetching a known resource, ensure the integrity hash is correct. -
TypeError: makeFetchHappen.defaults is not a function
cause Attempting to call `.defaults` on `makeFetchHappen` when it's not imported correctly, or `makeFetchHappen` itself is undefined due to an incorrect import.fixEnsure you are importing the default export: `import makeFetchHappen from 'make-fetch-happen';` for ESM or `const makeFetchHappen = require('make-fetch-happen');` for CommonJS. -
Proxy error: connect ECONNREFUSED
cause make-fetch-happen failed to establish a connection through the configured proxy server, often due to an incorrect proxy address, port, or an unresponsive proxy.fixDouble-check your `opts.proxy` configuration, including the protocol (http, https, socks) and credentials. Ensure the proxy server is running and accessible from your environment. -
EACCES: permission denied, open '/path/to/my-app-cache/content-v2/sha512-...' (or similar cache path error)
cause The application lacks sufficient write permissions for the specified `opts.cachePath` directory, preventing caching operations.fixEnsure the user running the Node.js process has read/write permissions to the `cachePath` directory. Consider changing the `cachePath` to a user-specific temporary directory or a location with appropriate permissions.
Warnings
- breaking Version 15.0.0 updated the minimum Node.js engine requirement to `^20.17.0 || >=22.9.0`. Older Node.js versions are no longer supported.
- breaking Version 14.0.0 updated the minimum Node.js engine requirement to `^18.17.0 || >=20.5.0`. Older Node.js versions are no longer supported.
- gotcha Prior to v14.0.3, `make-fetch-happen` could incorrectly ignore the `NODE_TLS_REJECT_UNAUTHORIZED` environment variable when the `strictSSL` option was not explicitly defined, potentially leading to insecure connections.
- gotcha Version 15.0.5 included a fix for URL logging of npm credentials. This implies that prior versions might have inadvertently logged sensitive credential information in URLs under certain conditions.
- gotcha Before v14.0.2, there were issues where the request signal (for aborting requests) was incorrectly used within the agent, potentially leading to unexpected request termination or resource leaks.
Install
-
npm install make-fetch-happen -
yarn add make-fetch-happen -
pnpm add make-fetch-happen
Imports
- fetch
import { fetch } from 'make-fetch-happen';import makeFetchHappen from 'make-fetch-happen'; const fetch = makeFetchHappen;
- fetch.defaults
import { defaults } from 'make-fetch-happen';import makeFetchHappen from 'make-fetch-happen'; const fetchWithDefaults = makeFetchHappen.defaults({ /* options */ }); - Response
import { Response } from 'node-fetch';import makeFetchHappen, { Response } from 'make-fetch-happen'; // Or globally available in Node.js >=18
Quickstart
import makeFetchHappen from 'make-fetch-happen';
const fetch = makeFetchHappen.defaults({
cachePath: './my-app-cache' // path where cache will be written (and read)
});
// First request: fetches from the web and caches the response
fetch('https://registry.npmjs.org/make-fetch-happen')
.then(res => res.json()) // download the body as JSON
.then(body => {
console.log(`Initial fetch: got ${body.name} from web.`);
// Second request: forces a conditional request to validate cache
return fetch('https://registry.npmjs.org/make-fetch-happen', {
cache: 'no-cache' // instructs to revalidate with the origin
});
})
.then(res => {
console.log(`Conditional fetch status: ${res.status}`); // Expected 304 if cache valid
return res.json().then(body => {
console.log(`Conditional fetch: got ${body.name} from cache (status ${res.status}).`);
});
})
.catch(error => console.error('An error occurred:', error));