v1.10.82-f67ee7d
Skip to main content
← Back to Code Snippets

JavaScript node-fetch Proxy

Complete node-fetch proxy integration example for JavaScript/Node.js with Hex Proxies. Includes authentication, timeouts, and error handling.

JavaScriptnode-fetch
Install:npm install node-fetch https-proxy-agent
JavaScript / node-fetch
const fetch = require("node-fetch");
const { HttpsProxyAgent } = require("https-proxy-agent");

const agent = new HttpsProxyAgent(
  "http://user:pass@gate.hexproxies.com:8080"
);

async function fetchWithProxy() {
  try {
    const response = await fetch("https://httpbin.org/ip", {
      agent,
      timeout: 30000,
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const data = await response.json();
    console.log("Origin IP:", data.origin);
  } catch (error) {
    console.error("Request failed:", error.message);
  }
}

fetchWithProxy();

Why node-fetch for Proxy Work

node-fetch brings the familiar browser Fetch API to the Node.js server environment, providing a lightweight alternative to heavier HTTP clients. At just 0.3KB minified, it adds minimal overhead to your project while offering a standards-compliant interface that frontend developers already know. This familiarity is a practical advantage for teams that build both browser and server applications, as the same mental model for making HTTP requests applies on both sides. For proxy workloads, node-fetch's simplicity means fewer abstractions between your code and the underlying network calls through gate.hexproxies.com:8080.

The library's minimal footprint makes it particularly suitable for serverless functions (AWS Lambda, Vercel, Cloudflare Workers) where cold start time and bundle size directly affect cost and latency. A Lambda function that routes requests through Hex Proxies needs only node-fetch and https-proxy-agent, keeping the deployment package small and cold starts fast. This lean profile also makes node-fetch a strong choice for CLI tools and microservices that need proxy support without the weight of a full HTTP framework.

Configuration Patterns

node-fetch accepts an `agent` option that controls how the underlying connection is established. For proxy routing, pass an `HttpsProxyAgent` instance that encapsulates the proxy URL, credentials, and connection pool. The agent handles CONNECT tunneling for HTTPS targets, establishing a tunnel through the proxy to the destination server. This is transparent to your application code, which interacts with the familiar `fetch(url, options)` signature.

For dynamic proxy selection, create a function that returns different agents based on the target URL, geographic requirements, or rotation schedule. Pass this function as the `agent` option and node-fetch will call it for each request, enabling per-request proxy assignment. This pattern works well for geographic targeting where different destination regions require proxies in matching locations.

Common Pitfalls

The major version split between node-fetch v2 and v3 catches many developers. Version 2 uses CommonJS (`require()`), while version 3 is ESM-only (`import`). If your project uses CommonJS modules and you install v3, you will get an ERR_REQUIRE_ESM error at runtime. Pin to `node-fetch@2` for CommonJS projects, or migrate your entire project to ESM with `"type": "module"` in package.json before upgrading.

node-fetch does not throw on non-2xx HTTP responses, unlike Axios. A 407 Proxy Authentication Required response will not trigger a catch block; instead, `response.ok` will be false. Always check `response.ok` or `response.status` before attempting to parse the response body. Failing to do this means proxy authentication failures silently produce garbage data instead of actionable errors.

Performance Optimization

node-fetch benefits from the same connection pooling strategies as other Node.js HTTP clients. Create the `HttpsProxyAgent` with `keepAlive: true` and reuse it across all fetch calls to maintain persistent TCP connections to the proxy. For workloads that hit multiple proxy endpoints, maintain a Map of agents keyed by proxy URL to ensure each endpoint gets its own connection pool without creating duplicate agents.

Stream large responses using `response.body` (a Node.js Readable stream) instead of buffering the entire response with `response.text()` or `response.json()`. This is critical for proxy workloads that download large files or process paginated API responses with thousands of pages. Streaming keeps memory usage constant regardless of response size and allows you to process data as it arrives rather than waiting for the complete download.

Tips

  • 1
    node-fetch v2 uses CommonJS; v3 is ESM-only. Match your project setup.
  • 2
    Check response.ok before parsing to catch non-2xx proxy responses.
  • 3
    Reuse the agent across fetch calls to benefit from keep-alive connections.

Ready to Integrate?

Get proxy credentials and start coding in minutes.