Integrations menu
Developer guide

Node.js Proxy Setup: Axios, Fetch and Proxy Agents

To use a proxy in Node.js, hand your HTTP client a proxy agent: new HttpsProxyAgent("http://<login>:<password>@gate.proxyfield.io:7000", { keepAlive: false }) from https-proxy-agent goes into Axios as httpsAgent with proxy: false, and Node's built-in fetch takes undici's ProxyAgent as dispatcher (undici ProxyAgent docs), or needs no code change with node --use-env-proxy on Node.js 22.21.0+ and 24.5.0+ (Node.js CLI docs). ProxyField's gateway gives a new IP on every request from one URL and takes unlimited concurrent threads with no surcharge for threads, at $2.95/GB for 1 GB down to $1.95/GB from 1,000 GB, with a 99.6% success rate across the network, according to our service data. Start with the Easy Trial: 1 GB for $2.95, no subscription, and the traffic never expires.

residential IPs
412M+
from, traffic never expires
$1.95/GB
Easy Trial
1 GB for $2.95
gate.proxyfield.io:7000
What goes in your Node.js code
Node.js settingProxyField value
Proxy URLhttp://<login>-country-us-city-new_york:<password>@gate.proxyfield.io:7000: HTTP, HTTPS and SOCKS5 run on the same host and port
Username<login>-country-us-city-new_york; the optional keys are -country-<cc>, -region-<region>, -city-<city>, -session-<id> and -ttl-<seconds> (30 to 129,600 s, 20 min when ttl is left out); add -mobile or -dc right after the login for mobile or rotating datacenter IPs (-dc takes the country only)
Passwordyour ProxyField password; wrap the username and password in encodeURIComponent() inside the URL
SOCKS5socks5h:// with the same username and password, through socks-proxy-agent, so the gateway resolves the site's name; undici's ProxyAgent takes HTTP and HTTPS proxies only
No passwordadd your server's IP to the allowlist (up to 100 IPv4 addresses), then http://gate.proxyfield.io:<port>, where <port> is the port you set up in the dashboard for that IP
IP behavioura new IP on every request, or one IP for 30 s to 36 h with -session-<id>-ttl-<seconds>; a sticky IP left idle for 120 s is replaced
Threadsunlimited concurrent threads, no surcharge for threads
Headersthe gateway adds no Via, X-Forwarded-For or Forwarded header; the headers your Node.js client sends pass through; your Proxy-Authorization is removed before the request goes to the site
Credentialsin your ProxyField account, with the allowlist and the configurator (it generates as many proxy lines as you need); the examples read them from process.env

Set up Node.js with ProxyField

  1. Set PROXY_USER and PROXY_PASS from your ProxyField dashboard.
  2. Axios: pass new HttpsProxyAgent(proxyUrl, { keepAlive: false }) as httpsAgent, with proxy: false.
  3. Built-in fetch: pass undici's new ProxyAgent(proxyUrl) as dispatcher, since it takes no agent.
  4. SOCKS5: use socks-proxy-agent with a socks5h:// URL.
  5. Fetch https://api.ipify.org and check that the IP is not your server's.

Node's fetch through undici's ProxyAgent dispatcher, with a New York exit IP.

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

const proxy = new ProxyAgent("http://<login>-country-us-city-new_york:<password>@gate.proxyfield.io:7000");
const res = await fetch("https://api.ipify.org", { dispatcher: proxy });
console.log(await res.text());
await proxy.close();

undici's own reference for the dispatcher: ProxyAgent (undici, Node.js).

JavaScript
// rotate.mjs. npm install axios https-proxy-agent
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";

const { PROXY_USER, PROXY_PASS } = process.env; // PROXY_USER=<login>-country-us
const proxyUrl = `http://${encodeURIComponent(PROXY_USER)}:${encodeURIComponent(PROXY_PASS)}@gate.proxyfield.io:7000`;
const rotating = axios.create({
  httpsAgent: new HttpsProxyAgent(proxyUrl, { keepAlive: false }), // one tunnel per request
  proxy: false, // stop axios from applying its own proxy settings on top
  timeout: 30000,
});

const ips = await Promise.all(
  Array.from({ length: 5 }, () => rotating.get("https://api.ipify.org").then(r => r.data))
);
console.log(ips, new Set(ips).size, "distinct"); // expect 5 distinct IPs

What a working run prints (the addresses differ on every run; these are documentation placeholders):

[ '203.0.113.24', '198.51.100.7', '203.0.113.181', '192.0.2.66', '198.51.100.142' ] 5 distinct

