Authors browser automation scripts using Puppeteer - Chrome / Chromium-only headless / headed automation, Page object via `page.*` API, network interception, PDF generation, screenshot capture, scraping. Distinct from Playwright (Puppeteer's older sibling, Chrome-only) - use Puppeteer for Chrome-only browser automation tasks (scraping, generating PDFs from HTML, screenshot pipelines) where Playwright's multi-browser support is unneeded overhead. Use when a project already depends on `puppeteer` / `puppeteer-core`, or when a Chrome-only script must emit PDFs, screenshots, or scraped data rather than assert on a page.
79
99%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
High
Do not use without reviewing
Specialized page.* recipes beyond the core automation and E2E spine in
SKILL.md. Each drives Chrome / Chromium over the DevTools
Protocol and runs as a standalone script or test body.
Stub third-party APIs or mock responses in tests:
await page.setRequestInterception(true);
page.on('request', request => {
if (request.url().includes('/api/orders')) {
request.respond({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ orderId: 'TEST-1234', total: 24.99 }),
});
} else {
request.continue();
}
});Common production use: server-side PDF from an HTML template.
import puppeteer from 'puppeteer';
(async () => {
const browser = await puppeteer.launch({ headless: 'new' });
const page = await browser.newPage();
await page.goto('https://example.com/invoice/123');
await page.pdf({
path: 'invoice-123.pdf',
format: 'A4',
margin: { top: '20mm', bottom: '20mm', left: '15mm', right: '15mm' },
printBackground: true,
});
await browser.close();
})();Capture one page at multiple viewports:
const viewports = [
{ name: 'mobile', width: 375, height: 667 },
{ name: 'tablet', width: 768, height: 1024 },
{ name: 'desktop', width: 1280, height: 720 },
];
for (const vp of viewports) {
await page.setViewport(vp);
await page.goto('https://example.com');
await page.screenshot({ path: `screenshots/${vp.name}.png`, fullPage: true });
}Extract structured data with $$eval:
await page.goto('https://example.com/products');
const products = await page.$$eval('.product-card', cards =>
cards.map(card => ({
name: card.querySelector('.product-name')?.textContent.trim(),
price: card.querySelector('.product-price')?.textContent.trim(),
url: card.querySelector('a')?.href,
}))
);
console.log(products);