Veredicto breve: elige Puppeteer para web scraping, generación de PDF y automatización solo de Chrome. Elige Playwright para testing E2E cross-browser: maneja Chromium, Firefox y WebKit con una sola API e incluye su propio test runner, espera automática y trace viewer.

CriterioPuppeteerPlaywright
NavegadoresChrome/Chromium ante todo, sin WebKit/SafariChromium, Firefox y WebKit con una sola API
Test runnerNo incluido; se suele combinar con Jest@playwright/test integrado: aserciones, paralelización, reintentos, trazas
EsperasA menudo hacen falta llamadas explícitas a waitForSelectorEspera automáticamente los elementos antes de actuar
DepuraciónslowMo, DevTools, capturas de pantalla, logs de consolaInspector, trace viewer, codegen
Descarga del navegadornpm install puppeteer descarga Chrome for TestingPaso aparte: npx playwright install
Captura desde la CLISin comando CLI, se usa page.screenshot()npx playwright screenshot <url> <archivo>
Mejor usoScraping, generación de PDF, tareas solo de ChromeSuites de pruebas E2E cross-browser

TL;DR

  • Elige Puppeteer para: web scraping, generación de PDF, automatización específica de Chrome, tareas ligeras
  • Elige Playwright para: testing E2E, cobertura cross-browser, test runner integrado, debugging avanzado
  • Las API básicas son similares (Playwright fue creado por ex-ingenieros de Puppeteer), así que la migración es directa
  • Playwright tiene más descargas semanales en npm: unos 117 millones frente a unos 13 millones de Puppeteer en la semana del 22 al 28 de septiembre de 2026 (npm: playwright, puppeteer)

Tiempo de lectura: 18 minutos

Puppeteer y Playwright son las dos herramientas dominantes de automatización de navegadores en Node.js, pero han divergido fundamentalmente en propósito: Puppeteer destaca en tareas específicas de Chrome mientras Playwright se ha convertido en el framework líder para testing E2E cross-browser. Puppeteer, lanzado por Google en 2017, fue pionero en automatización directa del Chrome DevTools Protocol. Playwright fue construido por Microsoft en 2020 con un equipo de ex-ingenieros de Puppeteer. A septiembre de 2026, Playwright tiene unas 97.000 estrellas en GitHub y Puppeteer unas 96.000. En la semana del 22 al 28 de septiembre de 2026, npm registró unos 117 millones de descargas de playwright y unos 76 millones de @playwright/test, frente a unos 13 millones de puppeteer y unos 25 millones de puppeteer-core (API del registro npm: playwright, @playwright/test, puppeteer, puppeteer-core). Playwright parchea navegadores en tiempo de compilación para entregar APIs consistentes en Chromium, Firefox y WebKit. Puppeteer se enfoca en Chrome y, desde la v23, también soporta Firefox mediante WebDriver BiDi (FAQ de Puppeteer).

Puppeteer y Playwright (como se discute en Playwright Comprehensive Guide: Multi-Browser Testing, Auto-Wait, and Trace Viewer Mastery) representan la generación moderna de herramientas de automatización de navegadores, ambas originadas de equipos en Google y Microsoft respectivamente. Mientras Puppeteer fue pionero en automatización de alto nivel del Chrome DevTools Protocol (CDP), Playwright (como se discute en Cypress Deep Dive: Architecture, Debugging, and Network Stubbing Mastery) surgió como una solución multi-navegador abordando las limitaciones de Puppeteer. Este análisis exhaustivo compara ambas herramientas en arquitectura, características, rendimiento y casos de uso prácticos para informar tu estrategia de automatización.

Introducción

La automatización de navegadores ha evolucionado significativamente desde la era WebDriver. Puppeteer (como se discute en Percy, Applitools & BackstopJS: Visual Regression Testing Solutions Compared), lanzado por Google en 2017, demostró que el acceso directo a CDP podía proporcionar automatización más rápida y confiable que herramientas basadas en WebDriver. Construyendo sobre esta base, el equipo de Playwright de Microsoft (muchos ex-contribuidores de Puppeteer) lanzó Playwright en 2020 con objetivos ambiciosos: verdadero soporte cross-browser, capacidades mejoradas de depuración y un framework de testing más opinado.