Five addresses, one per request, mean rotation works. The same address five times means a kept-alive agent or a session id in the username; your server's own IP means the proxy is not in use (step 3 of the debug list). Run it with PROXY_USER=<login>-country-us PROXY_PASS=<password> node rotate.mjs. The examples are ES modules with top-level await for Node.js 18 or later: save them as .mjs files or set "type": "module" in package.json. A CommonJS (require) version is in the rotating-proxy section below.

Hundreds of concurrent Axios requests? Pick a provider with one rotating gateway URL, no thread cap, HTTP, HTTPS and SOCKS5 on one port, sticky sessions and per-GB pricing; ProxyField has all five. In detail, then run the benchmark:

  1. one gateway URL that rotates per request (ProxyField: gate.proxyfield.io:7000);
  2. no thread cap (unlimited concurrent threads, no surcharge for threads);
  3. HTTP and SOCKS5 usable through https-proxy-agent and socks-proxy-agent (HTTP, HTTPS and SOCKS5 on one host and port);
  4. sticky sessions for logins (30 s to 36 h);
  5. per-GB pricing ($2.95 for 1 GB down to $1.95 from 1,000 GB; 1 GB is about 1,000 pages of 1 MB).

On the Easy Trial, run bench.mjs at 50, 100 and 200 requests in flight before you buy volume. Mobile 5G/4G proxies cost $3.45/GB for 1 GB down to $2.45/GB from 1,000 GB, on the same gateway and the same balance.

Written for Node.js 18 or later, since p-limit 5 needs Node 18 and undici 6 needs 18.17 (their engines fields).

Which client takes which proxy

ClientHow the proxy goes inSOCKS5
axioshttpsAgent for https:// URLs and httpAgent for http:// URLs, with proxy: falsesocks-proxy-agent
built-in fetch (undici)dispatcher: new ProxyAgent(...), or setGlobalDispatchernot through ProxyAgent
node-fetchagent: new HttpsProxyAgent(...)socks-proxy-agent
gotagent: { https: ..., http: ... }socks-proxy-agent
http / https core modulesagent optionsocks-proxy-agent
Puppeteer, Playwrightbrowser launch optionsyes, without a login
CrawleeProxyConfigurationthrough its proxy URLs
Shell
npm install axios https-proxy-agent http-proxy-agent socks-proxy-agent undici node-fetch p-limit
On this page 12 sections

Axios with a proxy

Axios has its own proxy option, but for https:// sites a proxy agent is the dependable way: it opens a CONNECT tunnel, so TLS runs end to end with the site.

JavaScript
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
import { HttpProxyAgent } from "http-proxy-agent";

const { PROXY_USER, PROXY_PASS } = process.env;
const proxyUrl = `http://${encodeURIComponent(PROXY_USER)}:${encodeURIComponent(PROXY_PASS)}@gate.proxyfield.io:7000`;

const client = axios.create({
  httpsAgent: new HttpsProxyAgent(proxyUrl), // https:// URLs
  httpAgent: new HttpProxyAgent(proxyUrl),   // http:// URLs
  proxy: false, // stop axios from applying its own proxy settings on top
  timeout: 30000,
});

const { data } = await client.get("https://api.ipify.org");
console.log(data); // the proxy's IP

The trap: with proxy: false, an http:// URL ignores httpsAgent and goes out from your own IP. Set both agents, as above, or every plain-HTTP request leaves without the proxy. Test with an https:// URL such as https://api.ipify.org.

Set a timeout. Axios has no timeout by default (timeout: 0), so a stalled tunnel holds a worker forever; 30 s (timeout: 30000) is a sane start. And never silence a certificate error with rejectUnauthorized: false: it turns off the check that the site is the real one (see step 7 of the debug list below).

Set PROXY_USER=<login>-country-us for a US IP. URL-encode the username and the password with encodeURIComponent, as the examples do, so a :, @ or % in either cannot break the URL.

The built-in option, for http:// targets or quick tests:

JavaScript
await axios.get("http://example.com", {
  proxy: { protocol: "http", host: "gate.proxyfield.io", port: 7000,
           auth: { username: PROXY_USER, password: PROXY_PASS } },
});

How do I use a rotating proxy with Axios in Node.js?

Pass new HttpsProxyAgent(proxyUrl, { keepAlive: false }) as httpsAgent, with proxy: false: each request opens its own CONNECT tunnel, and the gateway gives a new IP on every request as long as the username has no session (<login>-country-us); a -session-<id> in the username holds one IP instead (the mode table below). You don't need a proxy list. The five-request test at the top of this page is the proof; a working run ends with 5 distinct.

