Node.js Proxy Setup: axios, got, fetch & undici (2026 Guide)

Published June 6, 2026 · 10 min read

Every Node.js HTTP client handles proxies differently, and half of them don't handle proxy authentication at all without a helper package. axios silently ignores its own proxy option for HTTPS targets in some versions, native fetch has no proxy option whatsoever, and the error messages — ECONNRESET, 407, or just a hang — tell you nothing.

This is the complete, working reference for routing axios, got, node-fetch, native fetch (undici), and superagent through authenticated residential proxies. It's the Node companion to our Python guides (requests/httpx/aiohttp, Scrapy). All examples use the standard placeholder format — swap in your real credentials:

socks5h://USERNAME:[email protected]:913

The One Rule That Prevents Most Bugs

Don't use the built-in proxy options. Use a proxy agent. Node's HTTP clients delegate connection handling to an "agent" object, and the agent packages (https-proxy-agent, socks-proxy-agent) implement CONNECT tunneling and authentication correctly. The built-in options often don't — axios's proxy config is the most notorious example.

npm install socks-proxy-agent https-proxy-agent

axios

const axios = require("axios");
const { SocksProxyAgent } = require("socks-proxy-agent");

const agent = new SocksProxyAgent(
  "socks5h://USERNAME:[email protected]:913"
);

const res = await axios.get("https://api.ipify.org?format=json", {
  httpAgent: agent,    // for http:// targets
  httpsAgent: agent,   // for https:// targets
  proxy: false,        // IMPORTANT: disable axios's own proxy handling
});
console.log(res.data); // -> the proxy's exit IP

Two things people miss: you must set both httpAgent and httpsAgent (axios picks by target scheme), and you must set proxy: false so axios doesn't also try to apply HTTP_PROXY environment variables on top of your agent.

got

const got = require("got");
const { SocksProxyAgent } = require("socks-proxy-agent");

const agent = new SocksProxyAgent(
  "socks5h://USERNAME:[email protected]:913"
);

const body = await got("https://api.ipify.org?format=json", {
  agent: { http: agent, https: agent },
}).json();

If you're scraping protected targets with got, look at got-scraping instead — same API, plus browser-like header generation and HTTP/2 fingerprint mimicry (why that matters: JA3/JA4 explained).

Native fetch / undici (Node 18+)

Node's built-in fetch comes from undici, ignores proxy environment variables, and has no agent option. The undici way is a dispatcher:

const { ProxyAgent } = require("undici");

// undici's ProxyAgent speaks HTTP CONNECT (use your HTTP proxy port)
const dispatcher = new ProxyAgent({
  uri: "http://us.jibaoproxy.com:1000",
  token: "Basic " + Buffer.from("USERNAME:PASSWORD").toString("base64"),
});

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

Note: undici's ProxyAgent is HTTP-proxy only. For SOCKS5 with native fetch, either front it with a local forwarder or use a client that accepts socks agents (axios/got above).

node-fetch (v2/v3)

const fetch = require("node-fetch");
const { SocksProxyAgent } = require("socks-proxy-agent");

const agent = new SocksProxyAgent(
  "socks5h://USERNAME:[email protected]:913"
);

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

Rotation: New Identity Per Request vs Sticky Sessions

With a rotating residential gateway you don't manage IP lists — the gateway hands you a fresh exit per connection, or holds one exit per session id. In Node that maps cleanly to one agent per identity:

// Sticky: same session id -> same exit IP across requests
function identityAgent(sessionId) {
  return new SocksProxyAgent(
    `socks5h://USERNAME-session-${sessionId}:[email protected]:913`
  );
}

// Account A keeps IP A, account B keeps IP B - cookies and IP move together
const agentA = identityAgent("acct_a");
const agentB = identityAgent("acct_b");

Reuse the agent for connection pooling within an identity; never share one agent across identities. When to rotate vs stick is its own topic — see sticky vs rotating sessions.

Troubleshooting Table

SymptomCauseFix
407 Proxy Authentication RequiredCredentials not reaching the proxyPut user:pass in the agent URL, not the client config
axios works on http://, fails on https://Only httpAgent setSet httpsAgent too, and proxy: false
ECONNRESET immediatelyWrong port / wrong protocol (HTTP port with SOCKS agent)Match agent type to port
DNS leaks / internal hostnames failsocks5:// resolves DNS locallyUse socks5h:// — the h sends hostnames through the proxy
Native fetch ignores HTTP_PROXYundici doesn't read env varsPass a dispatcher explicitly
Works locally, 403 on target siteNot a proxy bug — TLS fingerprintgot-scraping or a real browser; see TLS guide
Free tool · no signup

Verify your proxy before you debug your code

Half of "my Node proxy code is broken" is actually a dead or misconfigured proxy. Paste your proxy URL into our checker — it tests connectivity, auth, exit IP, and latency in one shot.

Check my proxy →

Need IPs that pass reputation checks too? Get residential proxies with 500MB free traffic →

Summary

Residential Proxies for Node.js

SOCKS5 + HTTP endpoints, sticky or rotating, per-GB pricing — 500MB free traffic, no card required.

Start Free Trial
Universal for All IP Products · Massive Nodes Always Available

Join now & enjoy up to 100% deposit bonus.

New users get 500MB free traffic instantly, plus an extra first-deposit reward — limited-time offer.