Preguntas Clave que Este Artículo Responde:

  • ¿Cuáles son las diferencias arquitectónicas fundamentales?
  • ¿Cuándo elegir Puppeteer vs Playwright?
  • ¿Cómo se comparan en escenarios del mundo real?
  • ¿Cuáles son las consideraciones de migración?

Contexto Histórico y Orígenes

Génesis de Puppeteer

Lanzamiento: Enero 2017 por el equipo de Google Chrome

Objetivos Originales:

  • Proporcionar API de alto nivel sobre Chrome DevTools Protocol
  • Habilitar automatización de Chrome headless
  • Soportar web scraping y generación de PDF
  • Ofrecer alternativa más simple a Selenium

Evolución:

  • Inicialmente solo Chrome
  • Agregado soporte de Firefox: desde la v23.0.0 Puppeteer soporta Firefox estable, automatizado mediante WebDriver BiDi (FAQ de Puppeteer)
  • Enfocado en Chrome/Chromium como objetivo principal
  • Mantenido por equipo de Google Chrome

Emergencia de Playwright

Lanzamiento: Enero 2020 por Microsoft

Antecedentes del Equipo:

  • Liderado por ex-contribuidores core de Puppeteer
  • Ingenieros que construyeron Puppeteer en Google

Filosofía de Diseño:

  • Cross-browser desde el día uno (Chromium, Firefox, WebKit)
  • Construido para testing, no solo automatización
  • Trazado y depuración comprehensivos
  • Espera automática y resiliencia

Comparación Arquitectónica

Capa de Protocolo

Puppeteer:

API Puppeteer → Chrome DevTools Protocol → Chrome
              → WebDriver BiDi           → Firefox (por defecto), Chrome (opcional)

Playwright:

API Playwright → Protocolo Playwright → Parches específicos del navegador
                                       → Chromium (CDP)
                                       → Firefox (Juggler)
                                       → WebKit (Protocolo personalizado)

Diferencia Clave: Playwright parchea navegadores en tiempo de compilación, habilitando APIs consistentes en todos los navegadores. Puppeteer depende de protocolos nativos del navegador.

Matriz de Soporte de Navegadores

CaracterísticaPuppeteerPlaywright
Chromium✅ Soporte completo✅ Soporte completo
Chrome✅ Soporte completo✅ Soporte completo
Firefox✅ Soportado desde la v23, vía WebDriver BiDi (pptr.dev)✅ Soporte completo
WebKit/Safari❌ No soportado✅ Soporte completo
Edge✅ Vía Chromium✅ Soporte completo
ProtocoloCDP para Chrome, WebDriver BiDi para FirefoxParches personalizados
Versionado del NavegadorCada versión va ligada a una versión concreta de Chrome for TestingCada versión va ligada a compilaciones concretas de los navegadores

Instalación y Configuración

Puppeteer:

npm install puppeteer
# Descarga Chrome for Testing automáticamente

npm install puppeteer-core
# Sin descarga de navegador, usa Chrome del sistema

Playwright:

npm install playwright
npx playwright install  # Descarga todos los navegadores

npm install @playwright/test  # Con test runner
npx playwright install chromium  # Un solo navegador

Qué descarga cada herramienta y cuánto espacio ocupa se explica en Tamaño de instalación: Puppeteer vs Playwright.

API y Experiencia del Desarrollador

Automatización Básica

Puppeteer:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();

    await page.goto('https://example.com');
    await page.type('#username', 'testuser');
    await page.type('#password', 'password123');
    await page.click('button[type="submit"]');

    await page.waitForSelector('.dashboard');
    const title = await page.title();
    console.log('Título de página:', title);

    await browser.close();
})();

Playwright:

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

(async () => {
    const browser = await chromium.launch({ headless: false });
    const page = await browser.newPage();

    await page.goto('https://example.com');
    await page.fill('#username', 'testuser');
    await page.fill('#password', 'password123');
    await page.click('button[type="submit"]');

    await page.waitForSelector('.dashboard');
    const title = await page.title();
    console.log('Título de página:', title);

    await browser.close();
})();

