puppeteer
Automate browsers and scrape dynamic websites with Puppeteer. Use when a user asks to scrape JavaScript-rendered pages, automate browser interactions, take screenshots of web pages, generate PDFs from URLs, test web UIs, fill out forms programmatically, crawl SPAs, extract data from dynamic sites, automate login flows, or build web scrapers that need a real browser. Covers headless Chrome, page navigation, DOM interaction, network interception, screenshots, PDF generation, and stealth techniques.
What this skill does
# Puppeteer
## Overview
Puppeteer is a Node.js library that controls headless Chrome/Chromium. Unlike HTTP-based scrapers (cheerio, axios), Puppeteer renders JavaScript, executes AJAX calls, and interacts with the page like a real user. Use it for scraping SPAs, automating form submissions, generating screenshots/PDFs, and testing web interfaces. This skill covers page navigation, DOM extraction, form filling, network interception, stealth mode, and integration with data processing pipelines.
## Instructions
### Step 1: Installation
```bash
npm install puppeteer # downloads Chromium (~170MB)
npm install puppeteer-core # no bundled browser (use system Chrome)
# For stealth (anti-bot bypass)
npm install puppeteer-extra puppeteer-extra-plugin-stealth
```
### Step 2: Basic Page Scraping
```javascript
// scrape_page.js — Extract data from a JavaScript-rendered page
import puppeteer from 'puppeteer'
async function scrapePage(url) {
const browser = await puppeteer.launch({
headless: 'new', // modern headless mode
args: ['--no-sandbox'], // required in Docker/CI
})
const page = await browser.newPage()
// Set viewport and user agent for consistent rendering
await page.setViewport({ width: 1920, height: 1080 })
await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36')
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 })
// Extract data from the rendered DOM
const data = await page.evaluate(() => {
const items = []
document.querySelectorAll('.product-card').forEach(card => {
items.push({
title: card.querySelector('h2')?.textContent?.trim(),
price: card.querySelector('.price')?.textContent?.trim(),
image: card.querySelector('img')?.src,
link: card.querySelector('a')?.href,
})
})
return items
})
await browser.close()
return data
}
const products = await scrapePage('https://example.com/products')
console.log(JSON.stringify(products, null, 2))
```
### Step 3: Form Filling and Login
```javascript
// login_and_scrape.js — Log into a site and scrape authenticated content
import puppeteer from 'puppeteer'
async function loginAndScrape(email, password) {
const browser = await puppeteer.launch({ headless: 'new' })
const page = await browser.newPage()
await page.goto('https://example.com/login')
// Fill login form
await page.type('#email', email, { delay: 50 }) // delay simulates typing
await page.type('#password', password, { delay: 50 })
await page.click('button[type="submit"]')
// Wait for navigation after login
await page.waitForNavigation({ waitUntil: 'networkidle2' })
// Now scrape authenticated pages
await page.goto('https://example.com/dashboard')
const dashboardData = await page.evaluate(() => {
return {
username: document.querySelector('.user-name')?.textContent,
stats: document.querySelector('.stats')?.textContent,
}
})
// Save cookies for reuse (skip login next time)
const cookies = await page.cookies()
await fs.writeFile('cookies.json', JSON.stringify(cookies))
await browser.close()
return dashboardData
}
```
### Step 4: Screenshots and PDFs
```javascript
// capture.js — Generate screenshots and PDFs from web pages
import puppeteer from 'puppeteer'
async function captureScreenshot(url, outputPath) {
const browser = await puppeteer.launch({ headless: 'new' })
const page = await browser.newPage()
await page.setViewport({ width: 1920, height: 1080 })
await page.goto(url, { waitUntil: 'networkidle2' })
// Full page screenshot
await page.screenshot({ path: outputPath, fullPage: true, type: 'png' })
// Specific element screenshot
const element = await page.$('.hero-section')
await element.screenshot({ path: 'hero.png' })
// Generate PDF (great for invoices, reports)
await page.pdf({
path: 'page.pdf',
format: 'A4',
printBackground: true,
margin: { top: '1cm', bottom: '1cm', left: '1cm', right: '1cm' },
})
await browser.close()
}
```
### Step 5: Pagination and Crawling
```javascript
// crawl_paginated.js — Scrape all pages of a paginated listing
import puppeteer from 'puppeteer'
async function crawlAllPages(startUrl) {
const browser = await puppeteer.launch({ headless: 'new' })
const page = await browser.newPage()
const allItems = []
let currentUrl = startUrl
while (currentUrl) {
await page.goto(currentUrl, { waitUntil: 'networkidle2' })
// Extract items from current page
const items = await page.evaluate(() => {
return Array.from(document.querySelectorAll('.item')).map(el => ({
title: el.querySelector('.title')?.textContent?.trim(),
url: el.querySelector('a')?.href,
}))
})
allItems.push(...items)
console.log(`Page scraped: ${items.length} items (total: ${allItems.length})`)
// Find next page link
currentUrl = await page.evaluate(() => {
const next = document.querySelector('a.next-page')
return next?.href || null
})
// Polite delay between pages
await new Promise(r => setTimeout(r, 2000))
}
await browser.close()
return allItems
}
```
### Step 6: Network Interception
```javascript
// intercept.js — Block images/ads for faster scraping, capture API responses
import puppeteer from 'puppeteer'
async function scrapeWithInterception(url) {
const browser = await puppeteer.launch({ headless: 'new' })
const page = await browser.newPage()
// Block images, fonts, stylesheets for faster loading
await page.setRequestInterception(true)
page.on('request', req => {
if (['image', 'font', 'stylesheet'].includes(req.resourceType())) {
req.abort()
} else {
req.continue()
}
})
// Capture API responses (often easier than parsing DOM)
const apiData = []
page.on('response', async response => {
if (response.url().includes('/api/products')) {
const json = await response.json().catch(() => null)
if (json) apiData.push(json)
}
})
await page.goto(url, { waitUntil: 'networkidle2' })
await browser.close()
return apiData
}
```
### Step 7: Stealth Mode
```javascript
// stealth_scrape.js — Bypass bot detection with puppeteer-extra-plugin-stealth
import puppeteer from 'puppeteer-extra'
import StealthPlugin from 'puppeteer-extra-plugin-stealth'
puppeteer.use(StealthPlugin())
async function stealthScrape(url) {
const browser = await puppeteer.launch({
headless: 'new',
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-blink-features=AutomationControlled',
],
})
const page = await browser.newPage()
// Randomize viewport slightly
await page.setViewport({
width: 1920 + Math.floor(Math.random() * 100),
height: 1080 + Math.floor(Math.random() * 100),
})
await page.goto(url, { waitUntil: 'networkidle2' })
const content = await page.content()
await browser.close()
return content
}
```
## Examples
### Example 1: Scrape product prices from a JavaScript-heavy e-commerce site
**User prompt:** "I need to monitor competitor prices on a site that loads products via JavaScript. Extract product names, prices, and availability from all category pages."
The agent will:
1. Launch Puppeteer with stealth plugin to avoid bot detection.
2. Navigate to each category page, wait for product cards to render.
3. Use `page.evaluate()` to extract structured data from the DOM.
4. Handle pagination by clicking "next page" buttons or scrolling for infinite scroll.
5. Save results to JSON with timestamps for price tracking over time.
### Example 2: Generate PDF reports from a web dashboard
**User prompt:** "Log into our analytics dashboard every Monday morning and generate a PDF report of the weekly stats."
The agent will:
1. Launch Puppeteer, navigate to the login page, fill credentials.
2. Navigate to the weekly report view.
3. Wait for all charts and data to load (`waitForSRelated in Writing & Docs
jax-development
IncludedUse this skill when the user is writing, debugging, profiling, refactoring, reviewing, benchmarking, parallelising, exporting, or explaining JAX code, or when they mention JAX, jax.numpy, jit, grad, value_and_grad, vmap, scan, lax, random keys, pytrees, jax.Array, sharding, Mesh, PartitionSpec, NamedSharding, pmap, shard_map, Pallas, XLA, StableHLO, checkify, profiler, or the JAX repo. It helps turn NumPy or PyTorch-style code into pure functional JAX, fix tracer/control-flow/shape/PRNG bugs, remove recompiles and host-device syncs, choose transforms and sharding strategies, inspect jaxpr/lowering/IR, and benchmark compiled code correctly.
nature-article-writer
IncludedDrafts, rewrites, diagnostically critiques, and style-calibrates primary research manuscripts for Nature and Nature Portfolio journals. Use when the user wants a Nature-style title, summary paragraph or abstract, introduction, results, discussion, methods, figure legends, presubmission enquiry, cover letter, reviewer response, or when a scientific draft sounds generic, jargon-heavy, structurally weak, or AI-ish and needs precise, broad-reader-friendly prose without inventing data, analyses, or references. Best for primary research articles and letters rather than reviews or press releases unless explicitly adapting one.
deckrd
IncludedDocument-driven framework that derives requirements, specifications, implementation plans, and executable tasks from goals through structured AI dialogue. Use when user says "write requirements", "create spec", "plan implementation", "derive tasks", "structure this feature", "break down into tasks", or "document this module". Also use for reverse engineering existing code into docs (/deckrd rev). Do NOT use for direct code writing — use /deckrd-coder after tasks are generated. Do NOT use when the user only wants to run or fix existing code without planning.
clinical-decision-support
IncludedGenerate professional clinical decision support (CDS) documents for pharmaceutical and clinical research settings, including patient cohort analyses (biomarker-stratified with outcomes) and treatment recommendation reports (evidence-based guidelines with decision algorithms). Supports GRADE evidence grading, statistical analysis (hazard ratios, survival curves, waterfall plots), biomarker integration, and regulatory compliance. Outputs publication-ready LaTeX/PDF format optimized for drug development, clinical research, and evidence synthesis.
handling-sf-data
IncludedSalesforce data operations with 130-point scoring. Use this skill to create, update, delete, bulk import/export, generate test data, and clean up org records using sf CLI and anonymous Apex. TRIGGER when: user creates test data, performs bulk import/export, uses sf data CLI commands, needs data factory patterns for Apex tests, or needs to seed/clean records in a Salesforce org. DO NOT TRIGGER when: SOQL query writing only (use querying-soql), Apex test execution (use running-apex-tests), or metadata deployment (use deploying-metadata).
accelint-ac-to-playwright
IncludedConvert and validate acceptance criteria for Playwright test automation. Use when user asks to (1) review/evaluate/check if AC are ready for automation, (2) assess if AC can be converted as-is, (3) validate AC quality for Playwright, (4) turn AC into tests, (5) generate tests from acceptance criteria, (6) convert .md bullets or .feature Gherkin files to Playwright specs, (7) create test automation from requirements. Handles both bullet-style markdown and Gherkin syntax with JSON test plan generation and validation.