Install
openclaw skills install puppeteer-1-0-0Automate Chrome and Chromium with Puppeteer for scraping, testing, screenshots, and browser workflows.
openclaw skills install puppeteer-1-0-0On 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 | setup.md |
| Memory template | memory-template.md |
| Selectors guide | selectors.md |
| Waiting patterns | waiting.md |
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 sync