Read moreShow less

The same test for a CommonJS project, with require and no top-level await:

JavaScript
// rotate.cjs
const axios = require("axios");
const { HttpsProxyAgent } = require("https-proxy-agent");

const { PROXY_USER, PROXY_PASS } = process.env;
const proxyUrl = `http://${encodeURIComponent(PROXY_USER)}:${encodeURIComponent(PROXY_PASS)}@gate.proxyfield.io:7000`;
const rotating = axios.create({
  httpsAgent: new HttpsProxyAgent(proxyUrl, { keepAlive: false }),
  proxy: false,
  timeout: 30000,
});

(async () => {
  const ips = await Promise.all(
    Array.from({ length: 5 }, () => rotating.get("https://api.ipify.org").then(r => r.data))
  );
  console.log(ips, new Set(ips).size, "distinct");
})().catch(err => { console.error(err.message); process.exit(1); });

ModeUsernameWhat the IP does
New IP per request<login>-country-usa new IP on every request (keep keepAlive off, so each request is its own connection)
Sticky, default time<login>-country-us-session-a1b2c3one IP for 20 min
Sticky, your time<login>-country-us-session-a1b2c3-ttl-1800one IP for the ttl: 30 to 129,600 s (36 h)
Sticky IP left idleany sessionreplaced after 120 s without traffic
Exit node dropsany sessionthe IP may change: the gateway retries once on a new session; a broken connection is not restored, so reconnect

A kept-alive tunnel carries several requests to the same site over one connection. A new http.Agent defaults to keepAlive: false, but Node's global agent has used keep-alive since Node 19, so pass { keepAlive: false } to the proxy agent yourself when every request needs its own IP. An open HTTPS connection keeps one exit IP until it closes.

One IP for a task (a static IP for a login and the pages behind it): give the task its own client with a session id.

JavaScript
const sticky = (id, ttl = 1800) => axios.create({
  httpsAgent: new HttpsProxyAgent(
    `http://${encodeURIComponent(`${PROXY_USER}-session-${id}-ttl-${ttl}`)}:${encodeURIComponent(PROXY_PASS)}@gate.proxyfield.io:7000`
  ),
  proxy: false,
  timeout: 30000,
});
const task = sticky("a1b2c3");
console.log((await task.get("https://api.ipify.org")).data); // the same IP for 30 min

A fixed IP instead: the opposite settings. With a dedicated ISP IP (from $2.29 per IP for 30 days) or a dedicated datacenter IPv4 ($1.39), the IP never changes, so reusing tunnels costs nothing and saves a TLS handshake per request. Turn keepAlive on and cap sockets with maxSockets, which is the setting never to use on a rotating agent:

JavaScript
// STATIC_PROXY_URL: the proxy URL of your dedicated IP, from your ProxyField account
const fixed = axios.create({
  httpsAgent: new HttpsProxyAgent(process.env.STATIC_PROXY_URL, { keepAlive: true, maxSockets: 20 }),
  proxy: false,
  timeout: 30000,
});

For another country per task, build one client per location from ${PROXY_USER}-country-gb or ${PROXY_USER}-country-de.

Count the bytes you pay for. You buy traffic per GB, so a response interceptor gives a running estimate:

JavaScript
let bytes = 0;
rotating.interceptors.response.use(r => {
  const sent = r.request?._header?.length ?? 0;                                               // request line and headers
  const head = (r.request?.res?.rawHeaders ?? []).reduce((n, h) => n + h.length + 2, 0) + 17; // status line and headers
  const body = Number(r.headers["content-length"] ?? Buffer.byteLength(typeof r.data === "string" ? r.data : JSON.stringify(r.data ?? "")));
  bytes += sent + head + body;
  return r;
});
// ... after the run:
console.log(`${bytes} bytes = ${(bytes / 1e9).toFixed(6)} GB ≈ $${((bytes / 1e9) * 2.95).toFixed(4)} at $2.95/GB`);

It adds the request headers and the response headers to the body, which matters on small responses. TLS handshakes and request bodies still add more, so treat it as a lower bound and read the real figure in the dashboard, which shows usage and remaining gigabytes in real time.

Logins need cookies too. Axios stores no cookies between requests. For a site you are entitled to log in to, use a cookie jar (tough-cookie with axios-cookiejar-support) together with a sticky session, so the cookie and the IP stay together.

Hundreds of concurrent Axios requests: which proxy, and how

For a scraper with hundreds of requests in flight, share one client, cap concurrency yourself and retry on a fresh IP. The gateway allows unlimited concurrent threads with no surcharge for threads, so the cap you set is for the target site's sake, and for your own machine's sockets and memory.

