Back to Skills
antigravityDocument Processing

browser-automation

Browser automation powers web testing, scraping, and AI agent interactions. The difference between a flaky script and a reliable system comes down to understanding selectors, waiting strategies, and anti-detection patterns.

Documentation

Browser Automation

Browser automation powers web testing, scraping, and AI agent interactions. The difference between a flaky script and a reliable system comes down to understanding selectors, waiting strategies, and anti-detection patterns.

This skill covers Playwright (recommended) and Puppeteer, with patterns for testing, scraping, and agentic browser control. Key insight: Playwright won the framework war. Unless you need Puppeteer's stealth ecosystem or are Chrome-only, Playwright is the better choice in 2025.

Critical distinction: Testing automation (predictable apps you control) vs scraping/agent automation (unpredictable sites that fight back). Different problems, different solutions.

Principles

  • Use user-facing locators (getByRole, getByText) over CSS/XPath
  • Never add manual waits - Playwright's auto-wait handles it
  • Each test/task should be fully isolated with fresh context
  • Screenshots and traces are your debugging lifeline
  • Headless for CI, headed for debugging
  • Anti-detection is cat-and-mouse - stay current or get blocked

Capabilities

  • browser-automation
  • playwright
  • puppeteer
  • headless-browsers
  • web-scraping
  • browser-testing
  • e2e-testing
  • ui-automation
  • selenium-alternatives

Scope

  • api-testing → backend
  • load-testing → performance-thinker
  • accessibility-testing → accessibility-specialist
  • visual-regression-testing → ui-design

Tooling

Frameworks

  • Playwright - When: Default choice - cross-browser, auto-waiting, best DX Note: 96% success rate, 4.5s avg execution, Microsoft-backed
  • Puppeteer - When: Chrome-only, need stealth plugins, existing codebase Note: 75% success rate at scale, but best stealth ecosystem
  • Selenium - When: Legacy systems, specific language bindings Note: Slower, more verbose, but widest browser support

Stealth_tools

  • puppeteer-extra-plugin-stealth - When: Need to bypass bot detection with Puppeteer Note: Gold standard for anti-detection
  • playwright-extra - When: Stealth plugins for Playwright Note: Port of puppeteer-extra ecosystem
  • undetected-chromedriver - When: Selenium anti-detection Note: Dynamic bypass of detection

Cloud_browsers

  • Browserbase - When: Managed headless infrastructure Note: Built-in stealth mode, session management
  • BrowserStack - When: Cross-browser testing at scale Note: Real devices, CI integration

Patterns

Test Isolation Pattern

Each test runs in complete isolation with fresh state

When to use: Testing, any automation that needs reproducibility

TEST ISOLATION:

""" Each test gets its own:

  • Browser context (cookies, storage)
  • Fresh page
  • Clean state """

Playwright Test Example

""" import { test, expect } from '@playwright/test';

// Each test runs in isolated browser context test('user can add item to cart', async ({ page }) => { // Fresh context - no cookies, no storage from other tests await page.goto('/products'); await page.getByRole('button', { name: 'Add to Cart' }).click(); await expect(page.getByTestId('cart-count')).toHaveText('1'); });

test('user can remove item from cart', async ({ page }) => { // Completely isolated - cart is empty await page.goto('/cart'); await expect(page.getByText('Your cart is empty')).toBeVisible(); }); """

Shared Authentication Pattern

""" // Save auth state once, reuse across tests // setup.ts import { test as setup } from '@playwright/test';

setup('authenticate', async ({ page }) => { await page.goto('/login'); await page.getByLabel('Email').fill('user@example.com'); await page.getByLabel('Password').fill('password'); await page.getByRole('button', { name: 'Sign in' }).click();

// Wait for auth to complete await page.waitForURL('/dashboard');

// Save authentication state await page.context().storageState({ path: './playwright/.auth/user.json' }); });

// playwright.config.ts export default defineConfig({ projects: [ { name: 'setup', testMatch: /.*.setup.ts/ }, { name: 'tests', dependencies: ['setup'], use: { storageState: './playwright/.auth/user.json', }, }, ], }); """

User-Facing Locator Pattern

Select elements the way users see them

When to use: Always - the default approach for selectors

USER-FACING LOCATORS:

""" Priority order:

  1. getByRole - Best: matches accessibility tree
  2. getByText - Good: matches visible content
  3. getByLabel - Good: matches form labels
  4. getByTestId - Fallback: explicit test contracts
  5. CSS/XPath - Last resort: fragile, avoid """

Good Examples (User-Facing)

""" // By role - THE BEST CHOICE await page.getByRole('button', { name: 'Submit' }).click(); await page.getByRole('link', { name: 'Sign up' }).click(); await page.getByRole('heading', { name: 'Dashboard' }).isVisible(); await page.getByRole('textbox', { name: 'Search' }).fill('query');

// By text content await page.getByText('Welcome back').isVisible(); await page.getByText(/Order #\d+/).click(); // Regex supported

// By l

Use Cases

  • User mentions or implies: playwright
  • User mentions or implies: puppeteer
  • User mentions or implies: browser automation
  • User mentions or implies: headless
  • User mentions or implies: web scraping