How to Use Proxies with Node.js Axios in 2026: Complete Guide

How to Use Proxies with Node.js Axios in 2026: Complete Guide

Axios is the most popular HTTP client for Node.js, used by millions of developers for API calls, web scraping, and server-to-server communication. While Axios has a built-in proxy option, the real world of proxy integration is more nuanced — especially when dealing with HTTPS, SOCKS5, authentication, and rotation.

This guide covers every proxy configuration method for Axios, from the basics to production-grade patterns with TypeScript, with working code you can use immediately.

Why Use Proxies with Axios?

When your Node.js application makes HTTP requests, the target server sees your server’s IP address. This creates problems at scale:

  • API rate limits — services throttle requests from a single IP
  • IP blocking — aggressive scraping leads to permanent bans
  • Geo-restrictions — content varies by geographic location
  • Competitive intelligence — you do not want targets to know your infrastructure IP

Proxies route requests through intermediate servers, masking your real IP and enabling rotation. Use our proxy cost calculator to estimate costs for your project.

Prerequisites

  • Node.js 18+ (LTS recommended)
  • npm or yarn
npm init -y
npm install axios

For HTTPS and SOCKS proxy support:

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

Basic Proxy Configuration

Axios Built-In Proxy Option

Axios has a native proxy configuration for HTTP proxies:

const axios = require('axios');

const response = await axios.get('http://httpbin.org/ip', {
  proxy: {
    host: 'proxy.example.com',
    port: 8080
  }
});

console.log(response.data);

Critical limitation: The built-in proxy option only works for HTTP requests, not HTTPS. For HTTPS targets (which is most of the web in 2026), you need an agent-based approach.

Authenticated HTTP Proxy

const axios = require('axios');

const response = await axios.get('http://httpbin.org/ip', {
  proxy: {
    host: 'proxy.example.com',
    port: 8080,
    auth: {
      username: 'your_username',
      password: 'your_password'
    }
  }
});

console.log(response.data);

HTTPS Proxies with Agent Libraries

For HTTPS requests through a proxy (the standard case), use proxy agent libraries:

Using https-proxy-agent

npm install https-proxy-agent
const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

const agent = new HttpsProxyAgent('http://username:password@proxy.example.com:8080');

const response = await axios.get('https://httpbin.org/ip', {
  httpsAgent: agent
});

console.log(response.data);
// { "origin": "proxy.ip.address" }

Using http-proxy-agent for HTTP Targets

npm install http-proxy-agent
const axios = require('axios');
const { HttpProxyAgent } = require('http-proxy-agent');

const agent = new HttpProxyAgent('http://username:password@proxy.example.com:8080');

const response = await axios.get('http://httpbin.org/ip', {
  httpAgent: agent
});

console.log(response.data);

Combined HTTP and HTTPS Agent Setup

const axios = require('axios');
const { HttpProxyAgent } = require('http-proxy-agent');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxyUrl = 'http://username:password@proxy.example.com:8080';

const client = axios.create({
  httpAgent: new HttpProxyAgent(proxyUrl),
  httpsAgent: new HttpsProxyAgent(proxyUrl)
});

// Works for both HTTP and HTTPS targets
const httpResponse = await client.get('http://httpbin.org/ip');
const httpsResponse = await client.get('https://httpbin.org/ip');

console.log('HTTP:', httpResponse.data);
console.log('HTTPS:', httpsResponse.data);

SOCKS Proxy Support

Using socks-proxy-agent

npm install socks-proxy-agent
const axios = require('axios');
const { SocksProxyAgent } = require('socks-proxy-agent');

// SOCKS5 proxy
const agent = new SocksProxyAgent('socks5://username:password@proxy.example.com:1080');

const response = await axios.get('https://httpbin.org/ip', {
  httpAgent: agent,
  httpsAgent: agent
});

console.log(response.data);

SOCKS5h (Remote DNS Resolution)

const agent = new SocksProxyAgent('socks5h://username:password@proxy.example.com:1080');

