Configuración de Proxy en Node.js: Axios, Fetch, Undici y Rotación
La opción de proxy de axios es una trampa para objetivos HTTPS, y el fetch nativo ignora por completo tus variables de entorno de proxy. Aquí está la configuración que funciona en axios, fetch y undici: agentes, autenticación, SOCKS5, rotación y transmisión.
Rutar solicitudes de Node.js a través de un proxy parece una línea de código y se convierte en una tarde de depuración. La razón es que los tres clientes HTTP que la mayoría de los proyectos usan — axios, el fetch nativo que se incluyó como global en Node 18, y la biblioteca subyacente undici — cada uno toma un proxy de manera diferente, y ninguno se comporta como esperas. Axios tiene una configuración de proxy incorporada que está documentada, es solo para Node, y está silenciosamente rota para objetivos HTTPS detrás de un proxy HTTP: un error que ha estado abierto en el rastreador de GitHub de axios desde 2020 y que impulsó un hilo muy votado en Stack Overflow. Mientras tanto, fetch nativo ignora las variables de entorno HTTP_PROXY y no tiene ninguna opción de proxy. Esta guía te ofrece la configuración que realmente funciona en cada cliente, además de autenticación, SOCKS5, rotación y transmisión.
Configuración de proxy de Axios vs agentes de proxy
Axios viene con un objeto proxy — { host, port, auth } — y funciona bien para objetivos HTTP simples. La trampa es HTTPS: cuando el objetivo es https:// y el proxy habla HTTP, axios no logra abrir el túnel CONNECT y tu solicitud se cuelga o regresa con tu IP real. La solución que la comunidad acordó es omitir por completo la configuración incorporada y darle a axios un agente de proxy en su lugar, luego establecer proxy: false para que los dos mecanismos no entren en conflicto:
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
// Note the destructured import — a default import is the classic gotcha.
const agent = new HttpsProxyAgent("http://USER:PASS@gate.quantumproxies.io:PORT");
const client = axios.create({
httpAgent: agent, // for http:// targets
httpsAgent: agent, // for https:// targets
proxy: false, // disable axios' own broken proxy handling
timeout: 15000,
});
const r = await client.get("https://httpbin.org/ip");
console.log(r.data); // { origin: "<proxy exit IP>" }
Dos detalles ahorran horas. Primero, usa la importación desestructurada { HttpsProxyAgent } — las versiones recientes lo exportan como un símbolo nombrado, y una importación por defecto te da un objeto que lanza un error al ser construido. Segundo, el esquema de URL del proxy permanece http:// incluso cuando el proxy maneja tráfico HTTPS: el esquema describe cómo llegas al proxy, y el TLS al objetivo se ejecuta dentro del túnel. La misma clase de fallo aparece en Python; si también trabajas en requests, los patrones riman con nuestra guía de solución de ProxyError y SSLError.
Autenticación y variables de entorno
Los proxies autenticados usan credenciales HTTP Basic. Con un agente, incrústalas en la URL como http://user:pass@host:port; si la contraseña contiene @, : o /, codifícala en URL con encodeURIComponent() primero o la URL se dividirá en el lugar incorrecto. Un 407 Proxy Authentication Required significa que las credenciales fueron rechazadas o que tu IP de origen no está en la lista blanca. Axios también lee HTTP_PROXY, HTTPS_PROXY y NO_PROXY del entorno — útil para hacer proxy a una biblioteca de terceros sin tocar su código — y desactivas eso estableciendo proxy: false. La advertencia importante: el fetch nativo no lee estas variables, por lo que un scraper que depende del proxy de variables de entorno va directamente en el momento en que cambias de axios a fetch.

