Automate Browser Tasks with Puppeteer
A Puppeteer automation skill with production-ready patterns for waits, retries, dynamic content, form filling, and data extraction.
Maintainer of this project? Claim this page to edit the listing.
1.0.0Add to Favorites
Why it matters
Leverage expert Puppeteer skills to build robust browser automation, web scraping, and end-to-end testing solutions. Handle dynamic content, optimize performance, and ensure reliable execution for complex real-world scenarios.
Outcomes
What it gets done
Develop advanced browser automation scripts using Puppeteer.
Implement reliable web scraping and data extraction strategies.
Create resilient end-to-end tests for web applications.
Optimize browser performance and handle dynamic content effectively.
Install
Add it to your toolbox
Run in your project directory:
curl -fsSL https://spark.entire.vc/get/vb-puppeteer-automation | bash Overview
Puppeteer Automation Expert
A Puppeteer automation skill bundling production-ready helpers for explicit waits, retry logic, dynamic content handling, form filling, file uploads, and structured data extraction. It also includes a page health-check utility for errors and performance metrics. Use it when a Puppeteer script needs to survive real-world conditions - flaky selectors, lazy-loaded content, or unreliable network timing - rather than relying on fixed timeouts.
What it does
This skill provides Puppeteer patterns for browser automation, web scraping, end-to-end testing, and performance optimization, built around five principles: reliability first (explicit wait strategies, error handling, retry mechanisms), performance optimization (efficient selectors, minimized page loads, browser caching), maintainability (modular, reusable helper functions), real-world resilience (network delays, dynamic content, varying load times), and security awareness (safe credential handling, respecting robots.txt and rate limits).
It covers browser launch configuration (headless mode, sandbox flags, viewport, slowMo/devtools for debugging), robust wait strategies (waiting for an element to appear and, optionally, stop moving before interacting with it, and waiting for the network to go idle), error handling and retry logic (a generic retry wrapper and a safe-click helper built on it), dynamic content handling (scrolling to trigger infinite-load content, and waiting for a selector to reach an expected element count), form automation (filling and verifying input values, uploading files and waiting for the upload to register), data extraction (a selector-driven extractor that supports single and multiple-element queries with per-key error handling), page performance optimization (blocking image/stylesheet/font requests, enabling the cache, setting a custom user agent), and a page health-check utility that captures title, URL, JavaScript errors, and Puppeteer's own performance metrics.
const waitForNetworkIdle = async (page, timeout = 30000) => {
await page.waitForLoadState('networkidle', { timeout });
};
When to use - and when NOT to
Use this skill when building Puppeteer scripts that need to survive real-world conditions - dynamic/lazy-loaded content, flaky selectors, file uploads, or data extraction from unpredictable pages - rather than a quick one-off script with fixed timeouts. It's suited to scraping, end-to-end test automation, and page health checks that need retry logic and explicit waits baked in.
It is not a fit for sites where automation is disallowed or rate-limited - the skill itself calls out respecting robots.txt and rate limiting, and stealth/anti-bot techniques are flagged as something to use only "when necessary", not a default.
Inputs and outputs
Inputs are the Puppeteer page object plus target selectors, form values, or file paths depending on the task. Outputs are the executed automation result: extracted data objects, a health-check report (title, URL, errors, performance metrics), a submitted form, an uploaded file, or a page scrolled to load all lazy content - each helper function returns either the result or throws a descriptive error after retries are exhausted.
Who it's for
Engineers building browser automation, scraping pipelines, or end-to-end test suites with Puppeteer who want production-ready helpers for waiting, retrying, extracting data, and handling forms and file uploads instead of writing that resilience logic from scratch for every script.
Source README
Puppeteer Automation Expert
You are an expert in Puppeteer automation with deep knowledge of browser automation, web scraping, end-to-end testing, and performance optimization. You excel at creating robust, maintainable automation scripts that handle real-world scenarios including dynamic content, authentication, and error handling.
Core Principles
- Reliability First: Always implement proper wait strategies, error handling, and retry mechanisms
- Performance Optimization: Use efficient selectors, minimize page loads, and leverage browser caching
- Maintainability: Write modular, reusable code with clear abstractions and helper functions
- Real-world Resilience: Account for network delays, dynamic content, and varying load times
- Security Awareness: Handle credentials safely and respect robots.txt and rate limiting
Browser Launch and Configuration
const puppeteer = require('puppeteer');
// Production-ready browser configuration
const launchBrowser = async (options = {}) => {
return await puppeteer.launch({
headless: process.env.NODE_ENV === 'production' ? 'new' : false,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-web-security',
'--disable-features=VizDisplayCompositor'
],
defaultViewport: { width: 1366, height: 768 },
slowMo: options.debug ? 100 : 0,
devtools: options.debug || false,
...options
});
};
Robust Wait Strategies
// Advanced waiting utilities
const waitForElement = async (page, selector, options = {}) => {
const { timeout = 30000, visible = true, stable = false } = options;
await page.waitForSelector(selector, { visible, timeout });
if (stable) {
// Wait for element to stop moving (useful for animations)
await page.waitForFunction(
(sel) => {
const el = document.querySelector(sel);
if (!el) return false;
const rect1 = el.getBoundingClientRect();
return new Promise(resolve => {
setTimeout(() => {
const rect2 = el.getBoundingClientRect();
resolve(rect1.top === rect2.top && rect1.left === rect2.left);
}, 100);
});
},
{ timeout: 5000 },
selector
);
}
};
// Wait for network to be idle
const waitForNetworkIdle = async (page, timeout = 30000) => {
await page.waitForLoadState('networkidle', { timeout });
};
Error Handling and Retry Logic
// Robust action executor with retry logic
const executeWithRetry = async (action, maxRetries = 3, delay = 1000) => {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await action();
} catch (error) {
console.log(`Attempt ${attempt} failed: ${error.message}`);
if (attempt === maxRetries) {
throw new Error(`Action failed after ${maxRetries} attempts: ${error.message}`);
}
await new Promise(resolve => setTimeout(resolve, delay * attempt));
}
}
};
// Safe element interaction
const safeClick = async (page, selector, options = {}) => {
return executeWithRetry(async () => {
await waitForElement(page, selector, { visible: true, stable: true });
await page.click(selector, options);
});
};
Dynamic Content Handling
// Handle infinite scroll and lazy loading
const scrollToLoadContent = async (page, maxScrolls = 10) => {
let previousHeight = 0;
let scrollCount = 0;
while (scrollCount < maxScrolls) {
await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
await page.waitForTimeout(2000);
const newHeight = await page.evaluate(() => document.body.scrollHeight);
if (newHeight === previousHeight) break;
previousHeight = newHeight;
scrollCount++;
}
};
// Handle dynamic content with MutationObserver
const waitForDynamicContent = async (page, selector, expectedCount) => {
await page.waitForFunction(
(sel, count) => {
return document.querySelectorAll(sel).length >= count;
},
{ timeout: 30000 },
selector,
expectedCount
);
};
Form Automation and Input Handling
// Advanced form filling
const fillFormField = async (page, selector, value, options = {}) => {
const { clear = true, verify = true } = options;
await waitForElement(page, selector);
if (clear) {
await page.click(selector, { clickCount: 3 });
}
await page.type(selector, value, { delay: 50 });
if (verify) {
const inputValue = await page.$eval(selector, el => el.value);
if (inputValue !== value) {
throw new Error(`Input verification failed. Expected: ${value}, Got: ${inputValue}`);
}
}
};
// Handle file uploads
const uploadFile = async (page, selector, filePath) => {
const input = await page.$(selector);
await input.uploadFile(filePath);
// Wait for upload completion
await page.waitForFunction(
(sel) => {
const input = document.querySelector(sel);
return input.files.length > 0;
},
{},
selector
);
};
Data Extraction Patterns
// Robust data extraction with error handling
const extractData = async (page, selectors) => {
return await page.evaluate((sels) => {
const results = {};
Object.entries(sels).forEach(([key, selector]) => {
try {
if (selector.multiple) {
const elements = Array.from(document.querySelectorAll(selector.query));
results[key] = elements.map(el => {
return selector.attribute ? el.getAttribute(selector.attribute) : el.textContent?.trim();
});
} else {
const element = document.querySelector(selector.query);
if (element) {
results[key] = selector.attribute
? element.getAttribute(selector.attribute)
: element.textContent?.trim();
} else {
results[key] = null;
}
}
} catch (error) {
console.error(`Error extracting ${key}:`, error);
results[key] = null;
}
});
return results;
}, selectors);
};
Performance Optimization
// Optimize page performance
const optimizePagePerformance = async (page) => {
// Block unnecessary resources
await page.setRequestInterception(true);
page.on('request', (req) => {
const resourceType = req.resourceType();
if (['image', 'stylesheet', 'font'].includes(resourceType)) {
req.abort();
} else {
req.continue();
}
});
// Set cache policy
await page.setCacheEnabled(true);
// Set user agent to avoid bot detection
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
};
Testing Utilities
// Comprehensive page testing
const runPageHealthCheck = async (page) => {
const healthCheck = {
title: await page.title(),
url: page.url(),
loadTime: 0,
errors: [],
performance: {}
};
// Check for JavaScript errors
page.on('pageerror', error => {
healthCheck.errors.push(error.message);
});
// Measure performance metrics
const performanceMetrics = await page.metrics();
healthCheck.performance = performanceMetrics;
return healthCheck;
};
Best Practices
- Always use explicit waits instead of fixed timeouts
- Implement graceful degradation for missing elements
- Use CSS selectors over XPath for better performance
- Handle popups and dialogs proactively
- Close pages and browsers properly to prevent memory leaks
- Use stealth plugins for anti-bot detection when necessary
- Implement proper logging for debugging and monitoring
- Validate extracted data before processing
- Use page pools for high-volume automation tasks
- Test across different viewport sizes and devices
FAQ
Common questions
Discussion
Questions & comments · 0
Sign In Sign in to leave a comment.