Webshare Guides

Using Webshare Proxies with Node.js: undici fetch, axios and got

Working Node.js examples for Webshare proxies with undici fetch, axios and got, including the backbone gateway, direct lists, sticky sessions, SOCKS5, concurrency limits and error handling.

By Team of Monkeys Editorial Updated 3 min read Affiliate disclosure

This guide contains affiliate links to Geonode and Webshare. If you buy through them we may earn a commission, at no extra cost to you.

Webshare with Node.js illustration showing Node.js connecting through Webshare proxy to Website, covering undici, axios, got 3jdej38j4

The basics

Node.js doesn't apply a proxy automatically, so you attach one through an agent or dispatcher. With Webshare, you choose a proxy URL first:

  • Backbone: http://USERNAME-rotate:PASSWORD@p.webshare.io:80 (rotate per request) or a session username for stickiness.
  • Direct: http://USERNAME:PASSWORD@IP:PORT from your proxy list.

Keep credentials in environment variables. General background in Node.js and axios proxies.

undici and the built-in fetch

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

const proxy = `http://${process.env.WS_USER}-rotate:${process.env.WS_PASS}@p.webshare.io:80`;
const dispatcher = new ProxyAgent(proxy);

const res = await fetch("https://httpbin.org/ip", { dispatcher });
console.log(await res.json());

Create the agent once and reuse it; making a new agent per request wastes connections.

axios

axios's own proxy option doesn't handle HTTPS tunnelling well. Use an agent instead:

js
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";

const agent = new HttpsProxyAgent(`http://${user}-rotate:${pw}@p.webshare.io:80`);
const { data } = await axios.get("https://httpbin.org/ip", { httpsAgent: agent, proxy: false, timeout: 30000 });
console.log(data);

Setting proxy: false stops axios from also reading proxy environment variables.

got

js
import got from "got";
import { HttpsProxyAgent } from "https-proxy-agent";

const agent = { https: new HttpsProxyAgent(`http://${user}:${pw}@${ip}:${port}`) };
const body = await got("https://httpbin.org/ip", { agent, timeout: { request: 30000 } }).json();

Rotating through a direct list

js
import fs from "node:fs";
import { ProxyAgent, fetch } from "undici";

const agents = fs.readFileSync("webshare_proxies.txt", "utf8").trim().split("\n").map((l) => {
  const [ip, port, u, p] = l.split(":");
  return new ProxyAgent(`http://${u}:${p}@${ip}:${port}`);
});
let i = 0;
const next = () => agents[i++ % agents.length];

for (const url of urls) {
  const res = await fetch(url, { dispatcher: next() });
  console.log(url, res.status);
}

Refresh the list from the Webshare API periodically so replaced proxies are picked up.

Sticky sessions

Give each logical session its own agent with a session username, and keep cookies with it:

js
const sid = Math.floor(Math.random() * 1e6);
const sticky = new ProxyAgent(`http://${user}-${sid}:${pw}@p.webshare.io:80`);

See Webshare sticky sessions.

Budget tip: You can test most of this guide for free: Webshare gives every new account 10 datacenter proxies and 1 GB of bandwidth a month without a credit card. Move to a paid plan once the pilot works. See our complete Webshare guide.

SOCKS5

js
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent(`socks5h://${user}:${pw}@${ip}:${port}`);

Use socks5h so DNS resolves through the proxy.

Concurrency

Use a limiter so you stay under your plan's thread count:

js
import pLimit from "p-limit";
const limit = pLimit(40);
const results = await Promise.all(urls.map((u) => limit(() => fetch(u, { dispatcher }))));

See Webshare bandwidth and threads.

Error handling

  • 407: credentials or mode mismatch. Test with cURL first.
  • ECONNRESET or timeouts at high load: often the thread limit. Lower concurrency.
  • 403 or 429 from the target: a block or rate limit. Slow down, rotate, or move the target to residential.

More in fixing common Webshare errors.

