Puppeteer
Automate Chrome and Chromium with Puppeteer for scraping, testing, screenshots, and browser workflows.
Automate Chrome and Chromium with Puppeteer for scraping, testing, screenshots, and browser workflows.
Real data. Real impact.
Emerging
Developers
Per week
Open source
Skills give you superpowers. Install in 30 seconds.
On first use, read
setup.md for integration guidelines.
User needs browser automation: web scraping, E2E testing, PDF generation, screenshots, or any headless Chrome task. Agent handles page navigation, element interaction, waiting strategies, and data extraction.
Scripts and outputs in
~/puppeteer/. See memory-template.md for structure.
~/puppeteer/ ├── memory.md # Status + preferences ├── scripts/ # Reusable automation scripts └── output/ # Screenshots, PDFs, scraped data
| Topic | File |
|---|---|
| Setup process | |
| Memory template | |
| Selectors guide | |
| Waiting patterns | |
Never click or type immediately after navigation. Always wait for the element:
await page.waitForSelector('#button'); await page.click('#button');
Clicking without waiting causes "element not found" errors 90% of the time.
Prefer stable selectors in this order:
[data-testid="submit"] — test attributes (most stable)#unique-id — IDsform button[type="submit"] — semantic combinations.class-name — classes (least stable, changes often)Avoid:
div > div > div > button — breaks on any DOM change.
After clicks that navigate, wait for navigation:
await Promise.all([ page.waitForNavigation(), page.click('a.next-page') ]);
Without this, the script continues before the new page loads.
Always set viewport for consistent rendering:
await page.setViewport({ width: 1280, height: 800 });
Default viewport is 800x600 — many sites render differently or show mobile views.
Dismiss dialogs before they block interaction:
page.on('dialog', async dialog => { await dialog.dismiss(); // or dialog.accept() });
Unhandled dialogs freeze the script.
Always wrap in try/finally:
const browser = await puppeteer.launch(); try { // ... automation code } finally { await browser.close(); }
Leaked browser processes consume memory and ports.
Add delays between requests to avoid blocks:
await page.waitForTimeout(1000 + Math.random() * 2000);
Hammering sites triggers CAPTCHAs and IP bans.
page.click() on invisible element → fails silently, use waitForSelector with visible: truepage.evaluate() returns undefined → cannot return DOM nodes, only serializable dataheadless: 'new' or set user agentpage.waitForNavigation() or data is lostpage.evaluateHandle() to pierce shadow rootsuserDataDir for session persistenceData that stays local:
This skill does NOT:
Install with
clawhub install <slug> if user confirms:
playwright — Cross-browser automation alternativechrome — Chrome DevTools and debuggingweb — General web developmentclawhub star puppeteerclawhub syncNo automatic installation available. Please visit the source repository for installation instructions.
View Installation Instructions1,500+ AI skills, agents & workflows. Install in 30 seconds. Part of the Torly.ai family.
© 2026 Torly.ai. All rights reserved.