Similitud de API: los dos scripts son casi idénticos. Las API básicas se parecen porque Playwright fue creado por ex-ingenieros de Puppeteer, pero Playwright ofrece características adicionales.

Selectores Avanzados

Puppeteer:

// Selectores CSS
await page.click('#submit-button');
await page.click('.form-control:nth-child(2)');

// XPath
await page.waitForXPath('//button[contains(text(), "Enviar")]');
const [button] = await page.$x('//button[@type="submit"]');
await button.click();

// Selector de texto personalizado (vía page.evaluate)
await page.evaluate(() => {
    const button = Array.from(document.querySelectorAll('button'))
        .find(b => b.textContent.includes('Enviar'));
    button.click();
});

Playwright:

// Selectores CSS
await page.click('#submit-button');

// Selector de texto
await page.click('text=Enviar');
await page.click('button:has-text("Enviar")');

// XPath
await page.click('xpath=//button[@type="submit"]');

// Selectores avanzados
await page.click('button >> text=Enviar');  // Encadenamiento
await page.click('button:right-of(:text("Usuario"))');  // Basado en layout
await page.click('button:below(#header)');
await page.click('button:near(.form-group)');

// Basado en roles (accesibilidad)
await page.click('role=button[name="Enviar"]');

Ganador: Playwright - motor de selectores más rico con selectores basados en layout y roles.

Comportamiento de Espera Automática

Puppeteer:

// Espera manual a menudo necesaria
await page.waitForSelector('#result');
await page.waitForFunction(() => document.querySelector('#result').textContent !== '');

// Espera de red inactiva
await page.goto('https://example.com', { waitUntil: 'networkidle2' });

// Esperas personalizadas
await page.waitForTimeout(1000);
await page.waitForFunction(
    () => window.appReady === true,
    { timeout: 5000 }
);

Playwright:

// Espera automática incorporada
await page.click('#result');  // Espera elemento automáticamente

// Auto-espera por:
// - Elemento visible
// - Elemento estable (sin animar)
// - Elemento habilitado
// - Elemento que reciba eventos

// Aún soporta esperas explícitas
await page.waitForSelector('#result', { state: 'visible' });
await page.waitForLoadState('networkidle');
await page.waitForFunction(() => window.appReady === true);

Ganador: Playwright - espera automática más agresiva e inteligente reduce necesidad de esperas explícitas.

Múltiples Contextos y Ejecución Paralela

Puppeteer:

const browser = await puppeteer.launch();

// Contextos incógnito
const context1 = await browser.createIncognitoBrowserContext();
const context2 = await browser.createIncognitoBrowserContext();

const page1 = await context1.newPage();
const page2 = await context2.newPage();

await Promise.all([
    page1.goto('https://example.com'),
    page2.goto('https://example.com')
]);

// Almacenamiento, cookies, sesiones aisladas

Playwright:

const browser = await chromium.launch();

// Contextos de navegador (como incógnito)
const context1 = await browser.newContext({
    viewport: { width: 1920, height: 1080 },
    userAgent: 'User Agent Personalizado',
    locale: 'es-ES',
    timezoneId: 'Europe/Madrid',
    permissions: ['geolocation']
});

const context2 = await browser.newContext({
    viewport: { width: 375, height: 667 },  // Móvil
    isMobile: true,
    hasTouch: true
});

// Ejecución paralela con diferentes contextos
const [page1, page2] = await Promise.all([
    context1.newPage(),
    context2.newPage()
]);

Ganador: Playwright - más opciones de configuración para contextos, mejor soporte multi-contexto.

Testing Cross-Browser

Consistencia del Navegador

Puppeteer:

  • Chrome/Chromium: Excelente, soporte nativo
  • Firefox: Soportado desde la v23 mediante WebDriver BiDi; algunas funciones de Puppeteer no están disponibles sobre BiDi (lista)
  • Safari: No soportado

Playwright:

const { chromium, firefox, webkit } = require('playwright');

