# 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:

```js
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@residentialpremium.quantumproxies.io:8080");

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](https://quantumproxies.io/blog/python-requests-proxyerror-fix).

## 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.

![Tres fragmentos de código para la misma solicitud: axios recibe un HttpsProxyAgent en httpAgent y httpsAgent con proxy: false, fetch nativo recibe un dispatcher de undici en cada llamada, y setGlobalDispatcher de undici con un ProxyAgent pasa por proxy todo el proceso. Confundirlos es la causa principal de 'proxy not working'.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335145/blog/generated/qp-b9-007-diag1.png)
*Misma solicitud, tres sistemas de plomería. Axios quiere un agente, fetch nativo quiere un despachador de undici, y mezclarlos es la causa número uno de 'proxy no funciona'.*

## 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:

```js
import { ProxyAgent } from "undici";

const dispatcher = new ProxyAgent({
  uri: "http://residentialpremium.quantumproxies.io:8080",
  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](https://quantumproxies.io/socks5-proxies) expone la misma puerta de enlace sobre HTTP y SOCKS5, por lo que esto es un cambio de esquema, no una nueva compra:

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

const agent = new SocksProxyAgent("socks5h://USER:PASS@residentialpremium.quantumproxies.io:1080");

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](https://quantumproxies.io/rotating-proxies) 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:

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

const agent = new HttpsProxyAgent("http://USER:PASS@residentialpremium.quantumproxies.io:8080");
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](https://quantumproxies.io/blog/large-scale-web-scraping-architecture) 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:

```js
import fs from "node:fs";

const r = await client.get("https://example.com/large.json", {
  responseType: "stream",
});
r.data.pipe(fs.createWriteStream("out.json"));
```

![Una página httpbin.org/ip muestra cuatro errores de proxy en Node.js: la configuración proxy de axios que devuelve tu IP real o se queda colgada, una importación default del agente que lanza un error, socks5:// en axios que provoca un desajuste de protocolo y fetch ignorando HTTP_PROXY. La tarjeta da la solución de cada uno, y una nota advierte de no duplicar la configuración de agente y proxy.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335146/blog/generated/qp-b9-007-diag2.png)
*La mayoría de los fallos de proxy en Node.js se reducen a cinco errores: el error de HTTPS de axios, una importación de agente por defecto, configuración de proxy duplicada, esquema SOCKS incorrecto o esperar que fetch lea las variables de entorno.*

## 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](https://quantumproxies.io/residential-proxies)