Using socks5h:// ensures DNS lookups happen on the proxy server, preventing DNS leaks.

Axios Interceptors for Proxy Rotation

Axios interceptors let you modify every request before it is sent. This is perfect for proxy rotation:

Basic Rotation Interceptor

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxies = [
  'http://user:pass@proxy1.example.com:8080',
  'http://user:pass@proxy2.example.com:8080',
  'http://user:pass@proxy3.example.com:8080',
  'http://user:pass@proxy4.example.com:8080',
  'http://user:pass@proxy5.example.com:8080',
];

let proxyIndex = 0;

const client = axios.create();

client.interceptors.request.use((config) => {
  const proxyUrl = proxies[proxyIndex % proxies.length];
  proxyIndex++;

  config.httpsAgent = new HttpsProxyAgent(proxyUrl);
  config.proxy = false; // Disable built-in proxy to use agent

  return config;
});

// Each request uses a different proxy
const results = await Promise.all([
  client.get('https://httpbin.org/ip'),
  client.get('https://httpbin.org/ip'),
  client.get('https://httpbin.org/ip'),
]);

results.forEach((r, i) => console.log(`Request ${i + 1}:`, r.data));

Random Rotation Interceptor

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxies = [
  'http://user:pass@proxy1.example.com:8080',
  'http://user:pass@proxy2.example.com:8080',
  'http://user:pass@proxy3.example.com:8080',
];

const client = axios.create();

client.interceptors.request.use((config) => {
  const randomProxy = proxies[Math.floor(Math.random() * proxies.length)];
  config.httpsAgent = new HttpsProxyAgent(randomProxy);
  config.proxy = false;
  return config;
});

Geo-Targeted Interceptor

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

const geoProxies = {
  us: 'http://user:pass@us-proxy.example.com:8080',
  uk: 'http://user:pass@uk-proxy.example.com:8080',
  de: 'http://user:pass@de-proxy.example.com:8080',
  jp: 'http://user:pass@jp-proxy.example.com:8080',
};

function createGeoClient(country) {
  const proxyUrl = geoProxies[country];
  if (!proxyUrl) throw new Error(`No proxy for country: ${country}`);

  return axios.create({
    httpsAgent: new HttpsProxyAgent(proxyUrl),
    proxy: false
  });
}

const usClient = createGeoClient('us');
const ukClient = createGeoClient('uk');

const [usResult, ukResult] = await Promise.all([
  usClient.get('https://httpbin.org/ip'),
  ukClient.get('https://httpbin.org/ip'),
]);

console.log('US IP:', usResult.data);
console.log('UK IP:', ukResult.data);

Error Handling and Retry with axios-retry

Install axios-retry

npm install axios-retry

Basic Retry Configuration

const axios = require('axios');
const axiosRetry = require('axios-retry').default;
const { HttpsProxyAgent } = require('https-proxy-agent');

const client = axios.create({
  httpsAgent: new HttpsProxyAgent('http://user:pass@proxy.example.com:8080'),
  proxy: false,
  timeout: 15000
});

axiosRetry(client, {
  retries: 3,
  retryDelay: axiosRetry.exponentialDelay,
  retryCondition: (error) => {
    // Retry on network errors and 5xx responses
    return axiosRetry.isNetworkOrIdempotentRequestError(error)
      || (error.response && error.response.status >= 500)
      || (error.response && error.response.status === 429);
  },
  onRetry: (retryCount, error) => {
    console.log(`Retry ${retryCount}: ${error.message}`);
  }
});

const response = await client.get('https://httpbin.org/ip');
console.log(response.data);

Retry with Proxy Rotation on Failure

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

const proxies = [
  'http://user:pass@proxy1.example.com:8080',
  'http://user:pass@proxy2.example.com:8080',
  'http://user:pass@proxy3.example.com:8080',
];