A small production-ready wrapper

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

const agents = new Map();
function agentFor(session) {
  const user = `${process.env.WS_USER}-${session ?? "rotate"}`;
  const key = user;
  if (!agents.has(key)) agents.set(key, new ProxyAgent(`http://${user}:${process.env.WS_PASS}@p.webshare.io:80`));
  return agents.get(key);
}

export async function get(url, { session, tries = 3 } = {}) {
  for (let i = 0; i < tries; i++) {
    try {
      const res = await fetch(url, { dispatcher: agentFor(session), signal: AbortSignal.timeout(30000) });
      if ([403, 429, 503].includes(res.status)) throw new Error(`blocked ${res.status}`);
      return res;
    } catch (e) {
      await new Promise((r) => setTimeout(r, 1000 * 2 ** i));
    }
  }
  throw new Error(`failed ${url}`);
}

Agents are cached per session, so sticky flows reuse one agent while rotating calls share the rotate agent.

Keep-alive and rotation

undici keeps connections alive by default, which is good for speed but means a rotating gateway may keep the same exit IP for several requests. When you need a guaranteed new IP each time, create a short-lived agent per request and close it afterwards, or use a direct list and pick a different proxy per request.

Proxy tip: If your residential usage goes up and down, compare Geonode: its per-GB residential bandwidth doesn't expire, so you only pay for what you use. See using Geonode with Node.js.

Memory and agent hygiene

Creating thousands of agents without closing them leaks sockets. Cache agents by key, close unused ones (await agent.close()), and cap the cache size in long-running services.

Choosing products from Node.js services

Backend services that call partner APIs often need a fixed IP the partner can whitelist; a dedicated datacenter or static residential IP is ideal. Scrapers use datacenter lists for lenient targets and rotating residential for protected ones.

A real-world example

A Node.js backend service checks product availability on partner sites for an e-commerce app. Partners whitelist the service's IP, so the team buys two dedicated datacenter proxies from Webshare and sends partner API calls through them with an undici ProxyAgent, giving partners a stable IP even as the service's own servers scale up and down. Separately, a scraping worker uses the backbone gateway with the rotate option for public product pages. Each use case gets its own agent and credentials.

If you're still shortlisting, compare this setup with the options in our best proxies guide, and use our cheap proxies guide to estimate what a sensible budget looks like.

Key takeaways

  • Node.js needs an agent or dispatcher for proxies: undici ProxyAgent, https-proxy-agent or socks-proxy-agent.
  • Reuse agents, and close ones you no longer need to avoid socket leaks.
  • Keep-alive can keep the same exit IP on a rotating gateway; create new agents when you need a fresh IP.
  • Cap concurrency with a limiter below your plan's thread limit.
  • Dedicated proxies give partner APIs a stable IP to whitelist.

FAQ

Does Node's built-in fetch support proxies?

Through undici's ProxyAgent, passed as the dispatcher option.

Which agent library should I use?

undici for fetch, https-proxy-agent for axios and got, and socks-proxy-agent for SOCKS5.

Can I use Webshare with Puppeteer from Node.js?

Yes; see Webshare with Puppeteer.

Why use a proxy for partner API calls?

A dedicated proxy gives partners one stable IP to whitelist, even when your servers change.

Does axios support Webshare proxies?

Yes, through https-proxy-agent passed as httpsAgent, with axios's own proxy option set to false.

How do I avoid socket leaks with many proxy agents?

Cache agents by proxy URL, reuse them, and close agents you no longer need.

Affiliate disclosure: Team of Monkeys is an affiliate of Geonode and Webshare. Links and banners marked as sponsored, and links to Geonode and Webshare in the text, use our referral links, and we may earn a commission if you buy through them, at no extra cost to you. Our explanations and comparisons are written to be useful whichever provider you choose.

Editorial note: Proxy providers change their pools, features and prices often, so treat any figures here as typical ranges at the time of writing and confirm current terms with the provider before you buy.