Skill Featured

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.


91
Spark score
out of 100
Status Verified Official
Updated 7 months ago
Version 1.0.0
Models

Add 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

01

Develop advanced browser automation scripts using Puppeteer.

02

Implement reliable web scraping and data extraction strategies.

03

Create resilient end-to-end tests for web applications.

04

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.