
Aloísio Vítor
Image Processing Expert

Playwright es un framework moderno de pruebas de automatización de navegador desarrollado por Microsoft. Admite la automatización para Chromium, Firefox y WebKit (que corresponden a Chrome, Firefox y Safari). Ofrece una potente API para el control del navegador, la selección de elementos, la interacción con formularios, la interceptación de red y más, lo que lo hace ideal para tareas que requieren una interacción profunda con las páginas web.
Cualquier navegador, cualquier plataforma, una API
Usando Playwright en Node.js:
npm i playwright
npx playwright install # Instalar todos los navegadores (Chromium, Firefox, WebKit)
Ejemplo: Obtener todos los títulos de las entradas del blog de CapSolver
En el ejemplo a continuación, usamos Playwright para navegar al blog de CapSolver y obtener todos los títulos de las entradas del blog <h5> de la página

const { chromium } = require('playwright');
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
});
const [page] = context.pages();
await page.goto('https://www.capsolver.com/blog/All');
const h5Titles = await page.evaluate(() => {
const headings = Array.from(document.querySelectorAll('h5'));
return headings.map(heading => heading.textContent.trim());
});
console.log(h5Titles);
await context.close();
})();
Playwright es lo suficientemente potente como para cargar extensiones de navegador al igual que un navegador normal.
--disable-extensions-except y --load-extension.const { chromium } = require('playwright');
const extensionPath = 'path/to/capsolver extension';
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
],
});
const [page] = context.pages();
await page.goto('https://www.capsolver.com/blog/All');
await browser.close();
})();
Los tipos de CAPTCHA como reCAPTCHA v2/v3, Cloudflare Turnstile, AWS WAF, se utilizan ampliamente en miles de sitios web. A pesar de su popularidad, estos CAPTCHA suelen tener estructuras DOM consistentes y detectables. Ahí es donde entra en juego la Extensión CapSolver: detecta y resuelve automáticamente los CAPTCHA sin necesidad de interacción manual.
Tomemos reCAPTCHA v2 como ejemplo para demostrar cómo resolverlo usando la extensión CapSolver en Playwright.
Nota: A menos que se indique lo contrario, los siguientes ejemplos utilizan el modo de clic (/assets/config.js -> reCaptchaMode: 'click').
⚠️ No olvide descomprimir el archivo zip de la extensión y configurar su
apiKeyen/assets/config.js
const { chromium } = require('playwright');
// Paso 1: Descargue la extensión de GitHub: https://github.com/capsolver/capsolver-browser-extension/releases
// Paso 2: Descomprima el archivo de extensión y configure su apiKey en /assets/config.js
const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
'--lang=en-US'
],
});
const [page] = context.pages();
await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');
// La extensión detectará y resolverá automáticamente el reCAPTCHA.
await page.waitForTimeout(15000); // Esperar a que se resuelva
await page.click('button[type="submit"]');
await page.waitForTimeout(5000);
await context.close();
})();
⚠️ La extensión CapSolver también admite muchas opciones de configuración útiles. A continuación, se muestran algunos ejemplos comunes (Nota: todas las configuraciones se establecen en
/assets/config.js)
solvedCallbackComo puede haber notado, en el código anterior esperamos 15 segundos después de cargar la página antes de hacer clic en el botón de enviar. Este retraso tenía la intención de darle a la extensión CapSolver tiempo suficiente para resolver automáticamente el reCAPTCHA. Sin embargo, este enfoque no es ideal; a veces, el CAPTCHA se resuelve mucho más rápido, y en condiciones de red deficientes, puede tardar incluso más de 15 segundos.
Ahí es donde entra en juego solvedCallback. Ofrece una mejor solución al activar una devolución de llamada una vez que se ha resuelto el CAPTCHA, notificándole que la verificación se ha completado. Puede configurar solvedCallback en /assets/config.js definiendo un nombre de función personalizado; de forma predeterminada, es captchaSolvedCallback. Luego, use page.exposeFunction en Playwright para exponer esta función dentro del contexto del navegador.
Ahora, mejoremos nuestro código anterior usando este enfoque.
const { chromium } = require('playwright');
const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
'--lang=en-US'
],
});
const [page] = context.pages();
await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');
await page.exposeFunction('captchaSolvedCallback', async () => {
console.log('¡Captcha resuelto!');
const iframe = await page.$('iframe[src*="recaptcha"]');
if (iframe) {
const frame = await iframe.contentFrame();
const finished = await frame.evaluate(() => {
const element = document.querySelector('.recaptcha-checkbox-border');
return element && window.getComputedStyle(element).display === 'none';
});
if (finished) {
console.log('¡Verificación completada!');
await page.click('button[type="submit"]');
await page.waitForTimeout(3000);
await context.close();
} else {
console.log('Verificación no completa. Reintentando...');
}
}
});
})();
Para reCAPTCHA v2, a veces pueden aparecer varios desafíos de imagen. Por lo tanto, después de cada desafío, verificamos si se ha marcado la casilla "No soy un robot"; si ha desaparecido, la verificación se considera completa.
manualSolvingEn ejemplos anteriores, la resolución de CAPTCHA comenzaba inmediatamente después de cargar la página. Sin embargo, en algunos escenarios, es posible que deba realizar otras tareas primero, como ingresar un nombre de usuario/contraseña, antes de activar la resolución de CAPTCHA. Comenzar demasiado pronto podría hacer que el token expire.
Para manejar esto, configure manualSolving: true en /assets/config.js, lo que le permite activar manualmente el proceso de resolución de CAPTCHA.
Hay dos maneras de activar la resolución:
window.postMessage({ type: 'capsolverSolve' });⚠️ Nota: ¡Esta función solo es compatible con versiones de la extensión superiores a la v1.16.0!
Ejemplo:
const { chromium } = require('playwright');
const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
'--lang=en-US'
],
});
const [page] = context.pages();
await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');
// Simular el llenado de credenciales
await page.evaluate(() => {
const inputA = document.querySelector('input[name="ex-a"]');
inputA.value = 'username';
const inputB = document.querySelector('input[name="ex-b"]');
inputB.value = 'password';
});
// Simular otras demoras o actividad del usuario
for (let i = 1; i <= 5; i++) {
await page.waitForTimeout(1000);
console.log(`Esperó ${i} segundos...`);
}
console.log('Comenzar a resolver CAPTCHA...');
// Método 1: Simular haciendo clic en el botón CapSolver
await page.evaluate(() => {
document.querySelector('#capsolver-solver-tip-button').click();
});
// Método 2: Activar usando postMessage
// await page.evaluate(() => {
// window.postMessage({ type: 'capsolverSolve' });
// });
await page.exposeFunction('captchaSolvedCallback', async () => {
console.log('¡Captcha resuelto!');
const iframe = await page.$('iframe[src*="recaptcha"]');
if (iframe) {
const frame = await iframe.contentFrame();
const finished = await frame.evaluate(() => {
const element = document.querySelector('.recaptcha-checkbox-border');
return element && window.getComputedStyle(element).display === 'none';
});
if (finished) {
console.log('¡Verificación completada!');
await page.click('button[type="submit"]');
await page.waitForTimeout(3000);
await context.close();
} else {
console.log('Verificación no completa. Intente de nuevo.');
}
}
});
})();
reCaptchaModeLa configuración reCaptchaMode admite dos modos: click y token.
Si experimenta varias rondas de selección de imágenes utilizando el modo click, es probable que se deba a una puntuación baja de huella digital del navegador. Se recomienda cambiar al modo token para una mayor fiabilidad.
| Modo Clic | Modo Token |
|---|---|
![]() |
![]() |
showSolveButtonCuando showSolveButton se establece en false (el valor predeterminado es true), el botón CapSolver ya no se mostrará en la página. Sin embargo, esto no afectará la funcionalidad normal de resolución de CAPTCHA.

