Node.js bindings for reqwest — a Rust HTTP client.
Implements the full undici.Dispatcher interface (including its
error classes), passes the same web-platform tests undici does, and
outperforms it on HTTP/2. Ships with system proxy, system CA
certificates, and Electron compatibility built in.
npm install node-reqwestPrebuilt binaries are shipped for macOS, Linux, and Windows on
x64 and arm64. Requires Node.js ≥ 22.12 and undici ≥ 8 as a
peer dependency.
Agent implements the undici.Dispatcher interface. Use it as a
global dispatcher for fetch, or with any undici-compatible API.
import { Agent } from "node-reqwest";
import { setGlobalDispatcher } from "undici";
const agent = new Agent({
allowH2: true,
proxy: "system", // also accepts "none" or { type: "custom", uri, auth? }
});
setGlobalDispatcher(agent);
// All fetch calls now use reqwest under the hood
const response = await fetch("https://example.com");| Feature | node-reqwest | Node.js / undici |
|---|---|---|
| DNS resolver | Async pure-Rust (hickory-dns) | C (c-ares) — crashes Electron on Windows for nonexistent domains |
| System CA certificates | Built-in | Requires win-ca, mac-ca |
| System proxy | Built-in | Not available (complex Electron workaround) |
| SOCKS proxy | Built-in | Not available |
| HTTP/2 | Multiplexed via hyper | Implemented, but materially slower (see benchmarks) |
| TLS | rustls | OpenSSL |
Throughput vs. undici on the same workload. The conservative number
between two timed runs (with a warm-up run discarded):
| Scenario | node-reqwest vs. undici |
|---|---|
| HTTP/1 GET | at parity |
| HTTP/1 POST (stream body) | +5% |
| HTTP/2 GET | +50% |
| HTTP/2 POST (stream body) | +55% |
HTTP/1 GET, the tightest hot path, lands within run-to-run noise of undici (mean throughput; p50 favors node-reqwest by 3–7% but tail latency is GC-jittery on both sides). The HTTP/2 numbers are where the multiplexing wins show up.
Reproduce the benchmarks
The benchmark suite lives in packages/node/benchmarks/.
Each scenario starts a loopback HTTP/1 or HTTP/2 server (using
selfsigned for HTTP/2 TLS) and drives 100 parallel dispatches per
iteration via vitest's bench() runner; warm-up dispatches
prime the connection pool and JIT before timed samples.
To reproduce locally:
git clone --recurse-submodules https://github.com/vadimpiven/node_reqwest.git
cd node_reqwest
mise install # installs Node, Rust, pnpm via the pinned toolchain
pnpm install
pnpm --filter node-reqwest run benchpnpm run bench builds the Rust addon first (via prebench), then
executes every *.bench.ts file in packages/node/benchmarks/. Each
run prints per-bench hz (ops/sec), latency percentiles, and a
"Nx faster than" summary comparing the two dispatchers.
The README numbers are the conservative result between two consecutive
runs (the worst-for-node-reqwest ratio), with a discarded warm-up run
preceding them. Absolute throughput depends on your machine; the
ratio between the two dispatchers is what's stable across hardware.
| OS | Architectures |
|---|---|
| macOS | x64, arm64 |
| Linux | x64, arm64 |
| Windows | x64, arm64 |
- Node.js ≥ 22.12
- Peer dependency:
undici^8
Prebuilt binaries are published as part of every release; there is
no source build step on npm install. Linux prebuilds target
manylinux_2_28 (glibc ≥ 2.28).
Agent covers the undici.Dispatcher request/stream/pipeline
surface, but a few features are deliberately out of scope. See
COMPATIBILITY.md for the full matrix and error mapping.
- No CONNECT / Upgrade, so no WebSockets and no HTTP tunneling.
Use undici's
WebSocket/ProxyAgentfor those. - No HTTP trailers, no
drainevent, no pipelining knobs. reqwest manages the connection pool internally, so the corresponding Dispatcher options are no-ops. - No request retries. Bodies are streams; retry at the application layer.
This package downloads a precompiled binary during npm install.
GitHub releases for this project are
immutable — once published, release
assets cannot be modified or replaced, ensuring that the binary
you download is the same one that was originally published.
In addition, the postinstall script uses node-addon-slsa to cryptographically verify that the binary was built in the same GitHub Actions workflow run as this npm package, using sigstore provenance attestations and the GitHub Attestations API.
Installation aborts with a SECURITY error if any check fails.
Apache-2.0 OR MIT