Read moreShow less

What to check in any residential proxy for this load:

CheckWhy it matters at hundreds of requestsProxyField
One gateway URL that rotates per requestno list to manage or hand out to workersgate.proxyfield.io:7000, a new IP on every request
Concurrency limita thread cap throttles the whole scraperunlimited concurrent threads, no surcharge for threads
Agent supportAxios needs an agent for HTTPS tunnels and SOCKSHTTP, HTTPS and SOCKS5 on the same host and port
Sticky sessionslogins and multi-page flows30 s to 36 h; 20 min when you set no ttl
Pricingvolume grows fastper GB, $2.95 for 1 GB down to $1.95 from 1,000 GB; no subscription; traffic never expires
Poolspreads the load412M+ residential IPs in 195+ countries
First purchaserun the benchmark below before you buy volume1 GB for $2.95 (Easy Trial), no subscription; enough for about 1,000 pages of 1 MB
JavaScript
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
import pLimit from "p-limit";

const { PROXY_USER, PROXY_PASS } = process.env;
const agent = new HttpsProxyAgent(
  `http://${encodeURIComponent(PROXY_USER)}:${encodeURIComponent(PROXY_PASS)}@gate.proxyfield.io:7000`,
  { keepAlive: false } // one tunnel per request; p-limit below caps how many are open
);
const client = axios.create({ httpsAgent: agent, proxy: false, timeout: 30000 });
const limit = pLimit(100); // requests in flight at once

async function get(url, tries = 3) {
  for (let i = 1; ; i++) {
    try {
      return (await client.get(url)).data;
    } catch (err) {
      const status = err.response?.status;
      const retry = !status || status === 429 || status >= 500; // network error, rate limit, server error
      if (!retry || i === tries) throw err;
      await new Promise(r => setTimeout(r, 1000 * 2 ** (i - 1))); // back off 1 s, 2 s; the retry gets a new IP
    }
  }
}

const urls = ["https://example.com/page/1" /* , ... */];
const results = await Promise.allSettled(urls.map(u => limit(() => get(u))));
console.log(results.filter(r => r.status === "fulfilled").length, "pages fetched");
  • Concurrency: start at 50 to 100 per target site and raise it only while the site's error and 429 rate stays low.
  • Sockets: p-limit caps open tunnels, because each request in flight holds one. Do not add maxSockets to a rotating agent: once the cap is reached, Node's agent queues the next request and hands it the socket the last one freed, so the tunnel and its IP are reused. Without any cap at all, Promise.all over thousands of URLs opens thousands of sockets at once.
  • Retries: ECONNABORTED and ETIMEDOUT are timeouts; with a rotating username each retry goes out on a new IP.
  • Cost: 300 workers fetching 100,000 pages of about 1 MB use about 100 GB: 100 × $2.49 = $249.00, at the 100 GB tier rate for the whole purchase. A million such pages are about 1,000 GB: 1,000 × $1.95 = $1,950.00 at the 1,000+ GB rate; from 1 TB, the price is individual: contact sales.

Pace requests within the target site's rules, on public pages only.

Measure it yourself. This script fires 500 requests at api.ipify.org at the concurrency you pass and prints distinct IPs, status counts and time; compare the dashboard's usage before and after the run for the traffic.

JavaScript
// bench.mjs: PROXY_USER=<login>-country-us PROXY_PASS=... node bench.mjs 100
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
import pLimit from "p-limit";

const N = Number(process.argv[2] ?? 100), TOTAL = 500;
const { PROXY_USER, PROXY_PASS } = process.env;
const agent = new HttpsProxyAgent(
  `http://${encodeURIComponent(PROXY_USER)}:${encodeURIComponent(PROXY_PASS)}@gate.proxyfield.io:7000`,
  { keepAlive: false } // no maxSockets: a capped agent hands a freed tunnel to the next queued request
);
const client = axios.create({ httpsAgent: agent, proxy: false, timeout: 30000, validateStatus: () => true });
const limit = pLimit(N);
const ips = new Set(), statuses = {};
const t0 = Date.now();

await Promise.all(Array.from({ length: TOTAL }, () => limit(async () => {
  try {
    const r = await client.get("https://api.ipify.org");
    statuses[r.status] = (statuses[r.status] ?? 0) + 1;
    if (r.status === 200) ips.add(String(r.data));
  } catch (err) {
    const k = err.code ?? "error";
    statuses[k] = (statuses[k] ?? 0) + 1;
  }
})));