async function testAllBrowsers() {
    for (const browserType of [chromium, firefox, webkit]) {
        const browser = await browserType.launch();
        const page = await browser.newPage();

        await page.goto('https://example.com');
        // Misma API en todos los navegadores
        await page.screenshot({ path: `screenshot-${browserType.name()}.png` });

        await browser.close();
    }
}

Prueba Cross-Browser del Mundo Real:

const { test, expect } = require('@playwright/test');

test.describe('Login cross-browser', () => {
    test('debe hacer login exitosamente', async ({ page, browserName }) => {
        await page.goto('https://example.com/login');
        await page.fill('#username', 'testuser');
        await page.fill('#password', 'password123');
        await page.click('button[type="submit"]');

        await expect(page.locator('.dashboard')).toBeVisible();

        // Aserciones específicas del navegador
        if (browserName === 'webkit') {
            // Verificaciones específicas de Safari
            await expect(page.locator('.webkit-notice')).toBeVisible();
        }
    });
});

Ganador: Playwright - soporte cross-browser comprehensivo y consistente es característica central.

Intercepción de Red y Mocking

Intercepción de Solicitudes

Puppeteer:

await page.setRequestInterception(true);

page.on('request', (request) => {
    if (request.resourceType() === 'image') {
        request.abort();
    } else if (request.url().includes('/api/users')) {
        request.respond({
            status: 200,
            contentType: 'application/json',
            body: JSON.stringify([
                { id: 1, name: 'Usuario de Prueba' }
            ])
        });
    } else {
        request.continue();
    }
});

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

Playwright:

// Intercepción basada en rutas
await page.route('**/*.{png,jpg,jpeg}', route => route.abort());

await page.route('**/api/users', route => {
    route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify([
            { id: 1, name: 'Usuario de Prueba' }
        ])
    });
});

// O modificar solicitudes
await page.route('**/api/**', route => {
    const headers = route.request().headers();
    headers['Authorization'] = 'Bearer fake-token';
    route.continue({ headers });
});

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

Ganador: Playwright - enrutamiento más flexible, grabación HAR incorporada.

Integración con Framework de Testing

Puppeteer con Jest

// jest-puppeteer.config.js
module.exports = {
    launch: {
        headless: true,
        args: ['--no-sandbox']
    },
    browserContext: 'default'
};

// test.spec.js
describe('Prueba de Login', () => {
    beforeAll(async () => {
        await page.goto('https://example.com');
    });

    it('debe mostrar formulario de login', async () => {
        await expect(page).toMatch('Login');
        const title = await page.title();
        expect(title).toBe('Login - Example');
    });

    it('debe hacer login exitosamente', async () => {
        await page.type('#username', 'testuser');
        await page.type('#password', 'password123');
        await page.click('button[type="submit"]');
        await page.waitForSelector('.dashboard');

        const url = page.url();
        expect(url).toContain('/dashboard');
    });
});

Test Runner de Playwright

// playwright.config.js
module.exports = {
    testDir: './tests',
    timeout: 30000,
    retries: 2,
    use: {
        headless: true,
        viewport: { width: 1920, height: 1080 },
        screenshot: 'only-on-failure',
        video: 'retain-on-failure',
        trace: 'on-first-retry'
    },
    projects: [
        { name: 'chromium', use: { browserName: 'chromium' } },
        { name: 'firefox', use: { browserName: 'firefox' } },
        { name: 'webkit', use: { browserName: 'webkit' } }
    ]
};

// test.spec.js
const { test, expect } = require('@playwright/test');

test.describe('Prueba de Login', () => {
    test.beforeEach(async ({ page }) => {
        await page.goto('https://example.com');
    });

    test('debe mostrar formulario de login', async ({ page }) => {
        await expect(page.locator('h1')).toHaveText('Login');
        await expect(page).toHaveTitle('Login - Example');
    });

    test('debe hacer login exitosamente', async ({ page }) => {
        await page.fill('#username', 'testuser');
        await page.fill('#password', 'password123');
        await page.click('button[type="submit"]');

        await expect(page).toHaveURL(/.*dashboard/);
        await expect(page.locator('.dashboard')).toBeVisible();
    });
});

Ganador: Playwright - test runner opinado con aserciones incorporadas, paralelización, reintentos, capturas de pantalla, videos y trazas.

