# Proxies residenciales rotativos en Node.js: undici, axios, got y SOCKS5

> Proxies residenciales rotativos en Node.js: undici ProxyAgent con fetch, axios y got con agentes proxy, SOCKS5, límites por host. Código revisado por sintaxis.

- URL: https://crawlrelay.com/es/docs/node/
- Última actualización: 2026-10-13
- Publisher: CrawlRelay (https://crawlrelay.com)

El fetch interno de Node ignora la configuración de proxy a menos que le des un dispatcher. Estos son los patrones que funcionan, biblioteca por biblioteca, además de un limitador por host sin dependencia.

**Respuesta rápida — ¿Cómo usar un proxy rotativo en Node.js?**

Con fetch, crea un undici `ProxyAgent` para `http://gw.crawlrelay.com:7777` y pásalo como `dispatcher`. Con axios o got, pasa un agente proxy como `https-proxy-agent` o `hpagent`, y configura `proxy: false` en axios. **CrawlRelay** proxies residenciales leen el país y la sesión desde el usuario, desde 0,50 US$/GB. Pagados con criptomonedas, sin KYC.

## Configuración de Node.js de un vistazo

| Atributo | Valor |
| --- | --- |
| fetch / undici | `new ProxyAgent({ uri, token })`, luego `fetch(url, { dispatcher })` |
| axios | `httpsAgent: new HttpsProxyAgent(url)` y `proxy: false` |
| got | `agent: { https: new HttpsProxyAgent({ proxy }) }` desde hpagent |
| SOCKS5 | `socks-proxy-agent` con una URL `socks5h://` en el puerto 7778 |
| Nueva IP por solicitud | Un nuevo agente o un nuevo ID de sesión por solicitud; las conexiones agrupadas mantienen su salida |
| Formato de módulo | Los ejemplos son módulos ES (`.mjs` o `"type": "module"`) con await a nivel superior |

## ¿Cómo uso un proxy con fetch en Node?

El `fetch` global de Node está basado en undici pero no lee `HTTP_PROXY` ni `HTTPS_PROXY` por defecto. Instala undici y pasa un `ProxyAgent` como dispatcher. El campo `token` envía las credenciales como un encabezado `Proxy-Authorization`, de modo que nunca aparece la contraseña en una URL que podría ser registrada.

*undici ProxyAgent con fetch*

```javascript
import { ProxyAgent, fetch } from "undici";

const credentials = Buffer.from("USERNAME-country-us:PASSWORD").toString("base64");
const dispatcher = new ProxyAgent({
  uri: "http://gw.crawlrelay.com:7777",
  token: `Basic ${credentials}`,
});

const res = await fetch("https://api.ipify.org?format=json", {
  dispatcher,
  signal: AbortSignal.timeout(30000),
});
console.log(res.status, await res.json());
await dispatcher.close();
```

## ¿Cómo uso un proxy con axios?

No confíes en la opción `proxy` propia de axios para sitios HTTPS: envía la solicitud al proxy sin un túnel CONNECT, que muchos proxies rechazan. Desactívalo con `proxy: false` y pasa un agente que abra un túnel adecuado.

*axios + https-proxy-agent*

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

const agent = new HttpsProxyAgent("http://USERNAME-country-de:PASSWORD@gw.crawlrelay.com:7777");
const client = axios.create({ httpsAgent: agent, httpAgent: agent, proxy: false, timeout: 30000 });

const { data } = await client.get("https://api.ipify.org?format=json");
console.log(data.ip);
```

## ¿Cómo uso un proxy con got?

got usa un agente por protocolo. hpagent sigue el `http.Agent` de Node: keep-alive está desactivado a menos que pases `keepAlive: true`. Déjalo desactivado o configura `keepAlive: false` como abajo cuando quieres cada solicitud en una conexión nueva, y por lo general en una salida nueva.

*got + hpagent*

```javascript
import got from "got";
import { HttpsProxyAgent } from "hpagent";

const proxy = "http://USERNAME-country-fr:PASSWORD@gw.crawlrelay.com:7777";
const body = await got("https://api.ipify.org", {
  agent: { https: new HttpsProxyAgent({ proxy, keepAlive: false }) },
  timeout: { request: 30000 },
  retry: { limit: 2, statusCodes: [429, 502, 503, 504] },
}).text();
console.log(body);
```

## ¿Cómo uso SOCKS5 en Node.js?

Usa `socks-proxy-agent` con el esquema `socks5h://` para que el nombre de host se resuelva en la salida. Funciona con los módulos `http` y `https` de Node y con cualquier biblioteca que acepte un agente.

*socks-proxy-agent con node:https*

```javascript
import https from "node:https";
import { SocksProxyAgent } from "socks-proxy-agent";

const agent = new SocksProxyAgent("socks5h://USERNAME-country-gb:PASSWORD@gw.crawlrelay.com:7778");

const req = https.get("https://api.ipify.org", { agent, timeout: 30000 }, (res) => {
  let body = "";
  res.on("data", (chunk) => (body += chunk));
  res.on("end", () => console.log(res.statusCode, body));
});
req.on("timeout", () => req.destroy(new Error("timeout after 30 s")));
req.on("error", (err) => console.error(err.code, err.message));
```

## ¿Cómo limito la concurrencia por host sin una biblioteca?

`Promise.all` sobre 10,000 URLs abre 10,000 solicitudes a la vez. Un limitador pequeño por hostname mantiene cada sitio en un nivel respetuoso mientras el rastreo entero corre en paralelo. La versión abajo no tiene dependencia y funciona con cualquier cliente superior.

*Limitador por host + undici*

```javascript
import { ProxyAgent, fetch } from "undici";

const PER_HOST = 4;
const active = new Map();
const waiting = new Map();
const dispatcher = new ProxyAgent("http://USERNAME-country-us:PASSWORD@gw.crawlrelay.com:7777");

async function withHostSlot(url, task) {
  const host = new URL(url).hostname;
  while ((active.get(host) ?? 0) >= PER_HOST) {
    await new Promise((resolve) => {
      if (!waiting.has(host)) waiting.set(host, []);
      waiting.get(host).push(resolve);
    });
  }
  active.set(host, (active.get(host) ?? 0) + 1);
  try {
    return await task();
  } finally {
    active.set(host, active.get(host) - 1);
    waiting.get(host)?.shift()?.();
  }
}

const urls = ["https://example.com/", "https://example.org/", "https://example.net/"];
const results = await Promise.all(
  urls.map((url) =>
    withHostSlot(url, async () => {
      const res = await fetch(url, { dispatcher, signal: AbortSignal.timeout(30000) });
      return [url, res.status, (await res.arrayBuffer()).byteLength];
    }).catch((err) => [url, err.name, 0])
  )
);
console.table(results);
await dispatcher.close();
```

## ¿Por qué obtengo la misma IP dos veces o ECONNRESET?

Los agentes agrupan conexiones, y una conexión agrupada mantiene la salida con la que se abrió. Para una IP nueva en cada solicitud, crea un agente nuevo por solicitud y ciérralo después, desactiva keep-alive en el agente, o pon un `-session-<id>` único en el nombre de usuario de cada solicitud.

`ECONNRESET` y `socket hang up` suelen venir de reutilizar un socket agrupado que el otro lado ya cerró, o de una salida que se cayó. Reintenta solicitudes GET una vez en una conexión nueva. La [página sobre reinicios de conexión](https://crawlrelay.com/es/docs/errors/connection-reset/) cubre los detalles.

## Node.js y proxies: preguntas

### ¿fetch de Node.js soporta HTTP_PROXY?

No por defecto en las versiones que la mayoría de proyectos usan hoy: el fetch global ignora variables de entorno de proxy a menos que pases un dispatcher. Usa un `ProxyAgent` de undici como se mostró arriba, o define un dispatcher global con el `setGlobalDispatcher()` de undici si todas las solicitudes del proceso deben usar el proxy.

### ¿Por qué falla axios con sitios HTTPS detrás de un proxy?

La opción `proxy` integrada de axios envía solicitudes HTTPS al proxy en un formato que muchos proxies rechazan, en lugar de abrir un túnel CONNECT. Configura `proxy: false` y pasa un `HttpsProxyAgent` como `httpsAgent`. La solicitud entonces viaja por un túnel adecuado, y TLS permanece entre tu código y el sitio.

### ¿Cómo envío diferentes países desde un proceso Node.js?

Crea un agente por país, cada uno con su propio nombre de usuario como `USERNAME-country-de` o `USERNAME-country-jp`, y escoge el agente por solicitud. Los agentes son baratos, y mantenerlos separados también mantiene sus grupos de conexión, y así sus salidas, separados.

### ¿Qué timeout debo configurar en Node.js?

Siempre configura uno: `AbortSignal.timeout(30000)` para fetch, `timeout: 30000` para axios, `timeout: { request: 30000 }` para got. Treinta segundos son adecuados para páginas HTML; da hasta 60 segundos para objetivos lentos y salidas móviles, y reintenta una vez en una conexión nueva en lugar de esperar más.

**Conecta tu rastreador Node.js** 5,94 US$ para 10 GB, 0,50 US$/GB de 50 GB. [Ver precios](https://crawlrelay.com/es/pricing/) · [Guía Puppeteer](https://crawlrelay.com/es/docs/puppeteer/)

---

CrawlRelay: CrawlRelay es un servicio de proxies residenciales rotativos y proxies móviles 4G/5G para desarrolladores, ideal para scrapers y pipelines de datos de IA: tráfico prepago sin vencimiento desde 0,50 US$/GB, pagado con criptomonedas, sin subir documentos de identidad. Sin KYC — sin ID, sin selfie, sin documentos. Paga con criptomonedas.
