# Use a proxy with Node.js fetch

Source: https://ipvolt.com/guides/nodejs-fetch-proxy
Markdown: https://ipvolt.com/guides/nodejs-fetch-proxy.md

[Home](https://ipvolt.com/index.md) / [Guides](https://ipvolt.com/guides.md) / [Use a proxy with Node.js fetch](https://ipvolt.com/guides/nodejs-fetch-proxy.md)

Category: Integration
Reviewed: 2026-09-10
Reading time: 4 minutes
Author: ipvolt

Route Node.js native fetch through an Undici ProxyAgent with explicit authentication, an abort deadline and response cleanup.

## The starting point

Use a dispatcher for one fetch call so the proxy is explicit and other network clients in your process keep their own configuration.

## Choose a compatible runtime and dispatcher

This server-side example targets Node.js 24 and Undici 7. In a separate example project, run npm install undici@7. Node's built-in fetch accepts an Undici-compatible dispatcher. This is different from browser fetch, where page JavaScript cannot select an arbitrary system proxy.

Use a provider-documented HTTP(S) gateway in PROXY_URL, for example the deliberately nonworking https://proxy.example.invalid:8443. Inject PROXY_USERNAME and PROXY_PASSWORD through your deployment's secret manager. Do not put gateway credentials in frontend code.


## Keep proxy authentication on the dispatcher

Save as proxy-check.mjs and run node proxy-check.mjs. The Basic token belongs to the proxy agent, not to the destination's Authorization header. The request has a 30-second abort deadline and does not follow redirects automatically.

### proxy-check.mjs · Node.js 24 + Undici 7

```javascript
import { ProxyAgent } from 'undici';

function required(name) {
  const value = process.env[name];
  if (!value) throw new Error('Missing environment variable: ' + name);
  return value;
}

const gateway = new URL(required('PROXY_URL'));
if (!['http:', 'https:'].includes(gateway.protocol) || gateway.username || gateway.password) {
  throw new Error('Use a credential-free HTTP(S) proxy URL');
}
const credentials = required('PROXY_USERNAME') + ':' + required('PROXY_PASSWORD');
const dispatcher = new ProxyAgent({
  uri: gateway.href,
  token: 'Basic ' + Buffer.from(credentials).toString('base64'),
});

try {
  const response = await fetch('https://example.com/', {
    dispatcher,
    signal: AbortSignal.timeout(30_000),
    redirect: 'manual',
  });
  await response.body?.cancel();
  if (!response.ok) throw new Error('Destination HTTP ' + response.status);
  console.log({ status: response.status });
} finally {
  await dispatcher.close();
}
```


## Move from a diagnostic to a worker

This script deliberately cancels the response body because the diagnostic needs only a status. A worker that uses the result should consume the body within its budget. Always consume or cancel it before moving on, and close the dispatcher when the worker shuts down.

For repeated jobs, reuse a dispatcher with bounded concurrency rather than creating one per request. Keep each job's deadline separate. Do not install a process-wide dispatcher unless changing every affected client's routing is intentional.

- An HTTP error is a response; fetch does not reject merely because its status is 4xx or 5xx.
- A CONNECT rejection can surface as a fetch failure before a destination Response exists.
- Capture sanitized error categories; do not log the Basic token or full credential-bearing URLs.


## Before you ship

- Use the documented Node and Undici major versions.
- Pass the dispatcher explicitly.
- Consume or cancel response bodies and close the agent.

## Sources & further reading

- [Node.js: fetch and custom dispatchers](https://nodejs.org/api/globals.html#fetch)
- [Undici 7: ProxyAgent authentication and lifecycle](https://github.com/nodejs/undici/blob/v7.16.0/docs/docs/api/ProxyAgent.md)
- [Undici: runtime support and response body handling](https://github.com/nodejs/undici)

## Related guides

- [Use a proxy with curl](https://ipvolt.com/guides/curl-proxy-setup.md)
- [Proxy environment variables: HTTP_PROXY and NO_PROXY](https://ipvolt.com/guides/proxy-environment-variables.md)
- [HTTP vs SOCKS5 proxies: choose by the connection](https://ipvolt.com/guides/http-vs-socks5-proxies.md)

## About ipvolt

Examples use generic proxy settings, with links to the original technical documentation. Product-specific behavior must be checked with your provider. ipvolt is still in development.

## Know when access opens.

ipvolt · In development

We’re building proxy infrastructure for developers and data teams. Join the interest list for a heads-up when ipvolt is ready.

Consent: One email when access opens. Nothing else.

[Get early access](https://ipvolt.com/guides/nodejs-fetch-proxy#waitlist-closing). Use the email form on this page to join the interest list.

[Privacy](https://ipvolt.com/privacy)