Capacidades de Depuración

Depuración de Puppeteer

// Slowmo
const browser = await puppeteer.launch({
    headless: false,
    slowMo: 100  // Ralentizar por 100ms
});

// Devtools
const browser = await puppeteer.launch({
    headless: false,
    devtools: true
});

// Capturas de pantalla
await page.screenshot({ path: 'screenshot.png', fullPage: true });

// Logs de consola
page.on('console', msg => console.log('LOG DE PÁGINA:', msg.text()));

// Errores de página
page.on('pageerror', error => console.log('ERROR DE PÁGINA:', error.message));

Depuración de Playwright

// Inspector (depuración interactiva)
// Establecer variable de entorno
// PWDEBUG=1 npm test

// O en código
await page.pause();  // Abre inspector

// Trace viewer (depuración de viaje en el tiempo)
const context = await browser.newContext({
    recordVideo: { dir: 'videos/' },
    recordTrace: { dir: 'traces/' }
});

// Ver traza: npx playwright show-trace trace.zip

// Codegen (grabar acciones)
// npx playwright codegen https://example.com

// Modo headed con slomo
const browser = await chromium.launch({
    headless: false,
    slowMo: 1000
});

Ganador: Playwright - trace viewer proporciona depuración de viaje en el tiempo, inspector más pulido.

Tamaño de instalación: Puppeteer vs Playwright

Ninguno de los dos paquetes npm contiene un navegador. El espacio en disco lo ocupan los binarios de los navegadores, y las dos herramientas difieren en qué navegadores descargan y cuándo.

PuppeteerPlaywright
Navegadores descargados por defectoChrome for Testing y chrome-headless-shellChromium, un Chromium headless shell aparte, Firefox y WebKit
Cuándo ocurre la descargaDurante npm i puppeteer (script de instalación)Solo al ejecutar npx playwright install
Tamaño indicado en la documentación oficialChrome for Testing: ~170 MB macOS, ~282 MB Linux, ~280 MB Windows (pptr.dev)Ejemplo en macOS: 281M chromium, 187M firefox, 180M webkit (playwright.dev)
Caché de navegadores por defecto~/.cache/puppeteer~/Library/Caches/ms-playwright (macOS), ~/.cache/ms-playwright (Linux), %USERPROFILE%\AppData\Local\ms-playwright (Windows)
Omitir la descargaPUPPETEER_SKIP_DOWNLOAD, o instalar puppeteer-coreNo ejecutar npx playwright install
Usar un navegador ya instaladochannel: 'chrome' o executablePathchannel: 'chrome' o channel: 'msedge'

Qué descarga Puppeteer

Según la guía de instalación de Puppeteer, al instalar puppeteer se descarga automáticamente una versión reciente de Chrome for Testing (~170 MB en macOS, ~282 MB en Linux, ~280 MB en Windows) y un binario chrome-headless-shell (a partir de la v21.6.0). Los navegadores se guardan por defecto en $HOME/.cache/puppeteer.

  • La descarga puede omitirse sin aviso. La misma guía advierte que los gestores de paquetes que bloquean por defecto los scripts de instalación de dependencias (menciona pnpm, Yarn Berry, Bun y Deno) omiten la descarga del navegador, y Puppeteer falla después con Could not find Chrome. Ejecuta npx puppeteer browsers install para descargar el navegador manualmente.
  • Omitirla a propósito. Define PUPPETEER_SKIP_DOWNLOAD (o skipDownload en el archivo de configuración), o instala puppeteer-core, que no descarga Chrome al instalarse. La ubicación de la caché se cambia con PUPPETEER_CACHE_DIR o cacheDirectory (referencia de configuración).
  • Chrome del sistema. Con puppeteer-core se pasa executablePath, o channel, que hace que Puppeteer busque una instalación normal de Chrome en una ubicación conocida del sistema (LaunchOptions).
  • Firefox es opcional. Firefox tiene skipDownload: true por defecto; actívalo en el archivo de configuración y ejecuta npx puppeteer browsers install (guía de configuración).
