Al desarrollar aplicaciones Node.js para scraping, automatización o trabajo con API, a menudo surge la necesidad de utilizar servidores proxy. Esto permite eludir restricciones geográficas, distribuir la carga y evitar bloqueos por IP. En esta guía, analizaremos todas las formas de configurar proxies en Node.js, desde técnicas básicas hasta avanzadas con rotación y manejo de errores.
Conceptos básicos sobre el uso de proxies en Node.js
Un servidor proxy en Node.js actúa como intermediario entre su aplicación y el servidor de destino. Cuando envía una solicitud HTTP a través de un proxy, su aplicación primero se conecta al servidor proxy, que luego redirige la solicitud a la dirección final. Esto permite ocultar la dirección IP real de su servidor y utilizar la dirección IP del proxy.
En Node.js, hay varias formas básicas de trabajar con proxies dependiendo de la biblioteca utilizada para las solicitudes HTTP. Las opciones más populares son:
- Módulos incorporados http/https — funcionalidad básica sin dependencias adicionales
- Axios — biblioteca popular con una API conveniente y soporte para promesas
- Got — alternativa moderna con soporte para TypeScript
- node-fetch — implementación de Fetch API para Node.js
- request — biblioteca obsoleta, pero aún utilizada (no recomendada para nuevos proyectos)
Los servidores proxy admiten varios protocolos. Para trabajar con Node.js, los más utilizados son:
| Protocolo | Descripción | Aplicación |
|---|---|---|
| HTTP | Protocolo básico para conexiones no cifradas | Scraping, trabajo con API sin SSL |
| HTTPS | Proxy con soporte para cifrado SSL/TLS | Conexiones seguras, trabajo con API protegidas |
| SOCKS5 | Protocolo universal para cualquier tipo de tráfico | WebSocket, UDP, escenarios complejos |
Para tareas de scraping y automatización, los desarrolladores a menudo utilizan proxies residenciales, ya que tienen direcciones IP reales de usuarios domésticos y son menos propensos a ser bloqueados por los sitios de destino.
Configuración de proxy a través del módulo http/https incorporado
Node.js proporciona módulos incorporados http y https para trabajar con solicitudes HTTP. Para conectar un proxy, se puede utilizar la biblioteca http-proxy-agent o https-proxy-agent.
Primero, instale los paquetes necesarios:
npm install http-proxy-agent https-proxy-agent
Ejemplo de uso de un proxy HTTP con el módulo incorporado:
const http = require('http');
const { HttpProxyAgent } = require('http-proxy-agent');
// Configuración del proxy
const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = new HttpProxyAgent(proxyUrl);
// Opciones de la solicitud
const options = {
hostname: 'api.example.com',
path: '/endpoint',
method: 'GET',
agent: agent,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
};
// Realizar la solicitud
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Respuesta:', data);
});
});
req.on('error', (error) => {
console.error('La solicitud falló:', error.message);
});
req.end();
Para conexiones HTTPS, utilice https-proxy-agent:
const https = require('https');
const { HttpsProxyAgent } = require('https-proxy-agent');
const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = new HttpsProxyAgent(proxyUrl);
const options = {
hostname: 'api.example.com',
path: '/secure-endpoint',
method: 'GET',
agent: agent
};
https.get(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Respuesta segura:', data);
});
}).on('error', (error) => {
console.error('La solicitud HTTPS falló:', error.message);
});
Este enfoque proporciona el máximo control sobre las solicitudes, pero requiere más código para manejar promesas y errores. Para la mayoría de las tareas, es más conveniente utilizar bibliotecas especializadas.
Uso de proxies en la biblioteca Axios
Axios es una de las bibliotecas más populares para solicitudes HTTP en Node.js. Proporciona una API conveniente para configurar proxies y maneja automáticamente las promesas.
Instalación de Axios:
npm install axios
La configuración básica de un proxy en Axios se ve así:
const axios = require('axios');
// Método 1: Configuración del proxy en la configuración de la solicitud
axios.get('https://api.example.com/data', {
proxy: {
protocol: 'http',
host: 'proxy-server.com',
port: 8080,
auth: {
username: 'your-username',
password: 'your-password'
}
}
})
.then(response => {
console.log('Datos:', response.data);
})
.catch(error => {
console.error('Error:', error.message);
});
Para reutilizar las mismas configuraciones de proxy, es conveniente crear una instancia de Axios con la configuración preestablecida:
const axios = require('axios');
// Crear una instancia con configuraciones de proxy
const axiosWithProxy = axios.create({
proxy: {
protocol: 'http',
host: 'proxy-server.com',
port: 8080,
auth: {
username: 'your-username',
password: 'your-password'
}
},
timeout: 10000,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
// Uso de la instancia
async function fetchData() {
try {
const response = await axiosWithProxy.get('https://api.example.com/data');
console.log('Respuesta:', response.data);
return response.data;
} catch (error) {
console.error('La solicitud falló:', error.message);
throw error;
}
}
fetchData();
Para trabajar con proxies HTTPS a través del método CONNECT, se pueden utilizar agentes adicionales:
const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');
const proxyUrl = 'http://username:password@proxy-server.com:8080';
const httpsAgent = new HttpsProxyAgent(proxyUrl);
const axiosInstance = axios.create({
httpsAgent: httpsAgent,
timeout: 15000
});
// Uso
axiosInstance.get('https://api.example.com/secure-data')
.then(response => console.log(response.data))
.catch(error => console.error(error.message));
Axios maneja automáticamente la redirección y admite interceptores para registro y manejo de errores, lo que lo convierte en una excelente opción para proyectos que utilizan activamente proxies.
Configuración de proxies en got y node-fetch
Got es una alternativa moderna a Axios con excelente soporte para TypeScript y capacidades avanzadas de manejo de errores. Node-fetch implementa el estándar Fetch API para Node.js.
Uso de proxies en Got
Instalación de Got y los agentes necesarios:
npm install got https-proxy-agent
Ejemplo de configuración de proxy en Got:
const got = require('got');
const { HttpsProxyAgent } = require('https-proxy-agent');
const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = {
https: new HttpsProxyAgent(proxyUrl)
};
// Crear una instancia de Got con proxy
const gotWithProxy = got.extend({
agent: agent,
timeout: {
request: 10000
},
retry: {
limit: 3,
methods: ['GET', 'POST']
}
});
// Uso
async function fetchWithGot() {
try {
const response = await gotWithProxy('https://api.example.com/data');
console.log('Respuesta:', JSON.parse(response.body));
} catch (error) {
console.error('La solicitud Got falló:', error.message);
}
}
fetchWithGot();
Uso de proxies en node-fetch
Node-fetch requiere una configuración explícita del agente para trabajar con proxies:
npm install node-fetch https-proxy-agent
const fetch = require('node-fetch');
const { HttpsProxyAgent } = require('https-proxy-agent');
const proxyUrl = 'http://username:password@proxy-server.com:8080';
const agent = new HttpsProxyAgent(proxyUrl);
async function fetchWithProxy() {
try {
const response = await fetch('https://api.example.com/data', {
agent: agent,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
}
});
if (!response.ok) {
throw new Error(`Error HTTP! estado: ${response.status}`);
}
const data = await response.json();
console.log('Datos:', data);
return data;
} catch (error) {
console.error('Fetch falló:', error.message);
throw error;
}
}
fetchWithProxy();
Got proporciona una funcionalidad más rica desde el principio (reintentos automáticos, timeouts, manejo de errores), mientras que node-fetch está más cerca del estándar Fetch API y es adecuado para desarrolladores familiarizados con JavaScript en el navegador.
Conexión de proxies SOCKS5 a través de socks-proxy-agent
SOCKS5 es un protocolo de proxy universal que opera a un nivel más bajo que HTTP/HTTPS. Soporta cualquier tipo de tráfico, incluyendo conexiones UDP y WebSocket. Para trabajar con SOCKS5 en Node.js, se utiliza la biblioteca socks-proxy-agent.
Instalación de los paquetes necesarios:
npm install socks-proxy-agent
Ejemplo de uso de un proxy SOCKS5 con diferentes bibliotecas:
const { SocksProxyAgent } = require('socks-proxy-agent');
const https = require('https');
// Configuración de proxy SOCKS5 con autenticación
const proxyUrl = 'socks5://username:password@proxy-server.com:1080';
const agent = new SocksProxyAgent(proxyUrl);
const options = {
hostname: 'api.example.com',
path: '/endpoint',
method: 'GET',
agent: agent
};
https.get(options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Respuesta SOCKS5:', data);
});
}).on('error', (error) => {
console.error('La solicitud SOCKS5 falló:', error.message);
});
Uso de SOCKS5 con Axios:
const axios = require('axios');
const { SocksProxyAgent } = require('socks-proxy-agent');
const proxyUrl = 'socks5://username:password@proxy-server.com:1080';
const httpsAgent = new SocksProxyAgent(proxyUrl);
const httpAgent = new SocksProxyAgent(proxyUrl);
const axiosWithSocks = axios.create({
httpAgent: httpAgent,
httpsAgent: httpsAgent,
timeout: 15000
});
async function fetchViaSocks5() {
try {
const response = await axiosWithSocks.get('https://api.example.com/data');
console.log('Datos a través de SOCKS5:', response.data);
return response.data;
} catch (error) {
console.error('Error de solicitud SOCKS5:', error.message);
throw error;
}
}
fetchViaSocks5();
Los proxies SOCKS5 son especialmente útiles para tareas que requieren trabajar con protocolos no estándar o cuando se necesita la máxima flexibilidad. Muchos proveedores ofrecen proxies móviles con soporte para SOCKS5, lo que permite emular tráfico móvil para trabajar con API móviles.
Implementación de rotación de proxies para distribuir la carga
Al hacer scraping de grandes volúmenes de datos o trabajar con API que tienen límites en la cantidad de solicitudes desde una sola IP, es necesario utilizar rotación de proxies. Esto permite distribuir las solicitudes entre varios servidores proxy y evitar bloqueos.
Ejemplo de implementación de una simple rotación de proxies:
const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');
class ProxyRotator {
constructor(proxyList) {
this.proxyList = proxyList;
this.currentIndex = 0;
}
// Obtener el siguiente proxy de forma circular
getNextProxy() {
const proxy = this.proxyList[this.currentIndex];
this.currentIndex = (this.currentIndex + 1) % this.proxyList.length;
return proxy;
}
// Obtener un proxy aleatorio
getRandomProxy() {
const randomIndex = Math.floor(Math.random() * this.proxyList.length);
return this.proxyList[randomIndex];
}
// Crear una instancia de Axios con el proxy actual
createAxiosInstance(useRandom = false) {
const proxyUrl = useRandom ? this.getRandomProxy() : this.getNextProxy();
const agent = new HttpsProxyAgent(proxyUrl);
return axios.create({
httpsAgent: agent,
timeout: 10000,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
}
}
// Lista de proxies
const proxyList = [
'http://user1:pass1@proxy1.example.com:8080',
'http://user2:pass2@proxy2.example.com:8080',
'http://user3:pass3@proxy3.example.com:8080',
'http://user4:pass4@proxy4.example.com:8080'
];
const rotator = new ProxyRotator(proxyList);
// Uso de la rotación
async function fetchWithRotation(url) {
const axiosInstance = rotator.createAxiosInstance();
try {
const response = await axiosInstance.get(url);
console.log('Éxito con proxy');
return response.data;
} catch (error) {
console.error('La solicitud falló:', error.message);
throw error;
}
}
// Ejemplo de scraping masivo con rotación
async function massiveParsing(urls) {
const results = [];
for (const url of urls) {
try {
const data = await fetchWithRotation(url);
results.push({ url, success: true, data });
// Retraso entre solicitudes
await new Promise(resolve => setTimeout(resolve, 1000));
} catch (error) {
results.push({ url, success: false, error: error.message });
}
}
return results;
}
// Ejecutar el scraping
const urlsToParse = [
'https://api.example.com/data/1',
'https://api.example.com/data/2',
'https://api.example.com/data/3',
'https://api.example.com/data/4',
'https://api.example.com/data/5'
];
massiveParsing(urlsToParse)
.then(results => console.log('Resultados del scraping:', results))
.catch(error => console.error('Error en el scraping:', error));
Un ejemplo más avanzado con seguimiento del estado de los proxies y exclusión automática de los que no funcionan:
class AdvancedProxyRotator {
constructor(proxyList, maxFailures = 3) {
this.proxyList = proxyList.map(url => ({
url,
failures: 0,
active: true,
lastUsed: null
}));
this.maxFailures = maxFailures;
this.currentIndex = 0;
}
// Obtener un proxy activo
getActiveProxy() {
const activeProxies = this.proxyList.filter(p => p.active);
if (activeProxies.length === 0) {
throw new Error('No hay proxies activos disponibles');
}
// Buscar el proxy que no se ha utilizado durante más tiempo
const proxy = activeProxies.reduce((oldest, current) => {
if (!oldest.lastUsed) return oldest;
if (!current.lastUsed) return current;
return current.lastUsed < oldest.lastUsed ? current : oldest;
});
proxy.lastUsed = Date.now();
return proxy;
}
// Marcar un proxy como exitoso
markSuccess(proxyUrl) {
const proxy = this.proxyList.find(p => p.url === proxyUrl);
if (proxy) {
proxy.failures = 0;
}
}
// Marcar un proxy como fallido
markFailure(proxyUrl) {
const proxy = this.proxyList.find(p => p.url === proxyUrl);
if (proxy) {
proxy.failures++;
if (proxy.failures >= this.maxFailures) {
proxy.active = false;
console.warn(`Proxy ${proxyUrl} desactivado después de ${proxy.failures} fallos`);
}
}
}
// Crear una instancia de Axios con rotación
async createAxiosInstance() {
const proxy = this.getActiveProxy();
const agent = new HttpsProxyAgent(proxy.url);
return {
instance: axios.create({
httpsAgent: agent,
timeout: 10000
}),
proxyUrl: proxy.url
};
}
// Obtener estadísticas de los proxies
getStats() {
return {
total: this.proxyList.length,
active: this.proxyList.filter(p => p.active).length,
inactive: this.proxyList.filter(p => !p.active).length,
proxies: this.proxyList.map(p => ({
url: p.url.replace(/\/\/.*@/, '//***@'), // Ocultar credenciales
active: p.active,
failures: p.failures
}))
};
}
}
// Uso del rotador avanzado
const advancedRotator = new AdvancedProxyRotator(proxyList);
async function fetchWithAdvancedRotation(url) {
const { instance, proxyUrl } = await advancedRotator.createAxiosInstance();
try {
const response = await instance.get(url);
advancedRotator.markSuccess(proxyUrl);
return response.data;
} catch (error) {
advancedRotator.markFailure(proxyUrl);
throw error;
}
}
// Salida periódica de estadísticas
setInterval(() => {
console.log('Estadísticas de proxies:', advancedRotator.getStats());
}, 30000);
Este sistema excluye automáticamente los proxies que no funcionan de la rotación y distribuye uniformemente la carga entre los servidores activos. Esto es crítico al trabajar con grandes volúmenes de datos.
Manejo de errores y conmutación automática de proxies
Al trabajar con proxies, inevitablemente surgen errores: timeouts, rechazos de conexión, bloqueos por parte del servidor de destino. Un manejo adecuado de errores y la conmutación automática a otro proxy aumentan la fiabilidad de la aplicación.
Ejemplo de implementación de un sistema con reintentos automáticos y conmutación de proxies:
const axios = require('axios');
const { HttpsProxyAgent } = require('https-proxy-agent');
class ResilientProxyClient {
constructor(proxyList, maxRetries = 3) {
this.proxyList = proxyList;
this.maxRetries = maxRetries;
this.currentProxyIndex = 0;
}
// Obtener el siguiente proxy
getNextProxy() {
const proxy = this.proxyList[this.currentProxyIndex];
this.currentProxyIndex = (this.currentProxyIndex + 1) % this.proxyList.length;
return proxy;
}
// Determinar el tipo de error
isRetryableError(error) {
// Errores que justifican repetir la solicitud
const retryableCodes = ['ECONNRESET', 'ETIMEDOUT', 'ENOTFOUND', 'ECONNREFUSED'];
const retryableStatuses = [408, 429, 500, 502, 503, 504];
if (error.code && retryableCodes.includes(error.code)) {
return true;
}
if (error.response && retryableStatuses.includes(error.response.status)) {
return true;
}
return false;
}
// Realizar una solicitud con reintentos automáticos
async request(url, options = {}, attempt = 1) {
const proxyUrl = this.getNextProxy();
const agent = new HttpsProxyAgent(proxyUrl);
const config = {
...options,
httpsAgent: agent,
timeout: 10000,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
...options.headers
}
};
try {
console.log(`Intento ${attempt}/${this.maxRetries} con proxy: ${proxyUrl.replace(/\/\/.*@/, '//***@')}`);
const response = await axios.get(url, config);
console.log(`Éxito en el intento ${attempt}`);
return response.data;
} catch (error) {
console.error(`El intento ${attempt} falló: ${error.message}`);
// Si se alcanzó el límite de reintentos
if (attempt >= this.maxRetries) {
console.error(`Se alcanzó el máximo de reintentos (${this.maxRetries}) para ${url}`);
throw error;
}
// Si el error no es recuperable
if (!this.isRetryableError(error)) {
console.error(`Error no recuperable: ${error.message}`);
throw error;
}
// Retraso exponencial antes de reintentar
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
console.log(`Esperando ${delay}ms antes de reintentar...`);
await new Promise(resolve => setTimeout(resolve, delay));
// Reintento recursivo con el siguiente proxy
return this.request(url, options, attempt + 1);
}
}
// Procesamiento por lotes de URL con manejo de errores
async batchRequest(urls, concurrency = 3) {
const results = [];
const queue = [...urls];
const active = [];
while (queue.length > 0 || active.length > 0) {
// Iniciar nuevas tareas hasta alcanzar el límite de concurrencia
while (active.length < concurrency && queue.length > 0) {
const url = queue.shift();
const promise = this.request(url)
.then(data => ({ url, success: true, data }))
.catch(error => ({ url, success: false, error: error.message }))
.finally(() => {
const index = active.indexOf(promise);
if (index > -1) active.splice(index, 1);
});
active.push(promise);
}
// Esperar a que al menos una tarea se complete
if (active.length > 0) {
const result = await Promise.race(active);
results.push(result);
}
}
return results;
}
}
// Uso
const proxyList = [
'http://user1:pass1@proxy1.example.com:8080',
'http://user2:pass2@proxy2.example.com:8080',
'http://user3:pass3@proxy3.example.com:8080'
];
const client = new ResilientProxyClient(proxyList, 3);
// Solicitud única
client.request('https://api.example.com/data')
.then(data => console.log('Datos:', data))
.catch(error => console.error('Error final:', error.message));
// Procesamiento por lotes
const urls = [
'https://api.example.com/data/1',
'https://api.example.com/data/2',
'https://api.example.com/data/3',
'https://api.example.com/data/4',
'https://api.example.com/data/5'
];
client.batchRequest(urls, 3)
.then(results => {
const successful = results.filter(r => r.success).length;
const failed = results.filter(r => !r.success).length;
console.log(`Completado: ${successful} exitosos, ${failed} fallidos`);
console.log('Resultados:', results);
});
Esta implementación incluye:
- Conmutación automática al siguiente proxy en caso de error
- Retraso exponencial entre reintentos (1s, 2s, 4s, 8s, 10s máx)
- Determinación del tipo de error para decidir si reintentar
- Control de concurrencia durante el procesamiento por lotes
- Registro detallado para depuración
Mejores prácticas y optimización del rendimiento
Al trabajar con proxies en aplicaciones Node.js, se deben seguir las siguientes recomendaciones para garantizar estabilidad y rendimiento:
1. Gestión de conexiones
Reutilice agentes HTTP en lugar de crear nuevos para cada solicitud. Esto reduce la sobrecarga en el establecimiento de conexiones:
const { HttpsProxyAgent } = require('https-proxy-agent');
// Mal: creación de un agente para cada solicitud
async function badExample(url) {
const agent = new HttpsProxyAgent(proxyUrl);
return axios.get(url, { httpsAgent: agent });
}
// Bien: reutilización del agente
const agent = new HttpsProxyAgent(proxyUrl);
const axiosInstance = axios.create({
httpsAgent: agent,
httpAgent: agent
});
async function goodExample(url) {
return axiosInstance.get(url);
}
2. Configuración de timeouts
Siempre establezca timeouts razonables para evitar que la aplicación se congele:
const axiosInstance = axios.create({
httpsAgent: agent,
timeout: 10000, // Timeout general
// Configuración detallada de timeouts para Got
// timeout: {
// lookup: 1000, // Búsqueda DNS
// connect: 2000, // Conexión al proxy
// secureConnect: 2000, // Handshake SSL
// socket: 5000, // Inactividad del socket
// response: 3000, // Espera del primer byte de respuesta
// send: 10000, // Envío de la solicitud
// request: 15000 // Toda la solicitud
// }
});
3. Control de concurrencia
Limite la cantidad de solicitudes simultáneas para evitar sobrecargas:
const pLimit = require('p-limit');
// Limitación a 5 solicitudes simultáneas
const limit = pLimit(5);
async function processUrls(urls) {
const promises = urls.map(url =>
limit(() => axiosInstance.get(url))
);
return Promise.allSettled(promises);
}
4. Rotación de User-Agent
Combine la rotación de proxies con la rotación de User-Agent para mayor anonimato:
const userAgents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0'
];
function getRandomUserAgent() {
return userAgents[Math.floor(Math.random() * userAgents.length)];
}
async function fetchWithRandomUA(url) {
return axiosInstance.get(url, {
headers: {
'User-Agent': getRandomUserAgent()
}
});
}
5. Monitoreo y registro
Implemente un sistema de monitoreo para rastrear el rendimiento de los proxies:
class ProxyMonitor {
constructor() {
this.stats = new Map();
}
recordRequest(proxyUrl, success, responseTime) {
if (!this.stats.has(proxyUrl)) {
this.stats.set(proxyUrl, {
total: 0,
success: 0,
failed: 0,
totalResponseTime: 0,
avgResponseTime: 0
});
}
const stat = this.stats.get(proxyUrl);
stat.total++;
if (success) {
stat.success++;
stat.totalResponseTime += responseTime;
stat.avgResponseTime = stat.totalResponseTime / stat.success;
} else {
stat.failed++;
}
}
getReport() {
const report = [];
this.stats.forEach((stat, proxyUrl) => {
report.push({
proxy: proxyUrl.replace(/\/\/.*@/, '//***@'),
successRate: ((stat.success / stat.total) * 100).toFixed(2) + '%',
avgResponseTime: stat.avgResponseTime.toFixed(0) + 'ms',
total: stat.total,
success: stat.success,
failed: stat.failed
});
});
return report;
}
}
const monitor = new ProxyMonitor();
// Envoltura para solicitudes con monitoreo
async function monitoredRequest(url, proxyUrl) {
const startTime = Date.now();
try {
const response = await axiosInstance.get(url);
const responseTime = Date.now() - startTime;
monitor.recordRequest(proxyUrl, true, responseTime);
return response.data;
} catch (error) {
const responseTime = Date.now() - startTime;
monitor.recordRequest(proxyUrl, false, responseTime);
throw error;
}
}
// Informe periódico
setInterval(() => {
console.table(monitor.getReport());
}, 60000);
6. Selección del tipo de proxy
Elija el tipo de proxy según la tarea:
| Tarea | Tipo recomendado | Razón |
|---|---|---|
| Scraping masivo de datos públicos | Proxies de centro de datos | Alta velocidad, bajo costo |
| Trabajo con redes sociales y plataformas con protección | Proxies residenciales | IP reales, bajo riesgo de bloqueo |
| Emulación de tráfico móvil | Proxies móviles | IP de operadores móviles |
| Trabajo con protocolos no estándar | Proxies SOCKS5 | Soporte para cualquier tráfico |
Para tareas que requieren un alto nivel de anonimato y un riesgo mínimo de bloqueos, se recomienda utilizar proxies residenciales. Para scraping de grandes volúmenes de datos a alta velocidad, son adecuados los proxies de centros de datos.
7. Seguridad de credenciales
Nunca almacene las credenciales del proxy en el código. Utilice variables de entorno:
// archivo .env
PROXY_HOST=proxy-server.com
PROXY_PORT=8080
PROXY_USERNAME=your-username
PROXY_PASSWORD=your-password
// En el código
require('dotenv').config();
const proxyUrl = `http://${process.env.PROXY_USERNAME}:${process.env.PROXY_PASSWORD}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
// O para la lista de proxies
const proxyList = process.env.PROXY_LIST.split(',').map(proxy => proxy.trim());
Conclusión
Configurar proxies en aplicaciones Node.js es una habilidad importante para los desarrolladores que trabajan con scraping, automatización e integración con API externas. En esta guía, hemos revisado todas las formas principales de trabajar con proxies: desde la configuración básica a través de módulos incorporados hasta técnicas avanzadas con rotación, manejo de errores y monitoreo.
Puntos clave a recordar:
- Elija la biblioteca para solicitudes HTTP según la tarea: Axios para versatilidad, Got para proyectos de TypeScript, node-fetch para compatibilidad con API de navegador
- Utilice proxies SOCKS5 para trabajar con protocolos no estándar y máxima flexibilidad
- Implemente rotación de proxies para distribuir la carga y evitar bloqueos
- Implemente un sistema de manejo de errores con reintentos automáticos y conmutación de proxies
- Monitoree el rendimiento de los proxies y excluya automáticamente los que no funcionan
- Reutilice agentes HTTP y configure timeouts razonables
- Almacene las credenciales en variables de entorno, no en el código
Al elegir proxies para sus aplicaciones Node.js, considere la especificidad de la tarea. Para scraping de plataformas protegidas y trabajo con API sensibles a la reputación de IP, recomendamos utilizar proxies residenciales, ya que ofrecen un alto nivel de anonimato y un riesgo mínimo de bloqueos gracias al uso de direcciones IP reales de usuarios domésticos.