async function fetchWithRetry(url, maxRetries = 3) {
  const shuffled = [...proxies].sort(() => Math.random() - 0.5);

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const proxyUrl = shuffled[attempt % shuffled.length];

    try {
      const response = await axios.get(url, {
        httpsAgent: new HttpsProxyAgent(proxyUrl),
        proxy: false,
        timeout: 10000
      });

      if (response.status === 200) {
        return response.data;
      }
    } catch (error) {
      const msg = error.response
        ? `HTTP ${error.response.status}`
        : error.message;
      console.warn(`Attempt ${attempt + 1}/${maxRetries} [${proxyUrl}]: ${msg}`);
    }

    // Exponential backoff
    if (attempt < maxRetries - 1) {
      const delay = Math.min(1000 * Math.pow(2, attempt), 8000);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }

  throw new Error(`All ${maxRetries} attempts failed for ${url}`);
}

// Usage
const data = await fetchWithRetry('https://httpbin.org/ip');
console.log(data);

Proxy Pool Implementation

A production proxy pool tracks proxy health and routes requests to healthy proxies:

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

class ProxyPool {
  constructor(proxyUrls) {
    this.proxies = proxyUrls.map(url => ({
      url,
      failures: 0,
      lastUsed: 0,
      totalRequests: 0,
      successRate: 1.0
    }));
    this.maxFailures = 5;
    this.cooldownMs = 30000;
  }

  getProxy() {
    const now = Date.now();
    const available = this.proxies.filter(
      p => p.failures < this.maxFailures && (now - p.lastUsed > 500)
    );

    if (available.length === 0) {
      // Reset all proxies and try again
      this.proxies.forEach(p => { p.failures = 0; });
      return this.proxies[0];
    }

    // Prefer proxies with better success rates
    available.sort((a, b) => b.successRate - a.successRate);
    const proxy = available[0];
    proxy.lastUsed = now;
    proxy.totalRequests++;
    return proxy;
  }

  reportSuccess(proxy) {
    proxy.failures = Math.max(0, proxy.failures - 1);
    proxy.successRate = proxy.successRate * 0.9 + 0.1;
  }

  reportFailure(proxy) {
    proxy.failures++;
    proxy.successRate = proxy.successRate * 0.9;
  }

  getStats() {
    return this.proxies.map(p => ({
      url: p.url.replace(/\/\/.*@/, '//***@'), // Hide credentials
      failures: p.failures,
      requests: p.totalRequests,
      successRate: (p.successRate * 100).toFixed(1) + '%'
    }));
  }
}

// Usage
const pool = new ProxyPool([
  'http://user:pass@proxy1.example.com:8080',
  'http://user:pass@proxy2.example.com:8080',
  'http://user:pass@proxy3.example.com:8080',
  'http://user:pass@proxy4.example.com:8080',
  'http://user:pass@proxy5.example.com:8080',
]);

async function fetchUrl(url) {
  const proxyInfo = pool.getProxy();

  try {
    const response = await axios.get(url, {
      httpsAgent: new HttpsProxyAgent(proxyInfo.url),
      proxy: false,
      timeout: 10000
    });

    pool.reportSuccess(proxyInfo);
    return response.data;
  } catch (error) {
    pool.reportFailure(proxyInfo);
    throw error;
  }
}

// Scrape multiple URLs
const urls = Array.from({ length: 20 }, (_, i) => `https://httpbin.org/anything/${i}`);

const results = [];
for (const url of urls) {
  try {
    const data = await fetchUrl(url);
    results.push({ url, status: 'success' });
  } catch (err) {
    results.push({ url, status: 'failed', error: err.message });
  }
}

console.log(`Success: ${results.filter(r => r.status === 'success').length}/${results.length}`);
console.log('Pool stats:', pool.getStats());

Concurrent Requests with Proxy Rotation

const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');

