JavaScript sits at the heart of modern web automation, browser testing, and API clients. On the server side, Node.js powers scrapers, monitoring tools, and microservices. On the client side, frameworks like Puppeteer and Playwright drive full browser automation.
Adding proxies to this stack lets you:
This guide walks through how to integrate proxies into JavaScript and Node.js using Axios, Fetch, Got, Puppeteer, and Playwright. It covers configuration, authentication, rotation strategies, testing, troubleshooting, and best practices for production workloads.
At a high level, a proxy is a server that forwards your HTTP(S) requests. Instead of your app talking directly to a target site, it sends the request to the proxy, which then forwards it onward. The target sees the proxy IP, not your machine or server.
In JavaScript/Node.js environments, you’ll typically encounter:
Your code usually cares about three things:
Proxy URL format
http://user:pass@host:port https://user:pass@host:port socks5://user:pass@host:portWhere to plug this URL into your HTTP client or browser launcher
How to handle timeouts, retries, and errors when a proxy is slow or blocked
Regardless of provider, you will usually receive:
proxy.example.com or an IP like 198.51.100.10 8000, 8080, 3128 Store these values in environment variables so you don’t hard-code credentials:
export PROXY_HOST="proxy.example.com"
export PROXY_PORT="8000"
export PROXY_USER="myuser"
export PROXY_PASS="mypassword"
Then load them inside Node.js using process.env.
Axios is one of the most common HTTP clients for Node.js, used in scrapers, backend services, and CLI tools.
const axios = require('axios');
const proxyConfig = {
host: process.env.PROXY_HOST,
port: parseInt(process.env.PROXY_PORT, 10),
auth: {
username: process.env.PROXY_USER,
password: process.env.PROXY_PASS
}
};
async function fetchIp() {
try {
const res = await axios.get('https://httpbin.org/ip', { proxy: proxyConfig, timeout: 10000 });
console.log(res.data);
} catch (err) {
console.error('Request failed:', err.message);
}
}
fetchIp();
If your proxy uses IP allowlisting (no username/password), simply omit the auth block.
Axios’ built-in proxy option works for HTTP/HTTPS in many cases, but for more advanced setups (or when you need SOCKS) it’s better to use agents.
Install the agent libraries:
npm install https-proxy-agent socks-proxy-agent
Example using https-proxy-agent:
const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');
const proxyUrl = `http://${process.env.PROXY_USER}:${process.env.PROXY_PASS}` +
`@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
const agent = new HttpsProxyAgent(proxyUrl);
async function fetchIp() {
try {
const res = await axios.get('https://httpbin.org/ip', {
httpsAgent: agent,
proxy: false, // Disable Axios' built-in proxy handling
timeout: 10000
});
console.log(res.data);
} catch (err) {
console.error('Request failed:', err.message);
}
}
fetchIp();
For SOCKS5, use socks-proxy-agent in a similar way.
Modern Node.js versions (18+) ship with a built-in Fetch API. To add proxy support, you typically combine Fetch with an agent.
Install https-proxy-agent:
npm install https-proxy-agent
Example:
import fetch from 'node-fetch';
import HttpsProxyAgent from 'https-proxy-agent';
const proxyAgent = new HttpsProxyAgent('http://user:pass@proxyserver:8080');
const response = await fetch('https://httpbin.org/ip', { agent: proxyAgent });
console.log(await response.text());
This pattern works well for lightweight automation and simple API clients.
Got is a modern, promise-based HTTP client with good streaming support.
Install Got and a proxy agent:
npm install got https-proxy-agent
Usage:
import got from 'got';
import HttpsProxyAgent from 'https-proxy-agent';
const proxyUrl = `http://${process.env.PROXY_USER}:${process.env.PROXY_PASS}` +
`@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
const agent = {
https: new HttpsProxyAgent(proxyUrl),
http: new HttpsProxyAgent(proxyUrl)
};
async function fetchIp() {
try {
const body = await got('https://httpbin.org/ip', { agent, timeout: { request: 10000 } }).text();
console.log(body);
} catch (err) {
console.error('Got request failed:', err.message);
}
}
fetchIp();
Got is especially useful when you need features like streaming, hooks, or advanced retry logic.
Puppeteer lets you control Chromium/Chrome from Node.js. Proxies allow you to simulate users from different regions, test localized content, or spread traffic over multiple IPs.
Install Puppeteer:
npm install puppeteer
import puppeteer from 'puppeteer';
async function run() {
const proxyServer = `http://${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
const browser = await puppeteer.launch({
headless: true,
args: [`--proxy-server=${proxyServer}`]
});
const page = await browser.newPage();
// If your proxy requires authentication:
if (process.env.PROXY_USER && process.env.PROXY_PASS) {
await page.authenticate({
username: process.env.PROXY_USER,
password: process.env.PROXY_PASS
});
}
await page.goto('https://httpbin.org/ip', { waitUntil: 'networkidle2' });
const content = await page.content();
console.log(content);
await browser.close();
}
run().catch(console.error);
Tips for Puppeteer with proxies:
Playwright supports Chromium, Firefox, and WebKit and has built-in proxy configuration.
Install Playwright:
npm install playwright
Example with a single proxy:
import { chromium } from 'playwright';
async function run() {
const proxyServer = `http://${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
const proxyAuth = process.env.PROXY_USER && process.env.PROXY_PASS
? `${process.env.PROXY_USER}:${process.env.PROXY_PASS}`
: null;
const browser = await chromium.launch({
headless: true,
proxy: {
server: proxyServer,
username: proxyAuth ? process.env.PROXY_USER : undefined,
password: proxyAuth ? process.env.PROXY_PASS : undefined
}
});
const page = await browser.newPage();
await page.goto('https://httpbin.org/ip', { waitUntil: 'networkidle' });
const body = await page.textContent('body');
console.log(body);
await browser.close();
}
run().catch(console.error);
Playwright is especially useful when you need multi-browser coverage or deeper control over network and page events.
To avoid overusing a single IP, you can rotate through a list of proxies or use a rotating gateway from your provider.
const axios = require('axios');
const proxies = [
'http://user1:pass1@proxy1:8080',
'http://user2:pass2@proxy2:8080',
'http://user3:pass3@proxy3:8080'
];
function parseProxy(url) {
const [protocol, rest] = url.split('://');
const [auth, hostPort] = rest.split('@');
const [username, password] = auth.split(':');
const [host, port] = hostPort.split(':');
return { protocol, host, port: parseInt(port, 10), username, password };
}
async function fetchWithRandomProxy() {
const proxyUrl = proxies[Math.floor(Math.random() * proxies.length)];
const cfg = parseProxy(proxyUrl);
try {
const res = await axios.get('https://httpbin.org/ip', {
proxy: {
host: cfg.host,
port: cfg.port,
auth: {
username: cfg.username,
password: cfg.password
}
},
timeout: 10000
});
console.log(proxyUrl, '=>', res.data);
} catch (err) {
console.error('Proxy failed:', proxyUrl, '-', err.message);
}
}
(async () => {
for (let i = 0; i < 5; i += 1) {
await fetchWithRandomProxy();
}
})();
For serious workloads:
If your provider offers a rotating endpoint, you can often just use one proxy URL and let them handle the rotation behind the scenes.
Before scaling up, always validate the basics.
curl -x http://user:pass@proxy.example.com:8000 https://httpbin.org/ip
If the response shows a different IP than your machine, the proxy is working.
const axios = require('axios');
async function testProxy() {
try {
const res = await axios.get('https://httpbin.org/ip', {
proxy: {
host: process.env.PROXY_HOST,
port: parseInt(process.env.PROXY_PORT, 10),
auth: {
username: process.env.PROXY_USER,
password: process.env.PROXY_PASS
}
},
timeout: 10000
});
console.log(res.data);
} catch (err) {
console.error('Proxy test failed:', err.message);
}
}
testProxy();
Once basic connectivity works, test:
| Error / Symptom | Likely Cause | Fix |
|---|---|---|
ECONNREFUSED |
Wrong host/port or proxy offline | Double-check proxy endpoint, try another IP |
ETIMEDOUT |
Slow proxy or network congestion | Increase timeout, reduce concurrency, change proxy |
407 Proxy Authentication Required |
Bad or missing credentials | Verify username/password or switch to IP allowlisting |
ENOTFOUND proxy.example.com |
DNS resolution failure | Use a valid hostname or direct IP |
Many 403/429 responses from target |
IP flagged or too many rapid requests | Rotate IPs, slow down, add jitter and backoff |
| Pages load without proxy IP in test APIs | Misconfigured agent or bypassed proxy | Ensure all requests use the configured agent or proxy options |
When you need a clean, stable IP pool for Node.js and browser automation stacks, dedicated datacenter proxies are often the best starting point. Developer-friendly proxy providers make it easier to plug a single endpoint into Axios, Fetch, Puppeteer, or Playwright and scale up over time.

Rowan is a digital privacy advocate and web automation expert. With a background in software development and network analysis, Rowan helps users understand how proxies and anonymity tools can improve both security and efficiency online.