Volver al blog

Renderizado de JavaScript a través de proxy: cómo evitar bloqueos y errores

La representación de JavaScript requiere un enfoque especial al trabajar con proxies. Veamos qué problemas surgen y cómo resolverlos.

📅4 de diciembre de 2025
```html

Renderización de JavaScript a través de proxy: cómo evitar bloqueos y errores

Cuando analiza sitios web que cargan contenido a través de JavaScript, las simples solicitudes HTTP se vuelven ineficaces. Agregue a esto la protección contra bots y las restricciones geográficas, y la tarea se vuelve mucho más complicada. Los proxies resuelven parte de los problemas, pero requieren una configuración adecuada.

Por qué la renderización de JavaScript requiere proxy

Los sitios web modernos a menudo utilizan marcos como React, Vue o Angular, que cargan contenido en el lado del cliente. Cuando envía una solicitud GET ordinaria, obtiene HTML vacío con una etiqueta <div id="root"></div>, no el contenido listo.

Problemas que resuelven los proxies:

  • Bloqueos geográficos. Los sitios restringen el acceso por países. Los proxies con IP de la región necesaria eluden estas restricciones.
  • Protección contra bots. Cloudflare, hCaptcha y sistemas similares bloquean solicitudes automatizadas. Los proxies residenciales se ven como usuarios normales y pasan mejor las verificaciones.
  • Limitación de velocidad. El servidor puede bloquear una IP después de múltiples solicitudes. Los proxies distribuyen el tráfico y evitan bloqueos.
  • Anonimato. Ocultan su IP real al analizar.

Navegadores headless y proxy: conceptos básicos

Para la renderización de JavaScript se utilizan navegadores headless: Chromium sin interfaz gráfica. Opciones populares:

  • Puppeteer — biblioteca Node.js para controlar Chrome/Chromium.
  • Playwright — alternativa multiplataforma, compatible con Chrome, Firefox, Safari.
  • Selenium — opción clásica, funciona con diferentes navegadores.

Todos ellos admiten proxies a través de parámetros de inicio del navegador u opciones de conexión.

Configuración práctica

Puppeteer con proxy

Ejemplo básico de conexión de proxy a Puppeteer:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    args: [
      '--proxy-server=http://proxy.example.com:8080'
    ]
  });

  const page = await browser.newPage();
  await page.goto('https://example.com');
  
  const content = await page.content();
  console.log(content);
  
  await browser.close();
})();

Si el proxy requiere autenticación:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    args: [
      '--proxy-server=http://proxy.example.com:8080'
    ]
  });

  const page = await browser.newPage();
  
  // Configuración de credenciales para proxy
  await page.authenticate({
    username: 'user',
    password: 'pass'
  });
  
  await page.goto('https://example.com');
  const content = await page.content();
  
  await browser.close();
})();

Playwright con proxy

En Playwright, el proxy se configura a través del contexto del navegador:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({
    proxy: {
      server: 'http://proxy.example.com:8080',
      username: 'user',
      password: 'pass'
    }
  });

  const context = await browser.newContext();
  const page = await context.newPage();
  
  await page.goto('https://example.com');
  const content = await page.content();
  
  await browser.close();
})();

Rotación de proxy para múltiples solicitudes

Para análisis a gran escala, se necesita rotación de proxy. Aquí hay un ejemplo simple con una matriz:

const puppeteer = require('puppeteer');

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

let proxyIndex = 0;

async function getPageWithProxy(url) {
  const currentProxy = proxies[proxyIndex % proxies.length];
  proxyIndex++;
  
  const browser = await puppeteer.launch({
    args: [`--proxy-server=${currentProxy}`]
  });
  
  const page = await browser.newPage();
  await page.goto(url);
  const content = await page.content();
  
  await browser.close();
  return content;
}

// Uso
(async () => {
  const urls = ['https://example.com/1', 'https://example.com/2'];
  for (const url of urls) {
    const content = await getPageWithProxy(url);
    console.log('Analizado:', url);
  }
})();

Errores típicos y soluciones

Error Causa Solución
ERR_TUNNEL_CONNECTION_FAILED El proxy no está disponible o las credenciales son incorrectas Verifique IP:puerto del proxy, usuario/contraseña. Pruebe a través de curl
Tiempo de espera agotado al cargar Proxy lento o el sitio bloquea la solicitud Aumente el tiempo de espera, agregue User-Agent, use proxies residenciales
403 Prohibido El sitio detectó un bot Agregue encabezados realistas, use proxies residenciales, agregue retrasos entre solicitudes
CAPTCHA en cada solicitud El sitio ve el mismo User-Agent Rote User-Agent, use diferentes proxies para cada navegador

Adición de encabezados realistas

const page = await browser.newPage();

await page.setUserAgent(
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
);

await page.setExtraHTTPHeaders({
  'Accept-Language': 'es-ES,es;q=0.9',
  'Accept': 'text/html,application/xhtml+xml',
  'Referer': 'https://google.com'
});

await page.goto('https://example.com');

Optimización del rendimiento

Deshabilitación de recursos innecesarios

La carga de imágenes y estilos ralentiza el análisis. Si solo necesita texto:

const page = await browser.newPage();

// Bloqueamos la carga de imágenes y estilos
await page.on('request', (request) => {
  const resourceType = request.resourceType();
  if (['image', 'stylesheet', 'font', 'media'].includes(resourceType)) {
    request.abort();
  } else {
    request.continue();
  }
});

await page.goto('https://example.com');

Uso de un grupo de navegadores

Para procesar múltiples páginas en paralelo, cree un grupo de navegadores en lugar de iniciar un nuevo navegador para cada solicitud:

const puppeteer = require('puppeteer');

let browser;
const maxPages = 5;
let activePage = 0;

async function initBrowser() {
  browser = await puppeteer.launch({
    args: ['--proxy-server=http://proxy.example.com:8080']
  });
}

async function parsePage(url) {
  const page = await browser.newPage();
  try {
    await page.goto(url);
    const content = await page.content();
    return content;
  } finally {
    await page.close();
  }
}

// Uso
(async () => {
  await initBrowser();
  const urls = ['url1', 'url2', 'url3'];
  
  for (const url of urls) {
    await parsePage(url);
  }
  
  await browser.close();
})();

Herramientas y bibliotecas

  • Puppeteer Extra — extensión de Puppeteer con soporte de complementos para eludir la protección contra bots.
  • Cheerio — biblioteca ligera para analizar HTML después de la renderización del navegador.
  • Axios + Proxy Agent — para solicitudes simples a través de proxy sin navegador.
  • Scrapy — marco Python con soporte integrado para proxy y análisis distribuido.

Importante: Al trabajar con proxies, asegúrese de cumplir con los términos de uso del sitio de destino y no viole su robots.txt. El análisis debe ser ético y no sobrecargar los servidores.

Conclusión

La renderización de JavaScript a través de proxy es una herramienta poderosa para automatizar el análisis, pero requiere atención a los detalles. La configuración correcta del navegador, la rotación de proxy, los encabezados realistas y la optimización del rendimiento son las claves para un funcionamiento confiable.

Para análisis a gran escala con altos requisitos de anonimato, los proxies residenciales son adecuados, que se ven como usuarios normales y eluden la mayoría de las protecciones contra bots.

```