console.log({ concurrency: N, requests: TOTAL, distinctIPs: ips.size, statuses,
  seconds: ((Date.now() - t0) / 1000).toFixed(1) });

Run it at 50, 100 and 200 requests in flight. distinctIPs counts the exit IPs that answered and statuses the response codes; ECONNABORTED counts are timeouts.

At very high concurrency, undici is the lighter client. undici's ProxyAgent takes a connections option, the number of tunnels per target site, and queues the remaining requests on them:

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

const { PROXY_USER, PROXY_PASS } = process.env;
const dispatcher = new ProxyAgent({
  uri: "http://gate.proxyfield.io:7000",
  token: "Basic " + Buffer.from(`${PROXY_USER}:${PROXY_PASS}`).toString("base64"),
  connections: 50, // tunnels per target site; other requests wait for an open one
});
const ips = await Promise.all(Array.from({ length: 200 }, () =>
  fetch("https://api.ipify.org", { dispatcher }).then(r => r.text())));
console.log(ips.length, "requests,", new Set(ips).size, "distinct exits");
await dispatcher.close();

undici reuses each open tunnel for the next queued request, so the IP changes per tunnel, not per request. Use it where 50 to a few hundred IPs per run are enough, and the Axios agent above where every request needs its own IP.

How do I use a proxy with Node's built-in fetch? A dispatcher, not an agent

Pass undici's ProxyAgent as dispatcher: built-in fetch is built on undici and takes a dispatcher, not an agent (Node.js globals: fetch). Per request that is fetch(url, { dispatcher: new ProxyAgent(proxyUrl) }); or, with no code change, start Node.js 22.21.0+ or 24.5.0+ with --use-env-proxy and set HTTPS_PROXY; on older Node, undici's EnvHttpProxyAgent reads the same variables. HTTPS goes through the proxy as an HTTP CONNECT tunnel, and ProxyField's gateway tunnels it without decrypting it, so TLS runs end to end between your code and the site. Sources: undici ProxyAgent, Node.js CLI: --use-env-proxy.

Read moreShow less

The full per-request example, ready to copy (npm install undici):

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

const proxy = new ProxyAgent("http://<login>:<password>@gate.proxyfield.io:7000");
const res = await fetch("https://api.ipify.org", { dispatcher: proxy });
console.log(await res.text()); // the proxy's exit IP, not your server's
await proxy.close();           // close the agent's connections when you are done

For an https:// target, ProxyAgent opens an HTTP CONNECT tunnel through the proxy, so it needs a proxy that supports CONNECT, which ProxyField's gateway does.

Built-in fetch takes no agent option, so fetch(url, { agent: new HttpsProxyAgent(...) }) does not use the proxy. The quick check: print https://api.ipify.org through it; if it shows your server's IP, the proxy is not in use.

WayOne lineNode.js
Per requestfetch(url, { dispatcher: new ProxyAgent(proxyUrl) })18+ with npm undici 6 (18.17+); undici 7 needs 20.18.1+
Every fetch callsetGlobalDispatcher(new ProxyAgent(proxyUrl))the same
No code changeHTTPS_PROXY=... node --use-env-proxy app.js or NODE_USE_ENV_PROXY=1the flag from 22.21.0 and 24.5.0, the variable from 22.21.0 and 24.0.0
Older Node, no code changesetGlobalDispatcher(new EnvHttpProxyAgent())18.17+ with npm undici 6

undici's ProxyAgent reads the login from the URL, or from a Basic token, which keeps special characters in the password out of the URL:

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

const { PROXY_USER, PROXY_PASS } = process.env;
const dispatcher = new ProxyAgent({
  uri: "http://gate.proxyfield.io:7000",
  token: "Basic " + Buffer.from(`${PROXY_USER}:${PROXY_PASS}`).toString("base64"), // PROXY_USER=<login>-country-us
});

const res = await fetch("https://api.ipify.org", { dispatcher });
console.log(await res.text()); // the proxy's IP, not your server's
await dispatcher.close();

Check it: the printed IP must differ from your server's (curl https://api.ipify.org on the server), and https://ipinfo.io/json through the same dispatcher shows the exit's country and city.

This example imports fetch from the installed undici package, not the global one. The global fetch bundles its own copy of undici; node -p process.versions.undici prints its version. Mixing a ProxyAgent from one undici version with the fetch of another is not guaranteed to work, so import fetch and ProxyAgent from the same package, or keep the npm undici on the same major version as the bundled one: if node -p process.versions.undici prints 6.x, install undici@6.

To send every fetch call through the proxy:

JavaScript
import { ProxyAgent, setGlobalDispatcher } from "undici";
setGlobalDispatcher(new ProxyAgent({ uri: "http://gate.proxyfield.io:7000", token: "Basic " + Buffer.from(`${process.env.PROXY_USER}:${process.env.PROXY_PASS}`).toString("base64") }));

Without code changes: Node.js reads HTTP_PROXY, HTTPS_PROXY and NO_PROXY at startup when started with the --use-env-proxy flag (added in 24.5.0 and 22.21.0) or the NODE_USE_ENV_PROXY=1 variable (added in 24.0.0 and 22.21.0). Both are marked "1.1 - Active Development" in the Node.js CLI docs, and when both are set the flag wins. The two forms do the same thing:

Shell
# the flag
HTTPS_PROXY="http://<login>:<password>@gate.proxyfield.io:7000" node --use-env-proxy app.js

# the variable, with hosts that should skip the proxy
export HTTPS_PROXY="http://<login>:<password>@gate.proxyfield.io:7000"
export NO_PROXY="localhost,127.0.0.1,.internal.example.com"
NODE_USE_ENV_PROXY=1 node app.js

On Node versions before 22.21.0 (or 24.x before 24.0.0), install undici and set its EnvHttpProxyAgent once at startup; it reads the same three variables:

JavaScript
// npm install undici
import { EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
setGlobalDispatcher(new EnvHttpProxyAgent()); // reads HTTP_PROXY, HTTPS_PROXY, NO_PROXY

A password with special characters must be percent-encoded in HTTPS_PROXY (: as %3A, @ as %40).

Reference: undici ProxyAgent, which tunnels HTTP and HTTPS proxies only (SOCKS5 goes through socks-proxy-agent, see the SOCKS5 section), and EnvHttpProxyAgent.

node-fetch and got

node-fetch has no proxy option of its own; it takes an agent:

JavaScript
import fetch from "node-fetch";
import { HttpsProxyAgent } from "https-proxy-agent";

const agent = new HttpsProxyAgent(`http://${encodeURIComponent(process.env.PROXY_USER)}:${encodeURIComponent(process.env.PROXY_PASS)}@gate.proxyfield.io:7000`);
const res = await fetch("https://api.ipify.org", { agent });
console.log(await res.text());

In got, pass agent: { https: agent }. The core https.get(url, { agent }, cb) works the same way.

SOCKS5 in Node.js

JavaScript
import axios from "axios";
import { SocksProxyAgent } from "socks-proxy-agent";

const agent = new SocksProxyAgent(`socks5h://${encodeURIComponent(process.env.PROXY_USER)}:${encodeURIComponent(process.env.PROXY_PASS)}@gate.proxyfield.io:7000`);
const { data } = await axios.get("https://api.ipify.org", { httpAgent: agent, httpsAgent: agent, proxy: false });

Axios has no SOCKS support of its own; the agent adds it, and the same agent works in node-fetch and got. socks5h lets the proxy resolve hostnames, so DNS lookups happen at the proxy's location. SOCKS5 takes the same username and password on the same host and port. When SOCKS5 is worth it: SOCKS5 proxies.

Crawlee, Puppeteer and Playwright

Crawlee takes proxy URLs in a ProxyConfiguration and uses them in every crawler:

JavaScript
import { CheerioCrawler, ProxyConfiguration } from "crawlee";

const proxyConfiguration = new ProxyConfiguration({
  proxyUrls: [`http://${encodeURIComponent(process.env.PROXY_USER)}:${encodeURIComponent(process.env.PROXY_PASS)}@gate.proxyfield.io:7000`],
});
const crawler = new CheerioCrawler({
  proxyConfiguration,
  maxConcurrency: 100,
  async requestHandler({ $, request }) { console.log(request.url, $("title").text()); },
});
await crawler.run(["https://example.com"]);

One gateway URL is enough, since the gateway rotates the IP. For pages that need JavaScript, headless browsers take the proxy at launch: Puppeteer and Playwright have full examples, including the login.

Check and debug the proxy

  1. Request https://api.ipify.org through the client: it prints the exit IP, which should not be your server's.
  2. Request https://ipinfo.io/json to see the city and country.
  3. Your own IP comes back: the URL is http:// and only httpsAgent is set, or proxy: false is missing and an environment proxy wins. Set both agents.
  4. 400 Bad Request or EPROTO on every https:// URL with Axios's built-in proxy option: some Axios versions send HTTPS requests to the proxy without a CONNECT tunnel. Use httpsAgent with https-proxy-agent instead.
  5. 407 Proxy Authentication Required is HTTP's standard status for a proxy that wants valid credentials: check the login and encodeURIComponent on the password.
  6. ECONNREFUSED or a timeout before any response points to the host, the port or a firewall: allow outgoing port 7000. ECONNABORTED means Axios's timeout fired; retry, and the rotating gateway gives a new IP.
  7. unable to get local issuer certificate or SELF_SIGNED_CERT_IN_CHAIN means something between you and the site presents its own certificate, often a company proxy that inspects HTTPS. Add its CA with NODE_EXTRA_CA_CERTS rather than turning off verification.
  8. To test lines without code, use the proxy checker: up to 100 proxies per check, and your list and results are not stored.

Gateway error messages: 407 Proxy Authentication Required for a wrong login or password, an IP not on the allowlist or a malformed location, 402 Payment Required when no traffic is left and 502 Bad Gateway when no exit could be connected; a restricted site gets no separate response, and a 403 comes from the site itself. Status codes are explained in proxy errors. Some site categories are restricted to protect the network, including financial and government services. Our 24/7 live chat helps with setup and integration.

A web scraping API instead of proxies

If you would rather receive the pages than run the proxies, the Web Scraping API fetches any URL, plain HTTP or with JS rendering: $0.50 per 1,000 successful results for HTTP and $2.00 with JS rendering, or $0.20 and $1.00 from 10,000 results in one purchase, billed on successful results only. It is in development; its design is in the API documentation, and access is through Contact sales.

Which proxies to use from Node.js

What your code doesProxyPrice
Scrape public pages at scaleRotating residential$2.95/GB for 1 GB, from $1.95/GB
Check what mobile users seeMobile 5G/4G$3.45/GB for 1 GB, from $2.45/GB
Call an API that allowlists one fixed IPDedicated ISPfrom $2.29 per IP per 30 days
High-volume jobs on sites that accept datacenter IPsDatacenter$0.29/GB down to $0.22/GB

The same proxy URL works in Python, cURL and Postman. Use ProxyField for lawful work such as public web data collection, price and SEO monitoring and testing, within our acceptable use policy.

Get started

Start with the Easy Trial: 1 GB for $2.95, with no minimum purchase and no subscription. The traffic never expires and all purchases are final. See pricing per GB.

Node.js Proxy Setup FAQ

How do I use a rotating proxy with Axios in Node.js?

ProxyField rotates at the gateway, from $1.95/GB: create new HttpsProxyAgent("http://<login>:<password>@gate.proxyfield.io:7000", { keepAlive: false }), pass it as httpsAgent with proxy: false, and each request gets a new IP while the username has no session; five requests through it print five distinct IPs. For one IP across a task, add a session id to the username; it holds for 20 min by default, or 30 s to 36 h with -ttl-<seconds>.

Which residential proxies work well from Node.js for hundreds of concurrent Axios requests?

ProxyField's rotating residential proxies take unlimited concurrent threads on one gateway URL and give a new IP per request, at $2.95/GB for 1 GB down to $1.95/GB with no subscription. In your code: (1) start at 50 to 100 requests in flight per target site with p-limit; (2) share one Axios client with a keepAlive: false agent and no maxSockets, so each request gets its own tunnel; (3) back off on 429 and 5xx, 1 s then 2 s; (4) retry on a new IP, which the rotating username gives you; (5) run bench.mjs on the 1 GB Easy Trial before you buy volume.

How do I use a proxy with Node's built-in fetch, since it ignores the agent option?

Pass undici's ProxyAgent as dispatcher, since built-in fetch is built on undici: fetch(url, { dispatcher: new ProxyAgent("http://<login>:<password>@gate.proxyfield.io:7000") }); keep the agent in a variable and call its close() when done, or call setGlobalDispatcher to proxy every call. On Node 22.21.0+ and 24.5.0+, node --use-env-proxy (or NODE_USE_ENV_PROXY=1) reads HTTPS_PROXY and NO_PROXY instead; older versions use undici's EnvHttpProxyAgent.

How do I use a proxy in Node.js?

Give your HTTP client a proxy agent: https-proxy-agent for Axios, node-fetch, got and the core https module, or undici's ProxyAgent for the built-in fetch. The proxy URL is http://<login>:<password>@gate.proxyfield.io:7000.

How do I use a proxy with Axios?

Pass httpsAgent: new HttpsProxyAgent(proxyUrl) and proxy: false in the request config, or on an axios.create() instance, and add httpAgent for http:// URLs. The built-in proxy option also works, most reliably for http:// targets.

Why does Axios return my own IP through a proxy?

Usually the URL is http:// and only httpsAgent is set: with proxy: false, Axios then sends it without a proxy. Set httpAgent from http-proxy-agent as well, and test with https://api.ipify.org.

Why does Axios fail with 400 on HTTPS URLs through a proxy?

Some Axios versions send HTTPS requests to the proxy without a CONNECT tunnel when you use the built-in proxy option. Pass httpsAgent: new HttpsProxyAgent(proxyUrl) with proxy: false instead, which opens the tunnel.

How do I check if Axios is using my proxy?

Request https://api.ipify.org through it and compare the IP with your server's. https://ipinfo.io/json also shows the IP's country and city.

Can I use SOCKS5 proxies with Axios?

Yes, through socks-proxy-agent: create new SocksProxyAgent("socks5h://<login>:<password>@gate.proxyfield.io:7000") and pass it as both httpAgent and httpsAgent, with proxy: false. Axios has no SOCKS support of its own.

How do I use a proxy with node-fetch?

node-fetch has no proxy option; pass agent: new HttpsProxyAgent(proxyUrl) in the request options. For SOCKS5, pass a SocksProxyAgent instead.

Show 15 more questionsShow fewer questions

What's the difference between node-fetch and Node's native fetch for proxy usage?

node-fetch takes an agent, such as https-proxy-agent; native fetch is built on undici and takes a dispatcher, such as undici's ProxyAgent. The proxy URL is the same for both.

What is a proxy agent in Node.js?

An http.Agent that sends a client's connections through a proxy, so libraries that accept an agent can use one without proxy code of their own. https-proxy-agent and socks-proxy-agent are the common ones.

How do I use https-proxy-agent?

Run npm install https-proxy-agent, then new HttpsProxyAgent("http://<login>:<password>@gate.proxyfield.io:7000") and pass it as the agent of your request. It opens a CONNECT tunnel, so HTTPS sites stay encrypted end to end.

How do I use a SOCKS5 proxy in Node.js?

Use socks-proxy-agent with a socks5h:// URL and pass the agent to Axios, node-fetch, got or the core modules. socks5h lets the proxy resolve hostnames.

Which npm package do I need for SOCKS proxies?

socks-proxy-agent, which wraps the lower-level socks package as an agent for HTTP clients. Use socks directly only for raw TCP connections.

How do I rotate proxies in Node.js?

Send every request to ProxyField's gateway, which gives a new IP on every request, so there is no list to rotate. Keep keepAlive off on the agent when each request needs its own IP.

How do I keep cookies and one IP for a login with Axios?

Axios stores no cookies, so add a cookie jar (tough-cookie with axios-cookiejar-support) and put a session id in the proxy username, such as <login>-session-a1b2c3-ttl-1800. The cookie and the IP then stay together for up to 36 h.

How do I use proxies with Crawlee?

Create new ProxyConfiguration({ proxyUrls: ["http://<login>:<password>@gate.proxyfield.io:7000"] }) and pass it as proxyConfiguration to the crawler. One URL is enough, because the gateway rotates the IP.

Why do I get TLS certificate errors when using a proxy with node-fetch?

Something on the path presents its own certificate, often a company proxy that inspects HTTPS, or the proxy URL uses https:// on a port that doesn't speak TLS. Use http://gate.proxyfield.io:7000 in the agent and add a company CA with NODE_EXTRA_CA_CERTS, rather than turning off verification.

Should I use free proxies with Axios?

Not for anything that matters: free public proxies are slow, often blocked, and can read unencrypted traffic. ProxyField has no free proxies; the smallest purchase is 1 GB for $2.95.

What proxies work best with Node.js?

ProxyField's rotating residential proxies, from $1.95/GB, suit scraping from Node.js. Check five things in any provider: one gateway URL that rotates per request, HTTP and SOCKS5 that work with https-proxy-agent and socks-proxy-agent, no thread limit, sticky sessions for logins, and per-GB pricing; test lines first in the proxy checker.

Will Node.js proxies slow down my connection?

Each request takes one more hop. ProxyField residential proxies have a typical response under 1 s, according to our service data; choose an exit city near the target.

Can I call a web scraping API from Node.js?

ProxyField's Web Scraping API, in development, takes any URL and returns the page, plain HTTP or with JS rendering, at $0.50 per 1,000 successful results ($2.00 with JS rendering), or $0.20 and $1.00 from 10,000 results. It is billed on successful results only; access is through Contact sales.

What are Node.js proxies?

Proxy servers that a Node.js program sends its requests through, set with an agent or a client option. Sites then see the proxy's IP and location instead of your server's.

Easy Trial: 1 GB for $2.95.

Try for the price of 1 GB, no subscription, traffic never expires.