Después de configurar useProxy: true, puede especificar los siguientes parámetros: proxyType, hostOrIp, port, proxyLogin y proxyPassword. Con esta configuración, utilizaremos su proxy personalizado para resolver el CAPTCHA. ¿Cuándo debería usar su propio proxy? Normalmente, en las siguientes situaciones:
Las anteriores son algunas opciones de configuración de uso común. Puede ajustar otras configuraciones según sus necesidades reales. Si tiene alguna pregunta, comuníquese con nuestro servicio de atención al cliente.
A diferencia de los CAPTCHA de terceros como reCAPTCHA, Cloudflare Turnstile, AWS WAF o GeeTest, existe otro tipo de CAPTCHA que requiere el reconocimiento de letras o dígitos de una imagen. Nos referimos a estos como CAPTCHA de ImageToText. Normalmente se ven así:

ImageToText es un CAPTCHA implementado por los propios administradores del sitio web. A diferencia de los CAPTCHA de terceros, los CAPTCHA de ImageToText son personalizados por los propietarios del sitio web. Debido a que estos CAPTCHA varían en su ubicación en diferentes sitios web y páginas, la extensión CapSolver no puede detectar automáticamente qué imágenes son CAPTCHA. Por lo tanto, debe informar explícitamente a la extensión CapSolver en su código. Así es como se hace:
capsolver-image-to-text-source con el valor 0 al elemento de imagen del CAPTCHA;capsolver-image-to-text-result con el valor 0 al campo de entrada donde debe rellenarse el resultado.Estos atributos: capsolver-image-to-text-source y capsolver-image-to-text-result, se pueden configurar en /assets/config.js usando los campos textCaptchaSourceAttribute y textCaptchaResultAttribute, respectivamente.
Recorramos un ejemplo usando el sitio:
https://captcha.com/demos/features/captcha-demo.aspx
Primero, inspeccione el código fuente de la página para ubicar el elemento de imagen CAPTCHA y el campo de entrada del resultado. En este caso:
demoCaptcha_CaptchaImagecaptchaCodeAhora, usemos Playwright para automatizar la resolución de este CAPTCHA marcando estos elementos en consecuencia:
const { chromium } = require('playwright');
// Paso 1: Obtén la extensión de GitHub (https://github.com/capsolver/capsolver-browser-extension/releases)
// Paso 2: Descomprime el archivo zip de la extensión y configura tu apiKey en /assets/config.js
const extensionPath = 'path/to/CapSolver Browser Extension-v1.16.0';
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
'--lang=en-US'
],
});
const [page] = context.pages();
await page.goto('https://captcha.com/demos/features/captcha-demo.aspx');
await page.waitForSelector('#demoCaptcha_CaptchaImage');
// Dile a la Extensión CapSolver dónde se encuentra la imagen CAPTCHA
await page.evaluate(() => {
const imgElement = document.querySelector('#demoCaptcha_CaptchaImage');
if (imgElement) {
imgElement.setAttribute('capsolver-image-to-text-source', '0');
}
});
// Dile a la Extensión CapSolver dónde debe introducirse el resultado del reconocimiento
await page.evaluate(() => {
const resultElement = document.querySelector('#captchaCode');
if (resultElement) {
resultElement.setAttribute('capsolver-image-to-text-result', '0');
}
});
// Espera a que se resuelva el CAPTCHA y envía el formulario
await page.exposeFunction('captchaSolvedCallback', async () => {
console.log('¡Captcha resuelto!');
await page.waitForTimeout(3000);
await page.click('#validateCaptchaButton');
await page.waitForTimeout(3000);
await context.close();
});
})();
Resultado:

