Puppeteer es una biblioteca de Node.js que te permite controlar Chrome desde el código: abre páginas, rellena formularios, hace capturas de pantalla y espera hasta que se carga el contenido dinámico. Se usa en muchas tareas, desde pruebas de extremo a extremo hasta la generación de informes. Pero a medida que crece la automatización, la mayoría de los equipos se encuentra con el mismo obstáculo: el CAPTCHA.
Este artículo no trata de cómo «resolver» el CAPTCHA, sino de entender por qué aparece y evitar que una automatización legítima lo active sin necesidad. El CAPTCHA es la manera que tiene el dueño del sitio de decir «no estoy seguro de este tráfico»; leer bien esa señal siempre es más sostenible que competir contra ella. Al final encontrarás una configuración de Puppeteer que funciona, una lista de comprobación y lo que no debes hacer.
Tipos de CAPTCHA y cómo se activan
La mayoría de los CAPTCHA que verás hoy no son la pantalla de «selecciona los semáforos de la imagen». Hay tres formas habituales:
- Verificación invisible. Mientras se carga la página, el entorno del navegador y el comportamiento se puntúan en segundo plano; el usuario no ve nada. Si la puntuación es baja, se pasa a un paso visible.
- Confirmación con un clic. Una casilla de «No soy un robot» o una confirmación ligera como Cloudflare Turnstile. La mayoría de los usuarios reales la pasan con un clic.
- Rompecabezas visual o interactivo. El paso que se muestra cuando la puntuación es muy baja y que exige esfuerzo humano.
Estas tres formas son etapas distintas del mismo sistema de puntuación. Es decir, la pregunta no es si el CAPTCHA «apareció» o «no apareció», sino qué umbral superó tu puntuación. Cada medida que mantiene baja la puntuación hace que nunca llegues al paso visible.
¿Por qué aparece el CAPTCHA?
Las protecciones modernas contra bots no se fijan en una sola regla; puntúan muchas señales en conjunto. En las sesiones de Puppeteer, estos son los factores que más suben esa puntuación:
1. Tipo y reputación de la dirección IP
Si la petición llega desde una IP de centro de datos, se considera de entrada más sospechosa que una petición de un usuario doméstico corriente. Que se abran muchas sesiones desde la misma IP en poco tiempo, o que la dirección se haya usado antes de forma abusiva, sube todavía más la puntuación. Explicamos la diferencia entre tipos de IP en Proxies residenciales y de centro de datos: diferencias.
2. Velocidad y patrón de las peticiones
Las personas leen las páginas, se desplazan y esperan. Una sesión que abre decenas de páginas por segundo y hace exactamente el mismo clic en el mismo tiempo en cada página no se parece al comportamiento humano. Incluso una espera a intervalos fijos es un patrón; las esperas humanas son irregulares.
3. Huellas del navegador sin interfaz
Un navegador abierto por automatización puede llevar, con la configuración por defecto, huellas que lo delatan. La más conocida es que la propiedad navigator.webdriver sea true; esta propiedad existe precisamente para indicar que el navegador está bajo automatización. También llaman la atención los tamaños de ventana poco realistas (el valor por defecto de Puppeteer es 800×600), las funciones del navegador que faltan y los valores de User-Agent propios del modo sin interfaz.
4. Perfil incoherente
Una IP de Madrid con un navegador en idioma en-US y zona horaria de Nueva York; o una sola sesión cuya huella digital cambia en cada petición. Que las señales se contradigan entre sí resulta más sospechoso que cada una por separado. Tratamos cómo se forma la huella digital en ¿Qué es la huella digital del navegador?.
5. Sesión sin historial
Un navegador que se abre desde cero en cada ejecución, sin ninguna cookie, parece un usuario que visita el sitio por primera vez. Esto por sí solo no es un problema; pero combinado con las demás señales sube la puntuación. La cookie de una sesión que ya superó una verificación baja la puntuación en las visitas siguientes.
6. Análisis de comportamiento
Algunas protecciones no miran solo el momento de entrada, sino el movimiento del cursor y la coherencia de la interacción durante toda la sesión. Explicamos este enfoque de nueva generación en detalle en nuestro artículo sobre Cloudflare Precursor.
Causas y medidas en una tabla
| Causa | Señal | Medida legítima |
|---|---|---|
| IP de centro de datos | Tipo de ASN, reputación de la IP | Proxy residencial o ISP |
| Velocidad alta | Frecuencia de peticiones, intervalo fijo | Esperas variables, poca concurrencia |
| Huellas sin interfaz | navigator.webdriver, ventana por defecto | Ventana realista, modo sin interfaz actual |
| Perfil incoherente | Ubicación de la IP en conflicto con idioma o zona horaria | Ajustar el perfil a la IP |
| Sesión sin historial | Cookies vacías, perfil nuevo | userDataDir persistente |
| Cambio de IP dentro de la sesión | Misma cookie, dirección distinta | IP de sesión fija o estática |
¿Cómo reducir el CAPTCHA de forma legítima?
El objetivo común de las medidas siguientes no es ocultar tu automatización, sino evitar que genere sospechas innecesarias.
Baja la velocidad y reparte las peticiones
Es la medida más eficaz y la más barata. Añade esperas variables entre páginas, limita el número de pestañas abiertas a la vez y reparte el trabajo en distintas horas del día. Reducir la carga sobre el sitio de destino significa menos bloqueos para ti y menos costo para la otra parte.
const pause = (min, max) =>
new Promise((resolve) => setTimeout(resolve, min + Math.random() * (max - min)));
for (const url of urls) {
await page.goto(url, { waitUntil: "domcontentloaded" });
// procesa la página
await pause(2000, 6000);
}Conserva las sesiones y las cookies
En lugar de abrir un perfil nuevo en cada ejecución, usa un directorio de datos de usuario persistente. Así las cookies y las verificaciones ya superadas se conservan entre sesiones:
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
userDataDir: "./profile-1",
});Si gestionas varias cuentas o tareas, usa un directorio distinto para cada una; que los perfiles se mezclen genera la señal de que se gestionan muchas cuentas desde un solo dispositivo.
Mantén el perfil coherente
El idioma, la zona horaria y el tamaño de ventana del navegador deben coincidir con la ubicación de la IP que usas. No cambies estos valores durante la sesión:
const page = await browser.newPage();
await page.setViewport({ width: 1366, height: 768 });
await page.emulateTimezone("Europe/Madrid");
await page.setExtraHTTPHeaders({ "Accept-Language": "es-ES,es;q=0.9" });Elige el tamaño de ventana entre los valores habituales de los dispositivos reales; una resolución poco común llama la atención por sí sola.
Usa una sola IP por sesión
En Puppeteer el proxy se pasa con un argumento de arranque de Chrome. Si hace falta autenticación, se usa page.authenticate:
import puppeteer from "puppeteer";
const browser = await puppeteer.launch({
args: ["--proxy-server=http://pr.proxynet.io:8000"],
});
const page = await browser.newPage();
await page.authenticate({ username: "user", password: "pass" });
await page.goto("https://httpbin.org/ip", { waitUntil: "networkidle2" });
console.log(await page.evaluate(() => document.body.innerText));
await browser.close();Lo importante aquí es que la IP no cambie durante la sesión. Que la dirección IP cambie en mitad de una sesión con usuario iniciado es una de las causas más frecuentes del CAPTCHA. En este tipo de flujos, Proxies de sesión fija mantiene la misma IP durante un tiempo determinado; en sesiones largas por cuenta, Proxies ISP es más estable. En sitios protegidos, Proxies residenciales, que llega desde direcciones de usuarios reales, despierta menos sospechas que las IP de centro de datos.
No bloquees recursos sin necesidad
Bloquear imágenes y hojas de estilo para ahorrar ancho de banda es una costumbre muy extendida. Pero un «navegador» que no carga ninguna imagen no se parece a un usuario real, y algunas protecciones usan esa ausencia como señal. Si el costo del tráfico es un problema, bloquear solo los archivos multimedia pesados (vídeo, imágenes grandes) es un término medio más equilibrado.
Si puedes, acude a la fuente oficial
Si el sitio de destino ofrece una API, puede que no necesites automatizar un navegador. Las API son más rápidas, consumen menos recursos y no te encuentras con CAPTCHA. Si pruebas tu propio sitio o el de un cliente, pedir al dueño del sitio que excluya tu tráfico de pruebas de las reglas de protección es la solución más limpia.
Ejemplo completo: una configuración coherente de Puppeteer
Una configuración que reúne las medidas anteriores, funciona con proxy y espera un tiempo variable entre páginas:
import puppeteer from "puppeteer";
const pause = (min, max) =>
new Promise((resolve) => setTimeout(resolve, min + Math.random() * (max - min)));
const browser = await puppeteer.launch({
userDataDir: "./profile-1",
args: ["--proxy-server=http://pr.proxynet.io:8000", "--window-size=1366,768"],
defaultViewport: { width: 1366, height: 768 },
});
const page = await browser.newPage();
await page.authenticate({ username: "user", password: "pass" });
await page.emulateTimezone("Europe/Madrid");
await page.setExtraHTTPHeaders({ "Accept-Language": "es-ES,es;q=0.9" });
const urls = ["https://httpbin.org/ip", "https://httpbin.org/headers"];
for (const url of urls) {
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
console.log(url, (await page.evaluate(() => document.body.innerText)).slice(0, 80));
await pause(2000, 5000);
}
await browser.close();En esta configuración la IP es fija durante la sesión, el perfil es persistente, la zona horaria y el idioma coinciden con la ubicación de la IP (España) y entre páginas hay una espera irregular, parecida a la humana.
Lo que no debes hacer
- Usar servicios de resolución de CAPTCHA. Los servicios que hacen que personas o modelos resuelvan el CAPTCHA y pasan el resultado a la automatización atacan una protección que el dueño del sitio ha puesto a propósito. Incumplen las condiciones de uso de muchos sitios y pueden generar riesgos legales.
- Confiar en complementos para evitar la detección. Los complementos que prometen ocultar las huellas de la automatización están en una persecución constante con los proveedores de protección. Un método que funciona hoy puede dejar de funcionar mañana; basar tu flujo de trabajo en eso no es sostenible.
- Subir la velocidad cuando te bloquean. El CAPTCHA es un aviso. Responder con más peticiones suele terminar en el bloqueo total de la IP.
- Cambiar de IP en cada petición manteniendo la misma sesión. Que la dirección cambie constantemente mientras la cookie sigue igual es un patrón más sospechoso que cambiar de IP por sí solo.
Explicamos qué datos se pueden recoger y en qué condiciones en ¿Es legal el web scraping?.
¿Qué hacer cuando aparece un CAPTCHA?
Si ves CAPTCHA a pesar de las medidas, úsalo como una oportunidad de diagnóstico:
- Anota en qué página aparece. ¿En la de inicio de sesión, en un listado, en una página de detalle? Eso muestra dónde se concentra la protección.
- Cambia la IP y repite el mismo flujo. Si el CAPTCHA desaparece, el problema está en la reputación de la IP; si sigue, viene del perfil o de la velocidad.
- Reduce la velocidad a la mitad. Si la frecuencia baja, el umbral depende de la velocidad.
- Compara el perfil con un navegador real. Si entras al mismo sitio con Chrome normal y no ves CAPTCHA, lo determinante son las huellas de la automatización.
Estos cuatro pasos revelan en pocos intentos qué señal sube la puntuación. Probar una sola variable cada vez ahorra tiempo frente a probar a ciegas. Si en lugar de CAPTCHA recibes respuestas como 403, 429 o 503, encontrarás el significado de cada código y en cuáles conviene reintentar en Códigos de error HTTP en web scraping.
¿Hay herramientas mejores que Puppeteer?
La situación de Selenium, Playwright y Puppeteer frente al CAPTCHA es básicamente la misma; todas controlan un navegador real desde el código y están sujetas a las mismas señales. Cambiar de herramienta no elimina las causas anteriores. Muchas veces la primera pregunta no es qué herramienta elegir, sino si de verdad necesitas un navegador; explicamos cómo saberlo en Páginas estáticas y dinámicas. Para los equivalentes en el ecosistema de Python, consulta nuestros artículos sobre Selenium, SeleniumBase con proxy y Undetected ChromeDriver. Comparamos los demás factores que influyen en la elección del lenguaje en Web scraping: ¿JavaScript o Python?.
Preguntas frecuentes
¿El modo sin interfaz aumenta el CAPTCHA?
El antiguo modo sin interfaz llevaba huellas más fáciles de distinguir de un navegador normal. El modo sin interfaz actual de Chrome se parece mucho más a un navegador normal. Aun así, trabajar sin interfaz puede influir en la puntuación cuando se combina con otras señales.
¿Un proxy evita el CAPTCHA por completo?
No. El tipo de IP adecuado baja la puntuación de sospecha, pero siguen existiendo otras señales, como la velocidad de las peticiones, la incoherencia del perfil y el comportamiento. La IP es solo una parte de la solución.
¿Es buena idea cambiar de IP en cada petición?
Para descargas de páginas independientes que no requieren sesión, sí; Proxies rotativos es adecuado para ese trabajo. En flujos con inicio de sesión o de varios pasos, en cambio, la IP debe mantenerse fija durante la sesión; de lo contrario aumenta la probabilidad de CAPTCHA.
¿Puedo usar un proxy SOCKS5 en Puppeteer?
Sí. Se indica con el formato --proxy-server=socks5://servidor:puerto. Pero Chrome no soporta la autenticación con usuario y contraseña en SOCKS5; si vas a usar SOCKS5, tienes que autorizar la IP en el panel del proxy. Para las diferencias entre protocolos, consulta Proxy SOCKS o HTTP: cuál elegir.
¿Aparece menos CAPTCHA al automatizar la versión móvil de un sitio?
La vista móvil por sí sola no baja la puntuación. Si usas un perfil móvil, que la IP también sea móvil aporta coherencia; un perfil móvil con una IP de escritorio es una contradicción. Explicamos la diferencia del tráfico móvil en Proxies residenciales y móviles: diferencias.
¿El uso de proxy es distinto en Puppeteer y en Playwright?
La lógica es la misma: la dirección del proxy se indica al arrancar el navegador y las credenciales se definen con una llamada aparte. En Playwright esta configuración se hace en un solo objeto con el formato launch({ proxy: { server, username, password } }).
En resumen
Detrás del CAPTCHA en Puppeteer suelen estar el tipo de IP, la velocidad de las peticiones, las huellas del navegador sin interfaz y un perfil incoherente. Bajar la velocidad, conservar las sesiones, mantener el perfil coherente con la ubicación de la IP y usar una IP fija por sesión reduce claramente el CAPTCHA en automatizaciones legítimas. Cuando aparece un CAPTCHA, encontrar la causa probando una variable cada vez es mucho más rápido que el ensayo y error a ciegas. Intentar saltarse la protección, en cambio, es un camino frágil y arriesgado. Encontrarás los tipos de IP adecuados para tus proyectos de automatización en nuestras soluciones de proxy.