npm i puppeteer                               # paquete + Chrome for Testing + chrome-headless-shell
PUPPETEER_SKIP_DOWNLOAD=true npm i puppeteer  # solo el paquete, sin descargar navegador
npm i puppeteer-core                          # solo la librería, nunca descarga un navegador
npx puppeteer browsers install                # descargar los navegadores manualmente
// puppeteer-core con el Chrome ya instalado en la máquina
const puppeteer = require('puppeteer-core');
const browser = await puppeteer.launch({ channel: 'chrome' });

Qué descarga Playwright

npm i -D playwright instala solo la librería. La documentación de la librería Playwright indica que además hay que instalar los navegadores, ya sea con npx playwright install o añadiendo los paquetes auxiliares @playwright/browser-chromium, @playwright/browser-firefox y @playwright/browser-webkit, que descargan un navegador durante npm install.

Según la guía de navegadores, ejecutar npx playwright install sin argumentos instala los navegadores por defecto. Playwright descarga Chromium, WebKit y Firefox en una carpeta de caché específica del sistema operativo, e incluye un Chromium headless shell aparte para el modo headless. La guía señala que estos navegadores ocupan «unos cientos de megabytes» de disco y muestra este ejemplo en macOS: 281M para chromium, 187M para firefox, 180M para webkit.

  • Instalar menos. npx playwright install chromium descarga un solo navegador. --only-shell omite el Chromium completo cuando solo se ejecuta en headless, y --no-shell omite el headless shell.
  • Chrome o Edge del sistema. Playwright puede trabajar con Google Chrome y Microsoft Edge ya disponibles en la máquina mediante la opción channel; no los instala por defecto.
  • Ubicación de la caché. PLAYWRIGHT_BROWSERS_PATH mueve la caché; PLAYWRIGHT_BROWSERS_PATH=0 coloca los binarios en node_modules/playwright-core/.local-browsers.
  • Limpieza. Playwright elimina las versiones de navegadores que ninguna instalación de Playwright necesita ya; npx playwright uninstall borra los navegadores de la instalación actual.
  • Vista previa sin descargar. npx playwright install --dry-run no ejecuta la instalación y solo imprime información: cada navegador, su ubicación de instalación y la URL de descarga. La opción está definida en el código fuente de la CLI de Playwright. No imprime tamaños.
npm i -D playwright                       # solo la librería, sin navegadores
npx playwright install                    # navegadores por defecto: Chromium, Firefox, WebKit
npx playwright install chromium           # un solo navegador
npx playwright install --only-shell       # solo Chromium headless shell, sin Chromium completo
npx playwright install --no-shell         # omitir el Chromium headless shell
npx playwright install --dry-run          # muestra qué se instalaría, no descarga nada
npx playwright install --list             # lista los navegadores de todas las instalaciones de Playwright
npx playwright uninstall                  # elimina los navegadores de la instalación actual
// Google Chrome ya instalado en la máquina
const { chromium } = require('playwright');
const browser = await chromium.launch({ channel: 'chrome' });   // o 'msedge'

Cómo medirlo en tu máquina

Las cifras anteriores son ejemplos de la documentación, y las compilaciones de los navegadores cambian con cada versión. Para una configuración solo con Chromium, las cifras documentadas están en el mismo rango en ambas herramientas; el espacio de Playwright crece al añadir Firefox y WebKit. Para obtener los números reales de tu sistema operativo y tus versiones:

