Node.js

Send Node.js requests through NyxonProxies with undici's ProxyAgent, fetch, axios and environment variables. Rotation, sticky sessions, SOCKS5 and errors.

Node's built-in fetch ignores proxy settings unless you tell it otherwise, and it fails silently: the request simply leaves from your own IP. This page shows the setups that work, with undici, axios and environment variables.

undici ProxyAgent

undici is the HTTP client behind Node's fetch, published as a package with extra features such as ProxyAgent:

bash
npm install undici
javascript
import { fetch, ProxyAgent } from "undici";

const proxy = new ProxyAgent("http://USERNAME:[email protected]:8080");

const res = await fetch("https://api.ipify.org?format=json", { dispatcher: proxy });
console.log(await res.json());

The proxy URL starts with http:// even for HTTPS sites. The agent opens a tunnel through the gateway and runs TLS to the site inside it.

To route every fetch in the process through the proxy, the built-in one included, set the agent as the global dispatcher:

javascript
import { ProxyAgent, setGlobalDispatcher } from "undici";

setGlobalDispatcher(new ProxyAgent("http://USERNAME:[email protected]:8080"));

const res = await fetch("https://api.ipify.org?format=json");
console.log(await res.json());

Environment variables

Recent Node versions read HTTPS_PROXY and the other standard variables when you opt in with NODE_USE_ENV_PROXY=1 or the --use-env-proxy flag:

bash
export HTTPS_PROXY="http://USERNAME:[email protected]:8080"
NODE_USE_ENV_PROXY=1 node app.mjs

The variable works from Node 24.0 and 22.21, and the flag from 24.5 and 22.21. Without either, fetch ignores the variables. See Environment variables for the differences between tools.

axios

axios has its own proxy option:

javascript
import axios from "axios";

const res = await axios.get("https://api.ipify.org?format=json", {
  proxy: {
    protocol: "http",
    host: "geo.gw.nyxon.sh",
    port: 8080,
    auth: { username: "USERNAME", password: "PASSWORD" },
  },
});
console.log(res.data);

The auth object takes the password as it is, special characters included. axios also reads HTTPS_PROXY by default, and proxy: false turns that off. Keep axios up to date: versions before 1.16.1 could mishandle HTTPS sites through an HTTP proxy.

A new IP on every request

An agent keeps its connections open and reuses them, so requests through one ProxyAgent share an IP, even when sent in parallel. For a new IP per request, give each request its own agent and close it afterwards:

javascript
import { fetch, ProxyAgent } from "undici";

async function viaNewIp(url) {
  const agent = new ProxyAgent("http://USERNAME:[email protected]:8080");
  try {
    const res = await fetch(url, { dispatcher: agent });
    return await res.text();
  } finally {
    await agent.close();
  }
}

for (let i = 0; i < 3; i++) console.log(await viaNewIp("https://api.ipify.org"));

Country and sticky session

Targeting and sessions go in the username:

javascript
import { randomBytes } from "node:crypto";
import { fetch, ProxyAgent } from "undici";

function stickyAgent(country, minutes = 10) {
  const sid = randomBytes(4).toString("hex");
  const user = `USERNAME-country-${country}-session-${sid}-time-${minutes}`;
  return new ProxyAgent(`http://${user}:[email protected]:8080`);
}

const agent = stickyAgent("us");
for (let i = 0; i < 3; i++) {
  const res = await fetch("https://api.ipify.org", { dispatcher: agent });
  console.log(await res.text());
}
await agent.close();

All three requests print the same US IP, for up to 10 minutes. See Rotating and sticky sessions.

SOCKS5

For axios and Node's http module, use socks-proxy-agent with a socks5h:// URL, so the gateway resolves the hostname:

bash
npm install socks-proxy-agent
javascript
import axios from "axios";
import { SocksProxyAgent } from "socks-proxy-agent";

const agent = new SocksProxyAgent("socks5h://USERNAME:[email protected]:1080");
const res = await axios.get("https://api.ipify.org?format=json", {
  httpAgent: agent,
  httpsAgent: agent,
});
console.log(res.data);

With socks5://, Node resolves the hostname itself and sends only the IP. For fetch, undici has a Socks5ProxyAgent, still marked experimental.

Passwords with special characters

Encode the credentials before you put them in the URL. undici decodes them again for the gateway:

javascript
import { fetch, ProxyAgent } from "undici";

const user = encodeURIComponent(process.env.PROXY_USER);
const pass = encodeURIComponent(process.env.PROXY_PASS);
const proxy = new ProxyAgent(`http://${user}:${pass}@geo.gw.nyxon.sh:8080`);

const res = await fetch("https://api.ipify.org?format=json", { dispatcher: proxy });
console.log(await res.json());

Errors

fetch reports every network failure as TypeError: fetch failed, and the reason is in err.cause. Log both:

javascript
try {
  await fetch("https://api.ipify.org", { dispatcher: proxy });
} catch (err) {
  console.error(err.message, err.cause);
}
What you seeCause
fetch failed, cause Request was cancelled.Wrong username or password. The 407 is not shown.
fetch failed, cause with code ECONNREFUSEDWrong host or port.
fetch failed, cause with code ERR_SSL_WRONG_VERSION_NUMBERhttps:// in front of the proxy URL. Use http://.
TypeError: Invalid URL from new ProxyAgentSpecial characters in the credentials were not encoded.
axios: Request failed with status code 407Wrong username or password.

Because a wrong password looks like a cancelled request in fetch, test new credentials with curl or axios, where the 407 is visible.

Last updated

Still stuck?

People answer the live chat around the clock. Send the proxy line you used (without the password) and the error you see.