async function scrapeWithConcurrency(urls, proxies, concurrency = 5) {
  const results = new Array(urls.length);
  let index = 0;

  async function worker() {
    while (index < urls.length) {
      const currentIndex = index++;
      const url = urls[currentIndex];
      const proxyUrl = proxies[currentIndex % proxies.length];

      try {
        const response = await axios.get(url, {
          httpsAgent: new HttpsProxyAgent(proxyUrl),
          proxy: false,
          timeout: 10000
        });
        results[currentIndex] = { url, status: response.status, data: response.data };
      } catch (err) {
        results[currentIndex] = { url, error: err.message };
      }
    }
  }

  const workers = Array.from({ length: concurrency }, () => worker());
  await Promise.all(workers);

  return results;
}

// Usage
const urls = Array.from({ length: 50 }, (_, i) => `https://httpbin.org/anything/${i}`);
const proxies = [
  'http://user:pass@proxy1.example.com:8080',
  'http://user:pass@proxy2.example.com:8080',
  'http://user:pass@proxy3.example.com:8080',
];

const results = await scrapeWithConcurrency(urls, proxies, 5);
const successful = results.filter(r => !r.error).length;
console.log(`Completed: ${successful}/${results.length} successful`);

TypeScript Examples

Type-Safe Proxy Configuration

import axios, { AxiosInstance, AxiosRequestConfig, InternalAxiosRequestConfig } from 'axios';
import { HttpsProxyAgent } from 'https-proxy-agent';

interface ProxyConfig {
  host: string;
  port: number;
  username: string;
  password: string;
  protocol: 'http' | 'https' | 'socks5';
}

interface ProxyPoolConfig {
  proxies: ProxyConfig[];
  maxFailures: number;
  rotationStrategy: 'round-robin' | 'random' | 'least-used';
}

function proxyConfigToUrl(config: ProxyConfig): string {
  return `${config.protocol}://${config.username}:${config.password}@${config.host}:${config.port}`;
}

function createProxiedClient(proxyConfig: ProxyConfig): AxiosInstance {
  const proxyUrl = proxyConfigToUrl(proxyConfig);

  return axios.create({
    httpsAgent: new HttpsProxyAgent(proxyUrl),
    proxy: false,
    timeout: 15000,
    headers: {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/124.0.0.0',
    },
  });
}

// Usage
const proxy: ProxyConfig = {
  host: 'proxy.example.com',
  port: 8080,
  username: 'user',
  password: 'pass',
  protocol: 'http',
};

const client = createProxiedClient(proxy);

const response = await client.get<{ origin: string }>('https://httpbin.org/ip');
console.log('IP:', response.data.origin);

TypeScript Proxy Rotation Class

import axios, { AxiosInstance, AxiosResponse } from 'axios';
import { HttpsProxyAgent } from 'https-proxy-agent';

interface ProxyState {
  url: string;
  failures: number;
  lastUsed: number;
  requestCount: number;
}

class TypedProxyRotator {
  private proxies: ProxyState[];
  private index: number = 0;

  constructor(proxyUrls: string[]) {
    this.proxies = proxyUrls.map(url => ({
      url,
      failures: 0,
      lastUsed: 0,
      requestCount: 0,
    }));
  }

  private getNextProxy(): ProxyState {
    const proxy = this.proxies[this.index % this.proxies.length];
    this.index++;
    proxy.lastUsed = Date.now();
    proxy.requestCount++;
    return proxy;
  }

  async fetch<T = unknown>(url: string): Promise<T> {
    const maxAttempts = Math.min(3, this.proxies.length);

    for (let attempt = 0; attempt < maxAttempts; attempt++) {
      const proxy = this.getNextProxy();

      try {
        const response: AxiosResponse<T> = await axios.get(url, {
          httpsAgent: new HttpsProxyAgent(proxy.url),
          proxy: false,
          timeout: 10000,
        });

        proxy.failures = 0;
        return response.data;
      } catch (error) {
        proxy.failures++;
        console.warn(
          `Attempt ${attempt + 1}/${maxAttempts} failed via ${proxy.url}: ${
            error instanceof Error ? error.message : 'Unknown error'
          }`
        );
      }
    }

    throw new Error(`All ${maxAttempts} proxy attempts failed for ${url}`);
  }
}