Hacer proxy a fetch nativo con undici
El fetch global de Node está construido sobre undici, y undici es donde vive el proxy. Creas un ProxyAgent y lo pasas como la opción no estándar dispatcher — esta es la forma moderna y ligera en dependencias de hacer proxy a fetch, y maneja correctamente el HTTPS CONNECT desde el principio:
import { ProxyAgent } from "undici";
const dispatcher = new ProxyAgent({
uri: "http://gate.quantumproxies.io:PORT",
token: "Basic " + Buffer.from("USER:PASS").toString("base64"),
});
const res = await fetch("https://httpbin.org/ip", { dispatcher });
console.log(await res.json());
Si estás en undici directamente en lugar de fetch global, el mismo ProxyAgent se conecta a request() o a setGlobalDispatcher() para hacer proxy a cada fetch en el proceso a la vez. Ese cambio global de una sola llamada es la forma más limpia de enrutar toda una base de código a través de un proxy sin pasar un despachador por cada función.
Proxies SOCKS5 en Node.js
Ni axios ni undici hablan SOCKS de forma nativa — pasa una cadena socks5:// a la configuración de proxy de axios y obtendrás una afirmación de protocol mismatch. Instala socks-proxy-agent y úsalo de la misma manera que el agente HTTPS, conectado tanto a httpAgent como a httpsAgent. Prefiere socks5h:// sobre socks5://: la h final resuelve DNS en el lado del proxy, lo que detiene las fugas de DNS y resuelve nombres de host geolocalizados desde la ubicación de salida. Cada plan de proxy SOCKS5 expone la misma puerta de enlace sobre HTTP y SOCKS5, por lo que esto es un cambio de esquema, no una nueva compra:
import axios from "axios";
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent("socks5h://USER:PASS@gate.quantumproxies.io:PORT");
const client = axios.create({ httpAgent: agent, httpsAgent: agent });
const r = await client.get("https://httpbin.org/ip");
console.log(r.data);
Rotación sin una lista de proxies
La receta antigua — un arreglo de IPs, Math.random() por solicitud, eliminar las muertas — es código que ya no mantienes. Una puerta de enlace rotativa asigna una IP de salida fresca del lado del servidor en cada solicitud, por lo que un punto final se comporta como un grupo completo. A través de proxies residenciales rotativos ese grupo abarca más de 90 millones de IPs en más de 200 países, y el bucle a continuación imprime un origen diferente en cada iteración sin lógica de rotación:
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
const agent = new HttpsProxyAgent("http://USER:PASS@gate.quantumproxies.io:PORT");
const client = axios.create({ httpAgent: agent, httpsAgent: agent, proxy: false });
for (let i = 0; i < 3; i++) {
const r = await client.get("https://httpbin.org/ip");
console.log(r.data.origin); // a different exit IP each time
}
Cuando un flujo abarca varias solicitudes — inicio de sesión, agregar al carrito, pagar — la rotación por solicitud rompe la sesión. Un parámetro de sesión persistente en el nombre de usuario del proxy fija una IP de salida durante una ventana establecida, luego rota; mismo punto final, un cambio de cadena. Si estás escalando esto a miles de solicitudes concurrentes, mueve el trabajo fuera de los bucles de axios y lee nuestra guía sobre arquitectura de scraping a gran escala para presupuestos de cola y concurrencia.
Transmitiendo respuestas a través de un proxy
Descargar archivos o grandes cargas útiles JSON funciona igual que cualquier solicitud una vez que el agente está adjunto — establece responseType: "stream" y canaliza el cuerpo al disco. El proxy maneja la transferencia de manera transparente, por lo que una exportación de 200MB nunca se almacena en memoria:
import fs from "node:fs";
const r = await client.get("https://example.com/large.json", {
responseType: "stream",
});
r.data.pipe(fs.createWriteStream("out.json"));

Preguntas frecuentes
¿Por qué mi proxy de axios no funciona?
La causa más común es un objetivo HTTPS detrás de un proxy HTTP: la configuración de proxy incorporada de axios no logra abrir el túnel CONNECT y devuelve tu IP real o se cuelga. Cambia a un agente de proxy — adjunta HttpsProxyAgent a httpAgent y httpsAgent, y establece proxy: false para que axios deje de intentar manejar el proxy por sí mismo.
¿Axios soporta proxies SOCKS5?
No de forma nativa — pasar una URL socks5:// a la configuración de proxy lanza un error de incompatibilidad de protocolo. Instala socks-proxy-agent, construye un SocksProxyAgent, y conéctalo tanto a httpAgent como a httpsAgent. Usa el esquema socks5h:// para que el DNS se resuelva en el lado del proxy en lugar de filtrarse desde tu máquina.
¿Cómo uso un proxy con fetch nativo en Node.js?
Fetch nativo no tiene opción de proxy y ignora las variables de entorno HTTP_PROXY. Crea un ProxyAgent de undici y pásalo como la opción dispatcher en la llamada de fetch, o llama a setGlobalDispatcher() una vez para hacer proxy a cada fetch en el proceso. Undici maneja correctamente el HTTPS CONNECT sin configuración adicional.
¿Cómo configuro un proxy de axios con variables de entorno?
Exporta HTTP_PROXY, HTTPS_PROXY y opcionalmente NO_PROXY con URLs completas de proxy; axios las lee automáticamente. Establece proxy: false en una solicitud o instancia para que axios ignore el entorno. Recuerda que esto solo afecta a axios — undici y fetch nativo no captarán esas variables.
Toda la historia cabe en una tarjeta: axios necesita un agente y proxy: false, fetch nativo necesita un despachador de undici, SOCKS necesita su propio agente, y la rotación pertenece a la puerta de enlace en lugar de en tu bucle. Configura bien la plomería y la última variable es la calidad de IP — una salida residencial limpia pasa donde una IP de centro de datos marcada recibe un 403 en el mismo código.
Obtén proxies residenciales que pasen en la primera solicitud