du -sh ~/.cache/puppeteer/*                 # navegadores de Puppeteer (caché por defecto)
du -hs ~/Library/Caches/ms-playwright/*     # navegadores de Playwright, macOS
du -hs ~/.cache/ms-playwright/*             # navegadores de Playwright, Linux
du -sh node_modules                         # solo los paquetes npm (las cachés por defecto están fuera de node_modules)
npx playwright install --dry-run            # qué descargaría Playwright y dónde

Capturas de pantalla desde Node.js y la CLI

Ambas librerías toman capturas con page.screenshot(). La diferencia está en la línea de comandos: Playwright tiene un comando screenshot, Puppeteer no.

Puppeteer (API)

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('https://example.com', { waitUntil: 'networkidle2' });

    await page.screenshot({ path: 'page.png' });                       // viewport visible
    await page.screenshot({ path: 'full.png', fullPage: true });       // página completa con scroll

    const heading = await page.waitForSelector('h1');
    await heading.screenshot({ path: 'h1.png' });                      // un solo elemento

    await browser.close();
})();

Page.screenshot() y ElementHandle.screenshot() se describen en la guía de capturas de Puppeteer; fullPage figura en ScreenshotOptions.

Playwright (API)

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

(async () => {
    const browser = await chromium.launch();
    const page = await browser.newPage();
    await page.goto('https://example.com');

    await page.screenshot({ path: 'page.png' });                       // viewport visible
    await page.screenshot({ path: 'full.png', fullPage: true });       // página completa con scroll
    await page.locator('h1').screenshot({ path: 'h1.png' });           // un solo elemento

    const buffer = await page.screenshot();                            // sin path: devuelve un Buffer

    await browser.close();
})();

Estas llamadas provienen de la guía de capturas de Playwright.

CLI de Playwright: una captura sin escribir un script

# Sintaxis: npx playwright screenshot [options] <url> <filename>
npx playwright screenshot https://example.com example.png

# Página completa con scroll
npx playwright screenshot --full-page https://example.com full.png

# Otro motor de navegador: cr/chromium, ff/firefox, wk/webkit
npx playwright screenshot -b webkit https://example.com webkit.png

# Emulación de dispositivo y esquema de color oscuro
npx playwright screenshot --device "iPhone 11" --color-scheme dark https://example.com mobile.png

# Esperar un elemento y un tiempo (ms) antes de capturar
npx playwright screenshot --wait-for-selector "h1" --wait-for-timeout 1000 https://example.com ready.png

# Todas las opciones
npx playwright screenshot --help

El comando y sus opciones (--full-page, --wait-for-selector, --wait-for-timeout, -b/--browser, --device, --color-scheme) están definidos en el código fuente de la CLI de Playwright, y npx playwright screenshot --help los muestra para la versión instalada. El navegador que utiliza debe estar instalado previamente con npx playwright install.

¿Existe un equivalente en Puppeteer? No. La CLI puppeteer tiene un único comando, puppeteer browsers, que gestiona las descargas de navegadores. Para una captura se escribe un script corto de Node.js como el anterior y se ejecuta con node screenshot.js.

Matriz de Decisión

Elegir Puppeteer Si:

  • ✅ Solo necesitas soporte Chrome/Chromium
  • ✅ Estás construyendo web scrapers
  • ✅ Necesitas automatización ligera
  • ✅ Necesitas generar PDFs o capturas de pantalla
  • ✅ Tienes base de código Puppeteer existente
  • ✅ Prefieres abstracciones mínimas

Elegir Playwright Si:

  • ✅ Necesitas testing cross-browser (Firefox, Safari)
  • ✅ Estás construyendo suites de pruebas E2E
  • ✅ Quieres test runner integrado
  • ✅ Necesitas depuración avanzada (trace viewer)
  • ✅ Quieres espera automática y reintentos
  • ✅ Necesitas emulación móvil/tablet
  • ✅ Estás iniciando un nuevo proyecto

Conclusión

Tanto Puppeteer como Playwright son excelentes herramientas de automatización de navegadores, cada una sobresaliendo en diferentes escenarios. Puppeteer sigue siendo la opción predilecta para web scraping, generación de PDF y automatización específica de Chrome donde su madurez y simplicidad brillan. Playwright, sin embargo, ha emergido como la solución superior para testing E2E comprehensivo, ofreciendo genuino soporte cross-browser, capacidades poderosas de depuración y un framework de testing opinado que aborda puntos de dolor comunes.

Para nuevos proyectos de automatización de pruebas, las ventajas de Playwright—verdadero soporte cross-browser, trace viewer, espera automática y test runner integrado—lo convierten en la opción recomendada. Para scraping, generación de PDF o automatización solo de Chrome, el enfoque ligero y ecosistema maduro de Puppeteer siguen siendo convincentes.

La buena noticia: migrar entre ellos es relativamente sencillo debido a similitudes de API, permitiendo a los equipos cambiar según evolucionan las necesidades.

Recursos Oficiales

See Also