// Usage
const rotator = new TypedProxyRotator([
  'http://user:pass@proxy1.example.com:8080',
  'http://user:pass@proxy2.example.com:8080',
  'http://user:pass@proxy3.example.com:8080',
]);

interface IpResponse {
  origin: string;
}

const data = await rotator.fetch<IpResponse>('https://httpbin.org/ip');
console.log('IP:', data.origin);

Environment Variable Proxy Configuration

Axios respects the standard HTTP_PROXY and HTTPS_PROXY environment variables when the built-in proxy option is not set:

export HTTP_PROXY="http://user:pass@proxy.example.com:8080"
export HTTPS_PROXY="http://user:pass@proxy.example.com:8080"
export NO_PROXY="localhost,127.0.0.1"
const axios = require('axios');

// Axios reads environment variables automatically
const response = await axios.get('https://httpbin.org/ip');
console.log(response.data);

Note: If you set proxy: false in Axios config, environment variables are ignored. Remove the proxy key entirely to use env vars.

Troubleshooting Common Issues

Axios Proxy Option Does Not Work for HTTPS

Cause: The built-in proxy config only works for HTTP requests.

Fix: Use https-proxy-agent:

const { HttpsProxyAgent } = require('https-proxy-agent');

const response = await axios.get('https://example.com', {
  httpsAgent: new HttpsProxyAgent('http://user:pass@proxy:8080'),
  proxy: false  // Disable built-in proxy
});

Error: ECONNREFUSED or ECONNRESET

Cause: The proxy server refused the connection or reset it.

Fix:

  1. Verify the proxy is online
  2. Check that your IP is whitelisted with the proxy provider
  3. Reduce concurrent requests (you may be exceeding connection limits)

Error: SELF_SIGNED_CERT_IN_CHAIN

Cause: The proxy uses a self-signed certificate or does SSL interception.

Fix:

const agent = new HttpsProxyAgent('http://proxy:8080', {
  rejectUnauthorized: false  // Development only!
});

For production, add the CA certificate:

const fs = require('fs');
const agent = new HttpsProxyAgent('http://proxy:8080', {
  ca: fs.readFileSync('/path/to/ca-cert.pem')
});

Request Hangs Indefinitely

Cause: No timeout configured and the proxy connection stalls.

Fix: Always set a timeout:

const response = await axios.get(url, {
  httpsAgent: agent,
  proxy: false,
  timeout: 15000  // 15 seconds
});

Memory Leak with Many Proxy Agents

Cause: Creating a new HttpsProxyAgent for every request without reusing them.

Fix: Cache agents per proxy URL:

const agentCache = new Map();

function getAgent(proxyUrl) {
  if (!agentCache.has(proxyUrl)) {
    agentCache.set(proxyUrl, new HttpsProxyAgent(proxyUrl));
  }
  return agentCache.get(proxyUrl);
}

Proxy Works in cURL but Not Axios

Cause: Axios may be reading conflicting environment variables or the agent setup is wrong.

Fix:

  1. Check process.env.HTTP_PROXY and process.env.HTTPS_PROXY
  2. Explicitly set proxy: false when using an agent
  3. Use verbose logging: axios.interceptors.request.use(config => { console.log(config); return config; })

Summary

Axios proxy integration requires understanding the distinction between its built-in proxy option (HTTP only) and agent-based proxying (HTTPS and SOCKS5). Key points:

MethodUse Case
Built-in proxy configHTTP targets only
https-proxy-agentHTTPS targets through HTTP proxy
socks-proxy-agentSOCKS4/SOCKS5 proxies
Axios interceptorsProxy rotation per request
axios-retryAutomatic retry with backoff
Agent cachingPerformance optimization

For production scraping and data collection, combine proxy pools, health tracking, retry logic, and concurrency control. Estimate your bandwidth needs with the proxy cost calculator and test your request fingerprint with the browser fingerprint tester.


Related Reading

Scroll to Top