Usar la Extensión CapSolver es conveniente y rápido, pero si eres un desarrollador experimentado, te recomendamos encarecidamente que uses la integración de la API en su lugar. En comparación con el método basado en extensiones, el enfoque de la API ofrece varias ventajas clave:
Antes de profundizar en la demostración del código, aquí tienes una breve descripción de cómo usar la API de CapSolver:
Para crear una tarea, deberás enviar un objeto JSON a CapSolver. Este JSON incluye tu clientKey, websiteURL, websiteKey y otros datos. Estos campos varían según el tipo de CAPTCHA y el sitio web.
👉 Para obtener más detalles, consulta nuestra documentación: documentación
Antes de resolver reCAPTCHA v2, lee la documentación aquí:
📖 ReCaptchaV2
Esta guía explica qué parámetros JSON incluir al crear una tarea.
Además, puedes usar la Extensión CapSolver para generar rápidamente datos JSON para tus solicitudes API.
Consulta este blog para obtener ayuda:
🔗 obtener los datos JSON
Tomemos el siguiente ejemplo:
🔗 https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php
El JSON requerido para crear una tarea para esta página es:
{
"type": "ReCaptchaV2TaskProxyLess",
"websiteKey": "6LfW6wATAAAAAHLqO2pb8bDBahxlMxNdo9g947u9",
"websiteURL": "https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php"
}
También proporcionamos ejemplos de código JavaScript para usar la API en nuestra documentación:

Integración en Playwright:
const { chromium } = require('playwright');
const axios = require('axios');
// Reemplaza con tu clave de API
const api_key = 'YOUR_API_KEY';
const captcha_type = 'ReCaptchaV2TaskProxyLess';
const site_key = '6LfW6wATAAAAAHLqO2pb8bDBahxlMxNdo9g947u9';
const site_url = 'https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php';
async function capSolver() {
const payload = {
clientKey: api_key,
task: {
type: captcha_type,
websiteKey: site_key,
websiteURL: site_url
}
};
try {
const res = await axios.post('https://api.capsolver.com/createTask', payload);
const task_id = res.data.taskId;
if (!task_id) {
console.log('Error al crear la tarea:', res.data);
return;
}
console.log('ID de tarea obtenida:', task_id);
while (true) {
await new Promise(resolve => setTimeout(resolve, 1000)); // Retraso de 1 segundo
const getResultPayload = { clientKey: api_key, taskId: task_id };
const resp = await axios.post('https://api.capsolver.com/getTaskResult', getResultPayload);
const status = resp.data.status;
if (status === 'ready') {
return resp.data.solution.gRecaptchaResponse;
}
if (status === 'failed' || resp.data.errorId) {
console.log('¡Resolución fallida! respuesta:', resp.data);
return;
}
}
} catch (error) {
console.error('Error:', error);
}
}
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: ['--lang=en-US'],
});
const [page] = context.pages();
await page.goto('https://recaptcha-demo.appspot.com/recaptcha-v2-checkbox.php');
await page.waitForSelector('form[action="/recaptcha-v2-checkbox.php"]');
const token = await capSolver();
console.log("Token:", token);
// Establece el valor del token
await page.evaluate((token) => {
const textarea = document.getElementById('g-recaptcha-response');
if (textarea) {
textarea.value = token;
}
}, token);
await page.click('button[type="submit"]');
await page.waitForTimeout(5000);
await context.close();
})();
Seguimos usando el ejemplo de https://captcha.com/demos/features/captcha-demo.aspx, donde el elemento de imagen captcha tiene el id demoCaptcha_CaptchaImage, y el elemento de entrada de resultado tiene el id captchaCode, como se muestra en la siguiente imagen:

Para ImageToTextTask, necesitamos pasar el valor base64 de la imagen captcha a CapSolver. El código de ejemplo es el siguiente:
const { chromium } = require('playwright');
const axios = require('axios');
// Reemplaza con tu clave de API
const api_key = 'YOUR_API_KEY';
const captcha_type = 'ImageToTextTask';
const site_url = 'https://captcha.com/demos/features/captcha-demo.aspx';
async function capSolver(base64Image) {
const payload = {
clientKey: api_key,
task: {
type: captcha_type,
websiteURL: site_url,
body: base64Image,
}
};
try {
const res = await axios.post('https://api.capsolver.com/createTask', payload);
const status = res.data.status;
if (status === 'ready') {
return res.data.solution.text;
}
if (status === 'failed' || res.data.errorId) {
console.log('¡Resolución fallida! respuesta:', res.data);
return "";
}
} catch (error) {
console.error('Error:', error);
}
}
(async () => {
const context = await chromium.launchPersistentContext('', {
headless: false,
viewport: { width: 1920, height: 1080 },
args: ['--lang=en-US'],
});
const [page] = context.pages();
await page.goto('https://captcha.com/demos/features/captcha-demo.aspx');
await page.waitForSelector('#demoCaptcha_CaptchaImage');
// Obtén el valor base64 de la imagen captcha
const captchaImage = await page.evaluate(() => {
const img = document.querySelector('img[id="demoCaptcha_CaptchaImage"]');
return img ? img.getAttribute('src') : null;
});
const base64Image = captchaImage.split(',')[1];
const text = await capSolver(base64Image);
console.log("Texto:", text);
// Establece el texto captcha resuelto
await page.evaluate((text) => {
document.getElementById('captchaCode').value = text;
}, text);
await page.click('#validateCaptchaButton');
await page.waitForTimeout(5000);
await context.close();
})();
Además, para algunos tipos especiales de ImageToText, puedes especificar diferentes modelos para mejorar la precisión. Para obtener más detalles, consulta nuestra documentación:
https://docs.capsolver.com/en/guide/recognition/ImageToTextTask/

Vídeos de demostración con la extensión CapSolver:
Además, CapSolver ofrece un Programa de participación en los ingresos para desarrolladores, que permite a los desarrolladores y socios ganar comisiones integrando o promocionando las soluciones de CapSolver. Es una excelente manera de monetizar tu trabajo al mismo tiempo que ayudas a otros a resolver captchas de manera eficiente. Para obtener información completa, consulta:
Plan de desarrollador de CapSolver
Las sólidas funciones de Playwright, combinadas con la capacidad de CapSolver para manejar CAPTCHA, ofrecen una solución integral para la automatización web. Ya sea que uses la extensión CapSolver por conveniencia o la API para un mayor control, esta integración simplifica las tareas complejas y mejora los flujos de trabajo de automatización. Más allá de simplemente resolver CAPTCHA, recuerda que CapSolver también ofrece un Programa de participación en los ingresos para desarrolladores, que brinda una excelente oportunidad para ganar comisiones integrando o promocionando sus soluciones.
Compara los mejores marcos de agentes de IA para automatización web, resolución de CAPTCHA, cumplimiento y flujos de trabajo de agentes listos para producción en 2026.

Compara las mejores bibliotecas de scraping web en Java, incluyendo jsoup, Selenium, Playwright para Java, HtmlUnit, Apache Nutch y opciones de API.
