{"id":16357,"library":"fetch-h2","title":"fetch-h2: HTTP/1+2 Fetch API for Node.js","description":"fetch-h2 is a robust Node.js implementation of the standard Fetch API, providing a familiar, browser-like interface for making HTTP requests within a Node.js environment. It transparently handles both HTTP/1.1 and HTTP/2 connections, automatically negotiating the protocol via ALPN for `https://` URLs, and defaulting to HTTP/1.1 for `http://` unless `http2://` is explicitly used for plain-text HTTP/2 (h2c). The library is currently stable at version 3.0.2 and receives regular maintenance, including bug fixes and dependency updates. Key differentiators include its close adherence to the Fetch API standard, transparent socket re-use and session management, built-in in-memory cookie support per context, and automatic decoding of `br`, `gzip`, and `deflate` encodings. It offers a higher-level, more developer-friendly abstraction for HTTP/2 client requests in Node.js compared to the lower-level native `http2` module. Since version 3.0.0, it requires Node.js 12 or newer.","status":"active","version":"3.0.2","language":"javascript","source_language":"en","source_url":"https://github.com/grantila/fetch-h2","tags":["javascript","fetch","h2","http2","client","request","api","typesafe","typescript"],"install":[{"cmd":"npm install fetch-h2","lang":"bash","label":"npm"},{"cmd":"yarn add fetch-h2","lang":"bash","label":"yarn"},{"cmd":"pnpm add fetch-h2","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"fetch-h2 is primarily designed for ESM usage since v3, though CJS might still work. Named imports are standard.","wrong":"const fetch = require('fetch-h2')","symbol":"fetch","correct":"import { fetch } from 'fetch-h2'"},{"note":"All exports are named exports, including configuration functions like `setup`.","wrong":"import setup from 'fetch-h2'","symbol":"setup","correct":"import { setup } from 'fetch-h2'"},{"note":"Used for request cancellation and managing timeouts, mirroring the browser's AbortController API.","symbol":"AbortController","correct":"import { AbortController } from 'fetch-h2'"},{"note":"The Response class is directly exported, consistent with the Fetch API specification.","symbol":"Response","correct":"import { Response } from 'fetch-h2'"}],"quickstart":{"code":"import { fetch } from 'fetch-h2';\n\nasync function fetchData() {\n  const targetUrl = process.env.API_URL ?? 'https://httpbin.org/get';\n  try {\n    const response = await fetch(targetUrl, {\n      headers: {\n        'User-Agent': 'fetch-h2-checklist-day-example/1.0'\n      }\n    });\n\n    if (!response.ok) {\n      throw new Error(`HTTP error! status: ${response.status}`);\n    }\n\n    const data = await response.json();\n    console.log('Successfully fetched data:', data.url, data.headers['User-Agent']);\n    console.log('Headers:', response.headers.get('Content-Type'));\n  } catch (error) {\n    console.error('Failed to fetch:', error.message);\n  }\n}\n\nfetchData();","lang":"typescript","description":"Demonstrates a basic GET request using `fetch`, handling the response, and error conditions, including custom headers."},"warnings":[{"fix":"Upgrade your Node.js environment to version 12 or higher, or use an older version of fetch-h2 (e.g., <3.0.0) if Node 10 support is critical.","message":"Version 3.0.0 and above requires Node.js 12 or newer. Older Node.js versions (e.g., Node 10) are not supported.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Consult the `engines` field in the package.json or the release notes for the exact Node.js version compatibility.","message":"Previous versions (1.x, 2.x) had their own Node.js engine requirements (1.0.0 required Node 10, 2.0.0 required Node 10.4). Always check the engine requirement for your specific version.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"If persistent cookie storage or cross-process sharing is required, manually retrieve cookies from `CookieJar` and manage them outside the library.","message":"Cookies are handled per-context and stored only in-memory. They are not persisted to disk or automatically shared across different application runs.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For h2c connections, ensure your URL starts with `http2://` (e.g., `http2://localhost:8080`). For HTTPS, ALPN negotiation handles protocol selection.","message":"By default, `fetch-h2` will use HTTP/1.1 for `http://` URLs. To explicitly use plain-text HTTP/2 (h2c), you must prefix the URL with `http2://`.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Catch `TimeoutError` specifically if you need to differentiate timeout errors from other abort signals. Otherwise, catching `AbortError` will cover both.","message":"Timeouts are internally implemented using `AbortController` signals. When a timeout occurs, a `TimeoutError` (which extends `AbortError`) is thrown.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Use ESM `import { fetch } from 'fetch-h2'` in a module with `\"type\": \"module\"` in package.json or with an `.mjs` extension.","cause":"Attempting to use `require()` for the `fetch` function in a CommonJS module context, which is typically an ESM-only export.","error":"TypeError: fetch is not a function"},{"fix":"Increase the timeout value in the `init` object (e.g., `{ timeout: 10000 }`) or investigate network/server performance issues.","cause":"The HTTP request exceeded the configured timeout duration, leading to an automatic cancellation.","error":"TimeoutError: The operation timed out"},{"fix":"Check the URL, verify the resource exists, and ensure the server is configured to return expected status codes. Add specific error handling for different HTTP statuses.","cause":"The requested resource was not found on the server, or another non-2xx/3xx status code was returned indicating an application-level error.","error":"Error: HTTP error! status: 404"}],"ecosystem":"npm"}