Doramagic Project Pack · Human Manual

puppeteer

Puppeteer is a Node.js library that provides a high-level API to control Chrome, Firefox, or other browsers via the DevTools Protocol and WebDriver BiDi. It enables developers to automate ...

Getting Started

Related topics: System Architecture

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Prerequisites

Continue reading this section for the full explanation and source context.

Section System Requirements by Browser

Continue reading this section for the full explanation and source context.

Section Installing Puppeteer

Continue reading this section for the full explanation and source context.

Related topics: System Architecture

Getting Started

Overview

Puppeteer is a Node.js library that provides a high-level API to control Chrome, Firefox, or other browsers via the DevTools Protocol and WebDriver BiDi. It enables developers to automate browser tasks programmatically, including web scraping, page interactions, performance monitoring, and automated testing.

This guide covers the essential steps to install, configure, and run your first Puppeteer script.

Installation

Prerequisites

RequirementDetails
Node.jsCompatible version specified in package.json engines field
Package Managernpm, yarn, or pnpm
System DependenciesOS-specific tools (see below)

System Requirements by Browser

For Firefox downloads:

  • Linux builds: xz and bzip2 utilities required for .tar.gz and .tar.bz2 archives
  • MacOS builds: hdiutil required for .dmg archives

For Chrome downloads:

Installing Puppeteer

There are two primary packages available:

# Full package - downloads compatible Chrome during installation
npm i puppeteer

# Core package - library only, without downloading Chrome
npm i puppeteer-core

When installing puppeteer, the installation script (install.mjs) automatically downloads a compatible Chrome binary for your platform. The puppeteer-core package is designed for scenarios where you already have a browser installation or want to use a custom browser path.

Using Alternative Package Managers

Puppeteer supports installation via different package managers:

# Using npm
npm i puppeteer

# Using yarn
yarn add puppeteer

# Using pnpm
pnpm add puppeteer

Quick Start Example

The following example demonstrates a complete workflow: launching a browser, navigating to a page, interacting with elements, and extracting data.

import puppeteer from 'puppeteer';
// Or import puppeteer from 'puppeteer-core';

// Launch the browser and open a new blank page
const browser = await puppeteer.launch();
const page = await browser.newPage();

// Navigate the page to a URL
await page.goto('https://developer.chrome.com/');

// Set the screen size
await page.setViewport({width: 1080, height: 1024});

// Open the search menu using the keyboard
await page.keyboard.press('/');

// Type into search box using accessible input name
await page.locator('::-p-aria(Search)').fill('automate beyond recorder');

// Wait and click on first result
await page.locator('.devsite-result-item-link').click();

// Locate the full title with a unique string
const textSelector = await page
  .locator('::-p-text(Customize and automate)')
  .waitHandle();
const fullTitle = await textSelector?.evaluate(el => el.textContent);

// Print the full title
console.log('The title of this blog post is "%s".', fullTitle);

await browser.close();

Sources: README.md:1-40

Browser Launch Configuration

Basic Launch Options

The puppeteer.launch() method accepts a configuration object:

ParameterTypeDefaultDescription
headless`boolean \'new'`trueRun browser in headless mode
executablePathstringauto-detectedPath to browser executable
argsstring[][]Additional CLI arguments
protocolTimeoutnumber30000Protocol timeout in ms

Common Launch Arguments

const browser = await puppeteer.launch({
  headless: false,
  args: [
    '--no-sandbox',      // Required for some container environments
    '--disable-setuid-sandbox',
    '--disable-dev-shm-usage'
  ]
});

Core Concepts

Page Navigation

The page.goto() method navigates to a specified URL:

await page.goto('https://example.com', {
  waitUntil: 'networkidle2'  // Wait until network is idle
});

Viewport Configuration

Control the visible area of the page:

await page.setViewport({
  width: 1920,
  height: 1080,
  deviceScaleFactor: 2     // For high-DPI screenshots
});

Locators

Puppeteer provides a locator-based API for waiting and interacting with elements:

Selector TypeExampleDescription
CSS'div.class-name'Standard CSS selector
Text'::-p-text(Content)'Match by visible text
ARIA'::-p-aria(Role)'Accessible ARIA selector
XPath'::-p-xpath(//div)'XPath expression
Shadow DOMCombined selectorsQuery across shadow roots

Sources: packages/puppeteer-core/src/api/locators/locators.ts:1-50

Evaluating JavaScript in Page Context

Execute code within the browser environment:

// Simple evaluation
const title = await page.evaluate(() => document.title);

// With arguments
const links = await page.evaluate(
  (maxCount) => {
    return Array.from(document.querySelectorAll('a'))
      .slice(0, maxCount)
      .map(a => a.href);
  },
  10  // maxCount argument
);

// Handle evaluation for complex objects
const handle = await page.evaluateHandle(() => document.body);

Sources: packages/puppeteer-core/src/api/Page.ts:1-60

Exposing Functions to the Page

Expose Node.js functions to be called from browser context:

import fs from 'node:fs';

await page.exposeFunction('readfile', async filePath => {
  return new Promise((resolve, reject) => {
    fs.readFile(filePath, 'utf8', (err, text) => {
      if (err) reject(err);
      else resolve(text);
    });
  });
});

// Now callable from page context
await page.evaluate(async () => {
  const content = await window.readfile('/etc/hosts');
  console.log(content);
});

Sources: packages/puppeteer-core/src/api/Page.ts:1-35

Workflow Diagram

graph TD
    A[Start] --> B[Install Puppeteer]
    B --> C[puppeteer.launch]
    C --> D[Create Page]
    D --> E[Configure Viewport]
    E --> F[Navigate to URL]
    F --> G{Interact with Page}
    G -->|Click| H[Locate Element]
    G -->|Type| I[Fill Input]
    G -->|Extract| J[Evaluate JavaScript]
    H --> K[Perform Action]
    I --> K
    J --> L[Extract Data]
    K --> M{More Actions?}
    M -->|Yes| G
    M -->|No| N[Close Browser]
    L --> N

Media Emulation

Emulate Media Types

Test how pages render under different media conditions:

await page.emulateMediaType('print');

// Now matchMedia queries return print styles
await page.evaluate(() => matchMedia('print').matches);  // true

// Reset to default
await page.emulateMediaType(null);

Emulate CSS Media Features

await page.emulateMediaFeatures([
  {name: 'prefers-color-scheme', value: 'dark'},
  {name: 'prefers-color-scheme', value: 'light'}
]);

CPU Throttling

Emulate slow devices for performance testing:

// 2x slowdown
await page.emulateCPUThrottling(2);

// Disable throttling
await page.emulateCPUThrottling(null);

Sources: packages/puppeteer-core/src/api/Page.ts:1-30

Browser Management CLI

The @puppeteer/browsers package provides CLI tools for managing browser installations:

# List installed browsers
npx @puppeteer/browsers list

# Clear all installed browsers
npx @puppeteer/browsers clear

# Install specific versions
npx @puppeteer/browsers install chrome@stable
npx @puppeteer/browsers install chromedriver@116

# Install specific milestone
npx @puppeteer/browsers install chrome@117

Sources: packages/browsers/README.md:1-50

Docker Usage

Puppeteer can be containerized for CI/CD environments:

Building the Image

docker build -t puppeteer-chrome-linux .

Running with Docker

docker run -i --init --rm \
  --cap-add=SYS_ADMIN \
  --name puppeteer-chrome \
  puppeteer-chrome-linux \
  node -e "`cat test/smoke-test.js`"

Note: The --cap-add=SYS_ADMIN capability enables Chrome sandbox for enhanced security. Alternatively, start with --no-sandbox flag.

Sources: docker/README.md:1-30

Debugging

Enable debug logging to troubleshoot issues:

// Enable specific channel
window.__PUPPETEER_DEBUG='Page';

// Enable all channels
window.__PUPPETEER_DEBUG='*';

// Enable pattern matching
window.__PUPPETEER_DEBUG='foo*';  // Matches 'foo', 'foobar', etc.

In Node.js environment:

import {debug} from './common/Debug.js';

const log = debug('Page');
log('new page created');
// Output: "Page: new page created"

Sources: packages/puppeteer-core/src/common/Debug.ts:1-50

MCP Integration

Puppeteer supports the Model Context Protocol for AI-assisted browser automation:

Installation

npm install chrome-devtools-mcp

WebMCP Support

Puppeteer also includes experimental support for the WebMCP API, enabling AI agents to interact with browser automation:

Sources: README.md:1-25

Next Steps

TopicDescription
LocatorsAdvanced element location strategies
SelectorsCSS, text, ARIA, and XPath selectors
Page InteractionsClicking, typing, scrolling
BiDi ProtocolWebDriver BiDi support
Chrome ExtensionsExtension automation
API ReferenceComplete API documentation

Sources: [README.md:1-40]()

System Architecture

Related topics: Package Structure, CDP Implementation, WebDriver BiDi Implementation

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Chrome DevTools Protocol (CDP)

Continue reading this section for the full explanation and source context.

Section WebDriver BiDi Protocol

Continue reading this section for the full explanation and source context.

Section Page Abstraction

Continue reading this section for the full explanation and source context.

Related topics: Package Structure, CDP Implementation, WebDriver BiDi Implementation

System Architecture

Puppeteer is a high-level API that provides a programmatic interface for controlling Chrome/Chromium browsers. The system architecture is designed to abstract browser automation complexities while supporting multiple protocol backends.

Architecture Overview

Puppeteer uses a dual-protocol architecture that supports both Chrome DevTools Protocol (CDP) and WebDriver BiDi (BiDirectional) protocols. This design enables flexibility in browser automation while maintaining a consistent high-level API for users.

graph TD
    subgraph "User Layer"
        User["User Code"]
    end
    
    subgraph "Public API Layer"
        Puppeteer["puppeteer/puppeteer-core"]
        Page["Page API"]
        Browser["Browser API"]
    end
    
    subgraph "Protocol Abstraction Layer"
        CDP["CDP Implementation"]
        BiDi["BiDi Implementation"]
    end
    
    subgraph "Protocol Communication"
        CDP_Protocol["Chrome DevTools Protocol"]
        WebDriver_BiDi["WebDriver BiDi"]
    end
    
    subgraph "Browser Layer"
        Chrome["Chrome/Chromium"]
        Firefox["Firefox"]
    end
    
    User --> Puppeteer
    Puppeteer --> Page
    Puppeteer --> Browser
    Page --> CDP
    Page --> BiDi
    CDP --> CDP_Protocol
    BiDi --> WebDriver_BiDi
    CDP_Protocol --> Chrome
    WebDriver_BiDi --> Chrome
    WebDriver_BiDi --> Firefox

Core Entry Points

The main entry point for Puppeteer is defined in index.ts, which exports all public APIs and types. The system provides two primary packages:

PackagePurposeBrowser Download
puppeteerFull package with bundled ChromeYes (automatic)
puppeteer-coreLibrary-only, no browser downloadNo

Sources: packages/puppeteer-core/src/index.ts

Protocol Implementations

Chrome DevTools Protocol (CDP)

CDP is the native Chrome debugging protocol. The CDP implementation provides direct access to Chrome's debugging features through the CDPSession interface.

Key Components:

ComponentFilePurpose
CDPPuppeteercdp.tsMain entry point for CDP-based browser control
CDPExecutionContextExecutionContext.tsExecutes JavaScript in page context
CDPBrowserContextcdp.tsManages browser contexts via CDP
CDPPagecdp.tsPage implementation using CDP

Sources: packages/puppeteer-core/src/cdp/cdp.ts

CDP Execution Flow:

sequenceDiagram
    participant User as User Code
    participant Page as CDP Page
    participant Context as CDP ExecutionContext
    participant Client as CDPSession
    participant Chrome as Chrome Browser
    
    User->>Page: evaluate(pageFunction)
    Page->>Context: evaluate(pageFunction)
    Context->>Client: send(Runtime.evaluate)
    Client->>Chrome: Runtime.evaluate
    Chrome-->>Client: result
    Client-->>Context: result
    Context-->>Page: HandleFor<T>
    Page-->>User: Awaited<ReturnType<T>>

The CDP implementation evaluates page functions by stringifying them and sending them via Runtime.evaluate or Runtime.callFunctionOn CDP commands. The source URL comment is injected for better debugging support.

Sources: packages/puppeteer-core/src/cdp/ExecutionContext.ts:1-50

WebDriver BiDi Protocol

WebDriver BiDi is a cross-browser protocol specification that provides a standardized bidirectional communication interface.

ComponentFilePurpose
BiDiPuppeteerbidi.tsMain entry point for BiDi-based browser control
RealmRealm.tsBiDi execution environment
BiDiBrowserContextbidi.tsManages browser contexts via BiDi
BiDiPagebidi.tsPage implementation using BiDi

Sources: packages/puppeteer-core/src/bidi/bidi.ts

BiDi Realm Architecture:

The Realm class provides the execution context for BiDi-based browser automation. It includes a lazy-loaded puppeteerUtil that handles internal Puppeteer operations:

class Realm {
    internalPuppeteerUtil?: Promise<BidiJSHandle<PuppeteerInjectedUtil>>;
    
    get puppeteerUtil(): Promise<BidiJSHandle<PuppeteerInjectedUtil>> {
        // Lazy initialization with caching
    }
    
    async evaluateHandle(pageFunction, ...args): Promise<HandleFor<T>>;
    async evaluate(pageFunction, ...args): Promise<Awaited<T>>;
}

Sources: packages/puppeteer-core/src/bidi/Realm.ts:1-60

Abstract API Layer

The API layer defines abstract interfaces that both protocol implementations must fulfill.

Page Abstraction

The Page class is the central abstraction for browser tabs/pages:

classDiagram
    class Page {
        <<abstract>>
        +exposeFunction(name, pptrFunction)
        +$$eval(selector, pageFunction)
        +emulateMediaType(type)
        +emulateCPUThrottling(factor)
        +locator(selector) Locator
        -_isDragging: boolean
        -_timeoutSettings: TimeoutSettings
    }
    
    class CDPPage {
        +exposeFunction(name, pptrFunction)
        +$$eval(selector, pageFunction)
    }
    
    class BiDiPage {
        +exposeFunction(name, pptrFunction)
        +$$eval(selector, pageFunction)
    }
    
    Page <|-- CDPPage
    Page <|-- BiDiPage

Key Page features:

FeatureDescriptionSource
exposeFunctionExposes a function to the page's JavaScript contextPage.ts
$$evalEvaluates a function on matching elementsPage.ts
emulateMediaTypeEmulates CSS media typePage.ts
emulateCPUThrottlingSimulates slow CPUsPage.ts

Locator System

The Locator API provides a modern, promise-based approach to element finding with automatic retry logic.

graph TD
    Locator["Locator<T>"]
    FunctionLocator["FunctionLocator<T>"]
    DelegatedLocator["DelegatedLocator<T, U>"]
    Page["Page"]
    Frame["Frame"]
    
    Page --> Locator
    Frame --> Locator
    Locator <|-- FunctionLocator
    Locator <|-- DelegatedLocator
    DelegatedLocator --> Locator
    
    FunctionLocator: "_func: () => Awaitable<T>"
    DelegatedLocator: "#delegate: Locator<T>"

Locator Types:

TypePurposeKey Methods
Locator<T>Base locator classwait(), map(), filter()
FunctionLocator<T>Locates elements using a predicate functionUses waitForFunction internally
DelegatedLocator<T, U>Wraps another locator with transformationDelegates to another locator

Sources: packages/puppeteer-core/src/api/locators/locators.ts

Event System

Puppeteer uses an event-driven architecture based on EventEmitter:

graph LR
    Page["Page (EventEmitter)"]
    Request["Request Event"]
    Response["Response Event"]
    Console["Console Event"]
    
    Page --> |emit| Request
    Page --> |emit| Response
    Page --> |emit| Console
    
    User1["page.on('request', handler)"]
    User2["page.on('response', handler)"]
    User3["page.on('console', handler)"]
    
    Request --> User1
    Response --> User2
    Console --> User3

The Page class extends EventEmitter<PageEvents> and emits events documented in the PageEvent enum:

page.once('load', () => console.log('Page loaded!'));
page.on('request', logRequest);
page.off('request', logRequest);

Sources: packages/puppeteer-core/src/api/Page.ts:1-100

Lazy Evaluation (LazyArg)

The LazyArg system enables deferred argument evaluation within page context:

graph TD
    User["User Code"]
    Lazy["LazyArg.create(callback)"]
    Context["PuppeteerUtilWrapper"]
    Eval["evaluate()"]
    
    User --> Lazy
    Lazy --> Eval
    Eval --> Context
    Context --> |get| Lazy
class LazyArg<T, Context = PuppeteerUtilWrapper> {
    static create = <T>(
        get: (context: PuppeteerUtilWrapper) => Promise<T> | T
    ): T => {
        return new LazyArg(get) as unknown as T;
    };
    
    async get(context: Context): Promise<T> {
        return await this.#get(context);
    }
}

Sources: packages/puppeteer-core/src/common/LazyArg.ts

Device Emulation

Puppeteer provides pre-configured device profiles for emulation:

import {KnownDevices} from 'puppeteer';
const iPhone = KnownDevices['iPhone 15 Pro'];

const page = await browser.newPage();
await page.emulate(iPhone);
CategoryDevices Included
iPhoneiPhone 4, 5, 6, 7, 8, X, 11, 12, 13, 14, 15 series
iPadVarious iPad models
AndroidNexus, Pixel devices
DesktopChrome, Firefox, Safari viewports

Sources: packages/puppeteer-core/src/common/Device.ts

Debug System

The debug module provides channel-based logging:

const log = debug('Page');
log('new page created');
// Output: "Page: new page created"

Configuration:

Environment VariableEffect
window.__PUPPETEER_DEBUG='*'Enable all logging
window.__PUPPETEER_DEBUG='foo'Log only 'foo' channel
window.__PUPPETEER_DEBUG='foo*'Log all channels starting with 'foo'

Sources: packages/puppeteer-core/src/common/Debug.ts

Architecture Summary

graph TD
    subgraph "User Applications"
        Scripts["Automation Scripts"]
        Tests["Test Frameworks"]
        Scrapers["Web Scrapers"]
    end
    
    subgraph "puppeteer/puppeteer-core"
        API["Public API (Page, Browser, Frame)"]
        Locator["Locator API"]
        Event["Event System"]
    end
    
    subgraph "Protocol Adapters"
        CDP["CDP Adapter"]
        BiDi["BiDi Adapter"]
    end
    
    subgraph "Browser Runtimes"
        Chrome["Chrome/Chromium"]
        Firefox["Firefox"]
        Edge["Edge"]
    end
    
    Scripts --> API
    Tests --> API
    Scrapers --> API
    
    API --> Locator
    API --> Event
    
    API --> CDP
    API --> BiDi
    
    CDP --> Chrome
    CDP --> Edge
    BiDi --> Chrome
    BiDi --> Firefox
    BiDi --> Edge

Key Design Principles

  1. Protocol Abstraction: Both CDP and BiDi provide equivalent functionality through a unified API
  2. Lazy Evaluation: Arguments are evaluated only when needed within the browser context
  3. Event-Driven: Asynchronous operations use observable patterns for extensibility
  4. Device Emulation: Built-in device profiles ensure consistent cross-device testing
  5. Debugging Support: Channel-based logging enables granular troubleshooting

Sources: [packages/puppeteer-core/src/index.ts](https://github.com/puppeteer/puppeteer/blob/main/packages/puppeteer-core/src/index.ts)

Package Structure

Related topics: System Architecture, Browser Launching

Section Related Pages

Continue reading this section for the full explanation and source context.

Section puppeteer-core

Continue reading this section for the full explanation and source context.

Section Browser Launchers (@puppeteer/browsers)

Continue reading this section for the full explanation and source context.

Section Angular Schematics (ng-schematics)

Continue reading this section for the full explanation and source context.

Related topics: System Architecture, Browser Launching

Package Structure

Puppeteer is a comprehensive Node.js library that provides a high-level API to control Chrome, Firefox, and other browsers via the DevTools Protocol. The project is organized as a monorepo containing multiple packages that serve distinct purposes while maintaining a cohesive architecture.

Overview

The Puppeteer repository follows a multi-package architecture designed to separate concerns between browser automation logic, browser launching utilities, and framework-specific integrations.

graph TD
    A[Puppeteer Core] --> B[Browser Launchers]
    A --> C[Page API]
    A --> D[Locator API]
    B --> E[Chrome Driver]
    B --> F[Firefox Driver]
    C --> G[CDP Execution]
    D --> H[Locator Implementations]

Package Organization

The repository contains the following primary packages located in the packages/ directory:

PackagePurposeEntry Point
puppeteerFull Puppeteer distribution with bundled ChromeMain npm package
puppeteer-coreCore library without browser binariessrc/puppeteer-core.ts
@puppeteer/browsersBrowser management CLI and APIpackages/browsers/src/main.ts
ng-schematicsAngular schematics for PuppeteerAngular integration

puppeteer-core

The puppeteer-core package serves as the foundation for all browser automation functionality. It provides the complete API surface for launching browsers, creating pages, and executing automation tasks.

Location: packages/puppeteer-core/

Key Characteristics:

  • Does not download browser binaries during installation
  • Compatible with any browser implementation that supports DevTools Protocol
  • Requires explicit executablePath configuration when not using bundled browsers

Source Files:

FilePurpose
src/puppeteer-core.tsMain entry point, exports primary API
src/puppeteer-core-browser.tsBrowser class implementation
src/api/Page.tsAbstract Page class definition
src/api/locators/locators.tsLocator implementations
src/common/Configuration.tsConfiguration interfaces
src/cdp/ExecutionContext.tsCDP execution context

The package exports key classes including Browser, Page, Frame, Locator, and various configuration types that enable programmatic browser control.

Browser Launchers (`@puppeteer/browsers`)

The @puppeteer/browsers package provides both a CLI interface and programmatic API for managing browser installations. It handles downloading, caching, and launching of browser binaries.

CLI Commands:

CommandDescription
npx @puppeteer/browsers installDownload browser binaries
npx @puppeteer/browsers clearRemove installed browsers
npx @puppeteer/browsers listDisplay installed browsers
npx @puppeteer/browsers launchLaunch a specific browser

Supported Browsers:

  • Chrome for Testing (Stable, Beta, Dev, Canary)
  • ChromeDriver (matching versions)
  • Firefox

Installation Examples:

# Install latest stable Chrome
npx @puppeteer/browsers install chrome@stable

# Install specific version
npx @puppeteer/browsers install [email protected]

# Install latest ChromeDriver for Canary
npx @puppeteer/browsers install chromedriver@canary

Angular Schematics (`ng-schematics`)

The ng-schematics package provides Angular-specific tooling for integrating Puppeteer into Angular projects through the Angular CLI.

Location: packages/ng-schematics/package.json

This package enables Angular developers to scaffold and configure Puppeteer within their applications using standard Angular CLI commands.

Module Architecture

Core API Structure

The Puppeteer Core API is organized hierarchically with clear separation between different functional areas:

graph BT
    A[Browser] --> B[Page]
    A --> C[Target]
    B --> D[Frame]
    B --> E[Locator]
    D --> F[ExecutionContext]
    F --> G[JSHandle]

Key Entry Points

The main entry point packages/puppeteer-core/src/puppeteer-core.ts exports all public APIs:

  • puppeteer.launch() - Launch a browser instance
  • puppeteer.connect() - Connect to an existing browser
  • Browser class - Represents a browser instance
  • Page class - Represents a single page or tab
  • Frame class - Represents an iframe within a page
  • Locator classes - Fluent locator implementations for element queries

The browser-specific entry point packages/puppeteer-core/src/puppeteer-core-browser.ts provides implementation details for browser lifecycle management.

Common Utilities

Several utility modules support the core functionality:

ModuleLocationPurpose
LazyArgsrc/common/LazyArg.tsDeferred argument evaluation for page functions
Devicesrc/common/Device.tsPredefined device descriptors for emulation
Debugsrc/common/Debug.tsDebug logging infrastructure
Configurationsrc/common/Configuration.tsGlobal and per-browser configuration

Launch Options

Browser launch behavior is configured through LaunchOptions interface in packages/puppeteer-core/src/node/LaunchOptions.ts:

OptionTypeDefaultDescription
executablePathstringbundledPath to browser executable
ignoreDefaultArgs`boolean \string[]`falseSkip default arguments
enableExtensions`boolean \string[]`-Enable browser extensions
handleSIGINTbooleantrueClose on Ctrl+C
handleSIGTERMbooleantrueClose on SIGTERM
handleSIGHUPbooleantrueClose on SIGHUP
timeoutnumber30000Startup timeout in ms

Directory Structure

puppeteer/
├── packages/
│   ├── puppeteer-core/
│   │   ├── src/
│   │   │   ├── api/          # Public API definitions
│   │   │   │   ├── Page.ts
│   │   │   │   └── locators/
│   │   │   ├── cdp/          # CDP-specific implementations
│   │   │   ├── common/       # Shared utilities
│   │   │   ├── injected/     # Injected scripts
│   │   │   └── node/         # Node.js specific code
│   │   └── package.json
│   ├── browsers/
│   │   ├── src/
│   │   │   └── main.ts       # CLI entry point
│   │   └── README.md
│   └── ng-schematics/
├── examples/                  # Official usage examples
├── website/                   # Documentation site
├── docker/                    # Docker configuration
└── tools/                     # Development tools

Configuration System

Global Configuration

Configuration is defined through ChromeSettings, FirefoxSettings, and related interfaces in Configuration.ts:

interface ChromeSettings {
  skipDownload?: boolean;
  // URL prefix for browser downloads
}

Environment Variable Overrides

VariableConfiguration Property
PUPPETEER_SKIP_DOWNLOADskipDownload
PUPPETEER_TMP_DIRtemporaryDirectory
PUPPETEER_CHROME_SKIP_DOWNLOADchrome.skipDownload
PUPPETEER_CHROME_DOWNLOAD_BASE_URLchrome.downloadBaseUrl

Integration Patterns

Direct Usage (puppeteer-core)

import puppeteer from 'puppeteer-core';

const browser = await puppeteer.launch({
  executablePath: '/path/to/browser'
});

Full Distribution (puppeteer)

import puppeteer from 'puppeteer';
// Automatically downloads and uses bundled Chrome
const browser = await puppeteer.launch();

Debug Support

Puppeteer includes a debug logging system controlled via the __PUPPETEER_DEBUG environment variable:

# Enable all debug channels
window.__PUPPETEER_DEBUG='*'

# Enable specific channel
window.__PUPPETEER_DEBUG='Page'

# Enable channel prefix matching
window.__PUPPETEER_DEBUG='Page*'

The debug utility is implemented in packages/puppeteer-core/src/common/Debug.ts.

Browser Support Matrix

BrowserProtocolPackage Support
ChromeCDPFull
ChromiumCDPFull
FirefoxCDPExperimental
EdgeCDPVia Chrome compatibility

Additional Resources

The repository also includes:

  • Examples (examples/): Working code samples demonstrating various Puppeteer features
  • Website (website/): Documentation site built with Docusaurus 3
  • Docker (docker/): Containerization support for browser execution
  • ESLint Tools (tools/eslint/): Custom ESLint rules for code quality

Version Compatibility

Puppeteer maintains backward compatibility within major versions. The puppeteer-core package is guaranteed to work with any browser that implements the required DevTools Protocol capabilities, though optimal compatibility is achieved with bundled browser versions.

Source: https://github.com/puppeteer/puppeteer / Human Manual

Protocol Implementations

Related topics: CDP Implementation, WebDriver BiDi Implementation

Section Related Pages

Continue reading this section for the full explanation and source context.

Section CDP Execution Context

Continue reading this section for the full explanation and source context.

Section CDP Connection

Continue reading this section for the full explanation and source context.

Section BiDi Design Principles

Continue reading this section for the full explanation and source context.

Related topics: CDP Implementation, WebDriver BiDi Implementation

Protocol Implementations

Puppeteer provides abstraction layers over two browser automation protocols: the Chrome DevTools Protocol (CDP) and WebDriver BiDi. These protocol implementations form the foundation of how Puppeteer communicates with browsers, enabling code execution, DOM manipulation, and browser control.

Architecture Overview

Puppeteer's protocol layer sits between the high-level API (Page, Frame, etc.) and the underlying browser connections. The architecture uses a dual-protocol approach where both CDP and BiDi implementations share common interfaces while providing protocol-specific behaviors.

graph TD
    subgraph "High-Level API"
        Page[Page.ts]
        Frame[Frame.ts]
    end
    
    subgraph "Protocol Abstraction Layer"
        ExecutionContext[ExecutionContext.ts<br/>CDP]
        Realm[Realm.ts<br/>BiDi]
    end
    
    subgraph "Connection Layer"
        CDP_Conn[CDP Connection]
        BiDi_Conn[BiDi Connection]
    end
    
    subgraph "Browser"
        Chrome[Chrome/Chromium]
        Firefox[Firefox]
        WebKit[WebKit]
    end
    
    Page --> ExecutionContext
    Page --> Realm
    ExecutionContext --> CDP_Conn
    Realm --> BiDi_Conn
    CDP_Conn --> Chrome
    BiDi_Conn --> Firefox
    BiDi_Conn --> WebKit

Chrome DevTools Protocol (CDP) Implementation

The CDP implementation is located in packages/puppeteer-core/src/cdp/ and provides deep integration with Chrome/Chromium browsers. CDP offers rich capabilities including precise execution context management, detailed debugging features, and direct access to browser internals.

CDP Execution Context

The ExecutionContext class in packages/puppeteer-core/src/cdp/ExecutionContext.ts handles code evaluation within browser contexts:

// Simplified from ExecutionContext.ts
async evaluate<T>(
  returnByValue: boolean,
  pageFunction: Func | string,
  ...args: Params
): Promise<HandleFor<Awaited<ReturnType<Func>>> | Awaited<ReturnType<Func>>> {
  const sourceUrlComment = getSourceUrlComment(
    getSourcePuppeteerURLIfAvailable(pageFunction)?.toString() ??
      PuppeteerURL.INTERNAL_URL,
  );

  if (isString(pageFunction)) {
    const contextId = this.#id;
    const expression = pageFunction;
    const expressionWithSourceUrl = SOURCE_URL_REGEX.test(expression)
      ? expression
      : `${expression}\n${sourceUrlComment}\n`;

    const {exceptionDetails, result: remoteObject} = await this.#client
      .send('Runtime.evaluate', {
        expression: expressionWithSourceUrl,
        contextId,
        returnByValue,
        awaitPromise: true,
        userGesture: true,
      })
      .catch(rewriteError);

    if (exceptionDetails) {
      throw createEvaluationError(exceptionDetails);
    }
    // ...
  }
}

Sources: packages/puppeteer-core/src/cdp/ExecutionContext.ts:1-50

CDP Connection

The CDP Connection manages the WebSocket-based communication channel to the browser's DevTools endpoint. This implementation handles message routing, callback management, and protocol event distribution.

WebDriver BiDi Implementation

The BiDi implementation follows the WebDriver BiDi specification and is organized into two layers:

  1. packages/puppeteer-core/src/bidi/ - Puppeteer's BiDi abstractions
  2. packages/puppeteer-core/src/bidi/core/ - Spec-compliant WebDriver BiDi core

BiDi Design Principles

According to packages/puppeteer-core/src/bidi/core/README.md:

  • bidi/core attempts to implement WebDriver BiDi comprehensively, but minimally
  • All objects and events in WebDriver BiDi are implemented as a graph where objects are nodes and events are edges
  • The implementation always follows the spec and never Puppeteer's specific needs
  • This ensures that bugs can be precisely identified as either spec issues or Puppeteer workarounds

Sources: packages/puppeteer-core/src/bidi/core/README.md:1-30

BiDi Realm

The BiDi Realm class in packages/puppeteer-core/src/bidi/Realm.ts provides the execution environment for BiDi-based evaluations:

// Simplified from Realm.ts
class Realm extends EventEmitter<RealmEvents> {
  internalPuppeteerUtil?: Promise<BidiJSHandle<PuppeteerInjectedUtil>>;
  
  get puppeteerUtil(): Promise<BidiJSHandle<PuppeteerInjectedUtil>> {
    const promise = Promise.resolve() as Promise<unknown>;
    scriptInjector.inject(script => {
      if (this.internalPuppeteerUtil) {
        void this.internalPuppeteerUtil.then(handle => {
          void handle.dispose();
        });
      }
      this.internalPuppeteerUtil = promise.then(() => {
        return this.evaluateHandle(script) as Promise<
          BidiJSHandle<PuppeteerInjectedUtil>
        >;
      });
    }, !this.internalPuppeteerUtil);
    return this.internalPuppeteerUtil as Promise<
      BidiJSHandle<PuppeteerInjectedUtil>
    >;
  }
}

Sources: packages/puppeteer-core/src/bidi/Realm.ts:1-40

Script Injection System

The ScriptInjector class (packages/puppeteer-core/src/common/ScriptInjector.ts) handles the injection of utility scripts required by both protocol implementations. It maintains a set of amendments that get applied to the injected script:

export class ScriptInjector {
  #updated = false;
  #amendments = new Set<string>();

  append(statement: string): void {
    this.#update(() => {
      this.#amendments.add(statement);
    });
  }

  inject(inject: (script: string) => void, force = false): void {
    if (this.#updated || force) {
      inject(this.#get());
    }
    this.#updated = false;
  }

  #get(): string {
    return `(() => {
      const module = {};
      ${injectedSource}
      ${[...this.#amendments]
        .map(statement => {
          return `(${statement})(module.exports.default);`;
        })
        .join('')}
      return module.exports.default;
    })()`;
  }
}

export const scriptInjector = new ScriptInjector();

Sources: packages/puppeteer-core/src/common/ScriptInjector.ts:1-50

LazyArg Pattern

The LazyArg class provides a mechanism for lazy evaluation of arguments passed to page functions. This is essential for protocol implementations as it defers the resolution of context-dependent values:

export class LazyArg<T, Context = PuppeteerUtilWrapper> {
  static create = <T>(
    get: (context: PuppeteerUtilWrapper) => Promise<T> | T,
  ): T => {
    return new LazyArg(get) as unknown as T;
  };

  #get: (context: Context) => Promise<T> | T;
  private constructor(get: (context: Context) => Promise<T> | T) {
    this.#get = get;
  }

  async get(context: Context): Promise<T> {
    return await this.#get(context);
  }
}

Sources: packages/puppeteer-core/src/common/LazyArg.ts:1-30

Protocol Selection and Configuration

The protocol implementation is selected based on browser type and configuration. The Page class in packages/puppeteer-core/src/api/Page.ts defines the abstract interface that both protocol implementations satisfy:

export abstract class Page extends EventEmitter<PageEvents> {
  _isDragging = false;
  _timeoutSettings = new TimeoutSettings();
  _tabId = '';
  
  #requestHandlers = new WeakMap<Handler<HTTPRequest>, Handler<HTTPRequest>>();
}

Sources: packages/puppeteer-core/src/api/Page.ts:100-130

Key Differences Between Protocols

FeatureCDPBiDi
Browser SupportChrome, ChromiumFirefox, WebKit, Chrome
ArchitectureWebSocket-basedWebSocket + JSON commands
Spec ComplianceChrome-specificCross-browser standard
Execution ModelDirect context switchingRealm-based isolation
DebuggingDeep DevTools integrationStandard WebDriver interface

Event Flow Comparison

graph LR
    subgraph "CDP Flow"
        CDP1[Page Event] --> CDP2[Emulation Context]
        CDP2 --> CDP3[Request Handler]
    end
    
    subgraph "BiDi Flow"
        BiDi1[Page Event] --> BiDi2[Realm]
        BiDi2 --> BiDi3[Script Injector]
        BiDi3 --> BiDi4[BiDi Command]
    end

Summary

Puppeteer's protocol implementations provide a unified abstraction over CDP and WebDriver BiDi:

  1. CDP Implementation offers deep Chrome integration with precise context management
  2. BiDi Implementation provides cross-browser compatibility following the WebDriver BiDi specification
  3. ScriptInjector manages utility script injection for both protocols
  4. LazyArg enables lazy evaluation of protocol-dependent arguments
  5. The dual-protocol architecture allows Puppeteer to target different browsers while maintaining a consistent high-level API

Source: https://github.com/puppeteer/puppeteer / Human Manual

CDP Implementation

Related topics: System Architecture, Page API

Section Related Pages

Continue reading this section for the full explanation and source context.

Section High-Level Component Architecture

Continue reading this section for the full explanation and source context.

Section Module Responsibilities

Continue reading this section for the full explanation and source context.

Section WebSocket-Based Communication

Continue reading this section for the full explanation and source context.

Related topics: System Architecture, Page API

CDP Implementation

Overview

The Chrome DevTools Protocol (CDP) is the core communication mechanism that enables Puppeteer to interact with Chromium-based browsers. The CDP Implementation in Puppeteer provides a comprehensive abstraction layer over the raw CDP protocol, enabling high-level browser automation operations such as page navigation, JavaScript execution, network interception, and device emulation.

Puppeteer's CDP implementation is located in packages/puppeteer-core/src/cdp/ and consists of multiple interconnected modules that handle different aspects of browser automation.

Sources: packages/puppeteer-core/src/cdp/Connection.ts:1-50

Architecture

High-Level Component Architecture

graph TD
    subgraph "CDP Implementation Layer"
        Connection[CdpConnection]
        Session[CdpSession]
        Browser[CdpBrowser]
        Page[CdpPage]
        NetworkManager[NetworkManager]
        FrameManager[FrameManager]
    end
    
    subgraph "Core CDP Components"
        BrowserConnector[BrowserConnector]
        Target[CDPTarget]
        Accessibility[Accessibility]
        Input[Input]
    end
    
    subgraph "Protocol Layer"
        ProtocolCommands[CDP Protocol Commands]
        EventEmitters[Event Emitters]
        MessageHandlers[Message Handlers]
    end
    
    Connection --> Session
    Session --> Browser
    Browser --> Page
    Browser --> NetworkManager
    Browser --> FrameManager
    Session --> Target
    Connection --> BrowserConnector

Module Responsibilities

ModulePurposeKey Responsibilities
Connection.tsWebSocket communicationEstablishes/manages WebSocket connection, routes messages, handles reconnection
CdpSession.tsCDP session managementCreates/sends CDP commands, receives events, manages message IDs
Browser.tsBrowser lifecycleManages browser process, targets, pages, contexts
Page.tsPage automationNavigation, frame management, viewport, emulation
NetworkManager.tsNetwork interceptionRequest/response interception, authentication handling
FrameManager.tsFrame hierarchyMain frame, child frames, navigation tracking
ExecutionContext.tsJS executionEvaluates JavaScript, manages handles

Sources: packages/puppeteer-core/src/cdp/Browser.ts:1-100

Connection Management

WebSocket-Based Communication

The CdpConnection class establishes a WebSocket connection to the browser's DevTools endpoint. This is the foundational transport layer for all CDP communication.

sequenceDiagram
    participant Puppeteer as Puppeteer Client
    participant WS as WebSocket
    participant Browser as Chrome/Chromium
    
    Puppeteer->>WS: Connect to DevTools URL
    WS->>Puppeteer: Connection established
    Puppeteer->>Browser: CDP Command (method, params, id)
    Browser->>Puppeteer: CDP Response (id, result)
    Browser->>Puppeteer: CDP Event (method, params)

Connection Lifecycle

The connection management follows a defined lifecycle:

  1. Initialization: Establish WebSocket connection to the browser's remote debugging URL
  2. Session Creation: Create CdpSession instances for different targets
  3. Message Routing: Route CDP commands and events between client and browser
  4. Disconnection Handling: Gracefully handle disconnection and cleanup
  5. Reconnection: Support for reconnection scenarios

Sources: packages/puppeteer-core/src/cdp/Connection.ts:50-150

Session Management

CdpSession Implementation

The CdpSession class represents an active CDP session bound to a specific browser target. It handles:

  • Command Dispatch: Sending CDP method calls with parameters
  • Event Subscription: Listening for CDP events from the browser
  • Message Correlation: Matching responses to requests using message IDs
  • Session Lifecycle: Creating and disposing sessions
// Simplified session structure
class CdpSession {
  #connection: CdpConnection;
  #sessionId: string;
  #messageHandlers: Map<string, EventEmitter>;
  
  async send<T>(method: string, params?: object): Promise<T>;
  on(event: string, handler: Function): void;
  off(event: string, handler: Function): void;
  detach(): Promise<void>;
}

Message Flow

graph LR
    subgraph "Client Side"
        CMD[CDP Command]
        RES[CDP Response]
        EVT[CDP Event]
    end
    
    subgraph "Transport"
        WS[WebSocket]
    end
    
    subgraph "Browser Side"
        CDP[CDP Runtime]
        TGT[Target]
    end
    
    CMD -->|send method| WS
    WS -->|route| CDP
    CDP -->|response id| WS
    WS -->|response| RES
    TGT -->|emit event| CDP
    CDP -->|event| WS
    WS -->|event| EVT

Sources: packages/puppeteer-core/src/cdp/CdpSession.ts:1-80

Browser Implementation

CdpBrowser Class

The CdpBrowser class provides the high-level browser interface, implementing the Browser interface defined in the API layer. It coordinates multiple CDP sessions and manages browser targets.

classDiagram
    class CdpBrowser {
        +connection_: CdpConnection
        +browserContext_: BrowserContext
        +_targets: Map~string, CdpTarget~
        +_ignoreHTTPSErrors: boolean
        +_defaultViewport: Viewport | null
        +newPage(): Promise~CdpPage~
        +createIncognitoBrowserContext(): BrowserContext
        +disconnect(): void
        +wsEndpoint(): string
    }
    
    class CdpTarget {
        +_browserContext: BrowserContext
        +_session: CdpSession
        +_initialized: Promise~void~
        +_closeCallback: Function
        +initialize(): Promise~void~
    }
    
    CdpBrowser --> CdpTarget
    CdpTarget --> CdpSession

Target Management

Browser targets represent different browsing contexts managed by Chromium:

Target TypeDescriptionCreation Method
Browser TargetMain browser processAuto-created on connection
Page TargetSingle page/tabTarget.createTarget
Service WorkerBackground scriptAuto-created for SWs
BrowserContextIsolated profileBrowser.createIncognitoContext

Sources: packages/puppeteer-core/src/cdp/Browser.ts:100-250

Page Implementation

CdpPage Class

The CdpPage class extends the abstract Page class and implements page-specific CDP operations. It provides methods for:

  • Navigation: goto(), goBack(), goForward(), reload()
  • Content Operations: setContent(), content()
  • Viewport Management: setViewport(), viewport settings
  • Frame Access: mainFrame(), frames(), frame()
  • Device Emulation: emulate(), emulateMediaType(), emulateTimezone()
graph TD
    subgraph "CdpPage"
        PageAPI[Page Interface]
        Navigation[Navigation Manager]
        Emulation[Emulation Manager]
        Screenshot[Screenshot Handler]
    end
    
    subgraph "CDP Sessions"
        PageSession[Page Target Session]
        FrameSession[Frame Session]
    end
    
    PageAPI --> Navigation
    PageAPI --> Emulation
    PageAPI --> Screenshot
    Navigation --> PageSession
    Emulation --> PageSession
    FrameSession --> FrameManager

Page Lifecycle Events

EventTriggerUse Case
loadPage load completeWait for full page
domcontentloadedDOM readyEarly interaction
networkidleNo network for 500msWait for API calls
framenavigatedFrame navigation completeFrame sync
request/requestfailed/responseNetwork eventsIntercept/modify requests

Sources: packages/puppeteer-core/src/cdp/Page.ts:1-150

Network Management

NetworkManager Class

The NetworkManager handles all network-related CDP events and provides the interception infrastructure for page.setRequestInterception().

graph TD
    subgraph "NetworkManager"
        RequestInterceptor[Request Interceptor]
        AuthHandler[Auth Handler]
        CacheManager[Cache Manager]
    end
    
    subgraph "CDP Events"
        REQ[Network.requestWillBeSent]
        RES[Network.responseReceived]
        ERR[Network.requestFailed]
        CMPL[Network.loadingFinished]
    end
    
    subgraph "Public API"
        Interception[setRequestInterception]
        Auth[authenticate]
        Offline[setOfflineMode]
    end
    
    REQ --> RequestInterceptor
    RequestInterceptor --> Interception
    Auth --> AuthHandler
    AuthHandler --> REQ

Request Interception Flow

sequenceDiagram
    participant Browser as Browser
    participant NM as NetworkManager
    participant Interceptor as User Interceptor
    participant CDP as CDP Session
    
    Browser->>NM: requestWillBeSent
    NM->>Interceptor: intercept callback
    Interceptor->>NM: continue/abort/respond
    NM->>CDP: Network.continueRequest
    NM->>CDP: Network.failRequest
    NM->>CDP: Network.fulfillRequest

Authentication Handler

The NetworkManager includes authentication handling for HTTP Basic/Digest auth:

interface AuthCredentials {
  username: string;
  password: string;
}

class NetworkManager {
  #authCredentials?: AuthCredentials;
  #pendingAuthRequests: Map<string, InterceptionHandle>;
  
  setAuthCredentials(credentials: AuthCredentials): void;
  clearAuthCredentials(): void;
}

Sources: packages/puppeteer-core/src/cdp/NetworkManager.ts:1-200

Frame Management

FrameManager Class

The FrameManager maintains the frame hierarchy and tracks frame lifecycle events. It handles:

  • Frame Tree Construction: Building and maintaining the document frame hierarchy
  • Navigation Tracking: Tracking frame-level navigation events
  • Detached Frame Cleanup: Cleaning up frames when their documents unload
  • Frame Communication: Managing frame-specific CDP sessions
graph TD
    subgraph "FrameManager"
        FT[Frame Tree]
        EH[Event Handler]
        NC[Navigation Checker]
    end
    
    subgraph "Frame Types"
        MF[Main Frame]
        IF[iframe]
        SF[Shadow Frame]
    end
    
    FT --> MF
    FT --> IF
    FT --> SF
    EH -->|events| FT
    NC -->|nav events| FT

Frame Hierarchy

Frame TypeCDP TargetSessionCharacteristics
Main FramePage targetPrimary sessionTop-level document
SubframeAuto-createdLinked to parentCross-origin isolation
WorkerServiceWorker targetSeparate sessionNo DOM access

Sources: packages/puppeteer-core/src/cdp/FrameManager.ts:1-180

Execution Context

CdpExecutionContext

The execution context in CDP is the JavaScript execution environment within a frame. The ExecutionContext class provides:

  • JavaScript Evaluation: evaluate() and evaluateHandle() methods
  • Handle Management: Creating and managing JSHandle instances
  • Remote Object Conversion: Converting CDP RemoteObjects to JSHandles
graph LR
    subgraph "User Code"
        FN[Function/Expression]
    end
    
    subgraph "Puppeteer"
        EVAL[evaluate]
        LAZY[LazyArg]
        HANDLE[JsHandle]
    end
    
    subgraph "CDP"
        RTE[Runtime.evaluate]
        CALL[Runtime.callFunctionOn]
        RO[RemoteObject]
    end
    
    FN --> EVAL
    EVAL --> RTE
    EVAL --> CALL
    CALL --> LAZY
    RTE --> RO
    CALL --> RO
    RO --> HANDLE

Source URL Handling

Puppeteer injects source URL comments into evaluated code for better debugging:

const SOURCE_URL_COMMENT = '//# sourceURL=__puppeteer_evaluation_script__';

This enables:

  • Proper stack traces in console errors
  • Source map resolution in DevTools
  • Better debugging experience for evaluated code

Sources: packages/puppeteer-core/src/cdp/ExecutionContext.ts:30-120

Key CDP Methods Used

Browser-Level Methods

MethodCategoryPurpose
Target.createTargetTargetCreate new page/tab
Target.attachToTargetTargetAttach to existing target
Browser.closeBrowserClose browser
Browser.getVersionBrowserGet browser info

Page-Level Methods

MethodCategoryPurpose
Page.navigateNavigationNavigate to URL
Page.setDocumentContentContentSet HTML content
Page.captureScreenshotScreenshotTake screenshot
Page.setViewportEmulationSet viewport dimensions

Network Methods

MethodCategoryPurpose
Network.setRequestInterceptionInterceptionEnable request interception
Network.continueRequestInterceptionContinue intercepted request
Network.fulfillRequestInterceptionRespond with custom data
Network.getResponseBodyResponseGet response body

Runtime Methods

MethodCategoryPurpose
Runtime.evaluateEvaluationExecute expression
Runtime.callFunctionOnEvaluationCall function on object
Runtime.queryObjectsInspectionQuery JS objects

Sources: packages/puppeteer-core/src/cdp/Page.ts:200-350

Event Flow Architecture

graph TD
    subgraph "Browser Events"
        NE[Navigation Event]
        RE[Resource Event]
        EE[Execution Event]
    end
    
    subgraph "CDP Events"
        CDP_NE[Page.frameNavigated]
        CDP_RE[Network.requestWillBeSent]
        CDP_EE[Runtime.executionContextCreated]
    end
    
    subgraph "Puppeteer Events"
        P_E[page.on Event]
        CB[Event Callback]
    end
    
    NE -->|triggers| CDP_NE
    RE -->|triggers| CDP_RE
    EE -->|triggers| CDP_EE
    CDP_NE -->|emitted| P_E
    CDP_RE -->|emitted| P_E
    CDP_EE -->|emitted| P_E
    P_E -->|invokes| CB

Error Handling

Error Rewriting

Puppeteer rewrites CDP errors to provide more meaningful error messages:

function rewriteError(error: Error, message: string): never {
  throw new Error(`${message}: ${error.message}`);
}

Evaluation Errors

JavaScript evaluation errors are converted to Error instances with detailed information:

function createEvaluationError(exceptionDetails: ExceptionDetails): Error {
  const error = new Error();
  error.name = exceptionDetails.exception?.className ?? 'Error';
  error.message = exceptionDetails.exception?.description 
    ?? exceptionDetails.text;
  return error;
}

Sources: packages/puppeteer-core/src/cdp/ExecutionContext.ts:60-90

Configuration Options

OptionTypeDefaultDescription
executablePathstringbundled browserPath to browser executable
channelChromeReleaseChannelautoChrome update channel
browserSupportedBrowserchromeBrowser to use
timeoutnumber30000Browser launch timeout
protocolTimeoutnumberundefinedCDP protocol timeout

Browser Configuration

SettingEnvironment VariableDescription
defaultBrowserPUPPETEER_DEFAULT_BROWSERDefault browser to use
temporaryDirectoryPUPPETEER_TMP_DIRTemp directory for downloads
skipDownloadPUPPETEER_SKIP_DOWNLOADSkip browser download
logLevelPUPPETEER_LOG_LEVELLogging level

Sources: packages/puppeteer-core/src/node/LaunchOptions.ts:1-100

See Also

Sources: [packages/puppeteer-core/src/cdp/Connection.ts:1-50]()

WebDriver BiDi Implementation

Related topics: System Architecture, Protocol Implementations

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Event Flow Integrity

Continue reading this section for the full explanation and source context.

Section BiDi over CDP Bridge

Continue reading this section for the full explanation and source context.

Section WebDriver BiDi Capabilities

Continue reading this section for the full explanation and source context.

Related topics: System Architecture, Protocol Implementations

WebDriver BiDi Implementation

Overview

WebDriver BiDi (Bidirectional Protocol) is a W3C-standardized protocol that enables bidirectional communication between browser automation tools and web browsers. Puppeteer's WebDriver BiDi implementation provides a modern, cross-browser automation interface built on the WebDriver protocol specification.

The implementation exists as a first-class protocol option alongside CDP (Chrome DevTools Protocol), with deep integration into Puppeteer's core architecture.

Architecture Principles

The bidi/core module follows specific architectural guidelines that distinguish it from higher-level Puppeteer abstractions:

PrincipleDescription
Spec Compliancebidi/core always follows the WebDriver BiDi specification, never Puppeteer's needs
No WorkaroundsSpec deviations are never masked; instead, workarounds belong in upper layers
Comprehensive MinimalismAll required nodes and edges in the protocol graph are implemented fully
Event IntegrityEvents are never composed or duplicated; navigation flows must follow the correct event sequence

Sources: packages/puppeteer-core/src/bidi/core/README.md

Event Flow Integrity

A critical principle is that events must follow proper WebDriver BiDi semantics. For navigation events:

  • Fragment navigations must emit events through the complete chain: fragment navigation → navigation → browsing context
  • Direct emission to browsing context without intermediate events is prohibited
  • This ensures that consumers receive semantically correct event sequences matching the protocol specification

Protocol Connection Architecture

graph TD
    A[Puppeteer Application] --> B[BrowserLauncher]
    B --> C{PUPPETEER_WEBDRIVER_BIDI_ONLY}
    C -->|true| D[BiDi Only Mode]
    C -->|false| E[CDP + BiDi Hybrid Mode]
    D --> F[BiDi.connectBidiOverCdp]
    E --> G[CDP Connection]
    G --> H[BiDi.connectBidiOverCdp]
    F --> I[BidiBrowser Instance]
    H --> I

BiDi over CDP Bridge

When using WebDriver BiDi with browsers that primarily support CDP (like Chrome), Puppeteer establishes a CDP connection and wraps it with BiDi protocol support:

const bidiOnly = process.env['PUPPETEER_WEBDRIVER_BIDI_ONLY'] === 'true';
const BiDi = await import('../bidi/bidi.js');
const bidiConnection = await BiDi.connectBidiOverCdp(cdpConnection);
return await BiDi.BidiBrowser.create({
  connection: bidiConnection,
  // Do not provide CDP connection to Browser if BiDi-only mode is enabled
  cdpConnection: bidiOnly ? undefined : cdpConnection,
  closeCallback,
  process: browserProcess.nodeProcess,
  defaultViewport: opts.defaultViewport,
  acceptInsecureCerts: opts.acceptInsecureCerts,
  networkEnabled: opts.networkEnabled,
  issuesEnabled: opts.issuesEnabled,
});

Sources: packages/puppeteer-core/src/node/BrowserLauncher.ts:1-28

WebDriver BiDi Capabilities

When connecting with WebDriver BiDi protocol, capabilities can be specified:

interface SupportedWebDriverCapabilities {
  webDriverBiDi?: {
    // BiDi-specific capabilities passed to session.new
  };
}

The capabilities option allows passing WebDriver BiDi capabilities during connection establishment:

Headers to use for the web socket connection. Only works in the Node.js environment.
WebDriver BiDi capabilities passed to BiDi session.new. Only works for protocol="webDriverBiDi" and Puppeteer.connect.

Sources: packages/puppeteer-core/src/common/ConnectOptions.ts:1-50

Target Model

Puppeteer's BiDi implementation extends the abstract Target class with browser-specific target types:

BidiBrowserTarget

Represents the browser-level target in WebDriver BiDi context:

export class BidiBrowserTarget extends Target {
  #browser: BidiBrowser;

  override type(): TargetType {
    return TargetType.BROWSER;
  }

  override browser(): BidiBrowser {
    return this.#browser;
  }

  override browserContext(): BidiBrowserContext {
    return this.#browser.defaultBrowserContext();
  }
}

Unsupported operations throw UnsupportedOperation:

  • asPage() - Not supported at browser target level
  • createCDPSession() - CDP sessions not available in BiDi-only targets
  • opener() - Not applicable to browser targets

Sources: packages/puppeteer-core/src/bidi/Target.ts:1-50

BidiPageTarget

Represents individual page targets within the browser context. Extends the base Target with page-specific behavior through composition with BidiPage.

Console Message Handling

WebDriver BiDi requires conversion between BiDi console event levels and Puppeteer's internal representation:

export function convertConsoleMessageLevel(method: string): ConsoleMessageType {
  switch (method) {
    case 'group':
      return 'startGroup';
    case 'groupCollapsed':
      return 'startGroupCollapsed';
    case 'groupEnd':
      return 'endGroup';
    default:
      return method as ConsoleMessageType;
  }
}

This mapping ensures that BiDi's console event semantics align with Puppeteer's console message types.

Sources: packages/puppeteer-core/src/bidi/util.ts:1-40

Stack Trace Extraction

Console messages can include stack trace information extracted from BiDi protocol responses:

export function getStackTraceLocations(
  stackTrace?: Bidi.Script.StackTrace,
): ConsoleMessageLocation[] {
  const stackTraceLocations: ConsoleMessageLocation[] = [];
  if (stackTrace) {
    for (const callFrame of stackTrace.callFrames) {
      stackTraceLocations.push({
        url: callFrame.url,
        lineNumber: callFrame.lineNumber,
        columnNumber: callFrame.columnNumber,
      });
    }
  }
  return stackTraceLocations;
}

Firefox-Specific Configuration

Firefox has native WebDriver BiDi support and provides specific preferences configuration:

PreferenceValuePurpose
fission.bfcacheInParentundefinedBFCache behavior
fission.webContentIsolationStrategy0Process isolation strategy

Blocklist and Allowlist

Firefox's WebDriver BiDi implementation supports blocklist/allowlist configuration through preferences. However, these are only supported with the CDP protocol:

it('should reject blocklist for the default Firefox WebDriver BiDi protocol', async () => {
  const launcher = new FirefoxLauncher({} as PuppeteerNode);

  await expect(
    launcher.launch({
      blocklist: ['https://example.com/*'],
    }),
  ).rejects.toThrow(
    'blocklist and allowlist are only supported with the CDP protocol',
  );
});

Sources: packages/puppeteer-core/src/node/FirefoxLauncher.test.ts:1-40

Core Components

ComponentFileResponsibility
Browserbidi/Browser.tsMain browser instance management
BrowsingContextbidi/core/BrowsingContext.tsTab/window context handling
Navigationbidi/core/Navigation.tsNavigation event handling
Pagebidi/Page.tsPage-level operations
Realmbidi/Realm.tsJavaScript execution contexts

Protocol Modes

Puppeteer supports three protocol configuration modes:

graph LR
    A[Default] --> B[CDP + BiDi]
    C[PUPPETEER_WEBDRIVER_BIDI_ONLY=true] --> D[BiDi Only]
    E[protocol=webDriverBiDi] --> D
ModeCDP AvailableBiDi AvailableUse Case
DefaultYesYes (via bridge)Chrome automation
BiDi OnlyNoYesPure spec compliance
WebDriver BiDiNoNativeFirefox automation

Summary

The WebDriver BiDi implementation in Puppeteer provides:

  1. Standards-compliant protocol support through the bidi/core module following W3C WebDriver BiDi specification
  2. Flexible connection architecture supporting CDP bridge and native BiDi modes
  3. Browser-agnostic target model with proper abstraction layers
  4. Event integrity ensuring semantically correct event sequences per protocol spec
  5. Cross-browser compatibility with native Firefox BiDi support and Chrome CDP bridging

Sources: [packages/puppeteer-core/src/bidi/core/README.md]()

Page API

Related topics: Locators and Element Handles, Input Handling

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Class Hierarchy

Continue reading this section for the full explanation and source context.

Section Internal State Management

Continue reading this section for the full explanation and source context.

Section Basic Navigation Methods

Continue reading this section for the full explanation and source context.

Related topics: Locators and Element Handles, Input Handling

Page API

The Page API is the core interface in Puppeteer for interacting with browser pages and tabs. It provides methods for navigating pages, interacting with DOM elements, evaluating JavaScript, handling events, and emulating various browser environments and device characteristics.

Overview

The Page API serves as the primary abstraction for browser page operations in Puppeteer. A Page instance represents a single tab or window within a browser instance, offering a comprehensive set of methods to control page behavior, extract data, and automate interactions.

graph TD
    A[Browser Instance] --> B[Page API]
    B --> C[Navigation]
    B --> D[DOM Interaction]
    B --> E[JavaScript Evaluation]
    B --> F[Event Handling]
    B --> G[Device Emulation]
    
    C --> C1[goto, back, forward, reload]
    D --> D1[$, $$, locator]
    E --> E1[evaluate, exposeFunction]
    F --> F1[on, once, off]
    G --> G1[emulateMediaType, emulate]

Sources: packages/puppeteer-core/src/api/Page.ts:1-50

Core Architecture

Class Hierarchy

The Page class extends EventEmitter and serves as an abstract base class implemented by both CDP (Chrome DevTools Protocol) and WebDriver BiDi backends:

classDiagram
    class EventEmitter~PageEvents~ {
        <<abstract>>
    }
    class Page {
        <<abstract>>
        +_isDragging: boolean
        +_timeoutSettings: TimeoutSettings
        +_tabId: string
        +exposeFunction()
        +metrics()
        +captureHeapSnapshot()
        +emulateMediaType()
        +emulateCPUThrottling()
        +emulateMediaFeatures()
    }
    class CDPPage {
        +implementation
    }
    class BiDiPage {
        +implementation
    }
    
    EventEmitter <|-- Page
    Page <|-- CDPPage
    Page <|-- BiDiPage

Sources: packages/puppeteer-core/src/api/Page.ts:200-230

Internal State Management

The Page class maintains several internal state properties:

PropertyTypePurpose
_isDraggingbooleanTracks drag state for mouse interactions
_timeoutSettingsTimeoutSettingsManages timeout configuration for operations
_tabIdstringBrowser-specific tab identifier
#inflight$ReplaySubject<number>Tracks in-flight request count
#requestHandlersWeakMapMaps request handlers for monitoring

Sources: packages/puppeteer-core/src/api/Page.ts:200-215

Navigation API

Basic Navigation Methods

The Page API provides fundamental navigation methods for controlling page loading:

  • goto(url) - Navigate to a URL
  • reload() - Reload the current page
  • goBack() - Navigate to the previous page in history
  • goForward() - Navigate to the next page in history
  • close() - Close the page

URL Property

The url() method returns the current page URL as a shortcut for page.mainFrame().url():

const currentUrl = await page.url();

Sources: packages/puppeteer-core/src/api/Page.ts:280-295

JavaScript Evaluation

evaluate Method

The evaluate method executes JavaScript code in the page context. It supports both string expressions and function-based evaluation.

Sources: packages/puppeteer-core/src/cdp/ExecutionContext.ts:30-60

evaluate with Parameters

When passing arguments to page functions, Puppeteer serializes them using a specialized mechanism:

await page.evaluate(
  (text, inputValue) => {
    document.querySelector(text).value = inputValue;
  },
  'selector',
  'value'
);

Sources: packages/puppeteer-core/src/cdp/ExecutionContext.ts:45-55

Source URL Comment Injection

Puppeteer automatically injects source URL comments into evaluated code to enable better debugging and source map support:

const sourceUrlComment = getSourceUrlComment(
  getSourcePuppeteerURLIfAvailable(pageFunction)?.toString() ??
    PuppeteerURL.INTERNAL_URL,
);

The injection follows this pattern:

  1. Check if the expression already contains a source URL
  2. If not, append the source URL comment to the expression
  3. Include this comment in the CDP Runtime.evaluate call

Sources: packages/puppeteer-core/src/cdp/ExecutionContext.ts:35-45

exposeFunction API

The exposeFunction method allows exposing Node.js functions to the page's JavaScript context as window[name]:

Signature

abstract exposeFunction(
  name: string,
  pptrFunction: Function | {default: Function}
): Promise<void>;

Usage Example

const browser = await puppeteer.launch();
const page = await browser.newPage();

page.on('console', msg => console.log(msg.text()));
await page.exposeFunction('readfile', async filePath => {
  return fs.readFileSync(filePath, 'utf8');
});

await page.evaluate(async () => {
  const content = await window.readfile('/etc/hosts');
  console.log(content);
});

await browser.close();

Parameters

ParameterTypeDescription
namestringName of the function on the window object
pptrFunction`Function \{default: Function}`Callback function executed in Puppeteer's Node.js context

Sources: packages/puppeteer-core/src/api/Page.ts:140-175

Device Emulation

Emulate Media Type

The emulateMediaType method emulates CSS media type on the page:

await page.emulateMediaType('print');
await page.evaluate(() => matchMedia('print').matches); // true
await page.emulateMediaType(null); // Reset to default

Sources: packages/puppeteer-core/src/api/Page.ts:320-345

Emulate Media Features

The emulateMediaFeatures method emulates CSS media features:

await page.emulateMediaFeatures([
  { name: 'prefers-color-scheme', value: 'dark' },
]);

Sources: packages/puppeteer-core/src/api/Page.ts:345-360

Known Devices

Puppeteer provides a predefined set of device descriptors via KnownDevices:

import { KnownDevices } from 'puppeteer';
const iPhone = KnownDevices['iPhone 15 Pro'];

await page.emulate(iPhone);

Sources: packages/puppeteer-core/src/common/Device.ts:1-30

CPU Throttling

The emulateCPUThrottling method enables CPU throttling to simulate slow CPUs:

// No throttling (1x speed)
await page.emulateCPUThrottling(1);

// 2x slowdown
await page.emulateCPUThrottling(2);

// Disable throttling
await page.emulateCPUThrottling(null);

Sources: packages/puppeteer-core/src/api/Page.ts:355-360

Metrics API

The metrics() method returns performance metrics from the browser:

Returned Metrics

MetricDescription
TimestampMonotonic timestamp when sample was taken
DocumentsNumber of documents in the page
FramesNumber of frames in the page
JSEventListenersNumber of JavaScript event listeners
NodesNumber of DOM nodes
LayoutCountTotal full or partial page layouts
RecalcStyleCountTotal style recalculations
LayoutDurationCombined layout duration
RecalcStyleDurationCombined style recalculation duration
ScriptDurationCombined JavaScript execution duration
TaskDurationCombined browser task duration
JSHeapUsedSizeUsed JavaScript heap size
JSHeapTotalSizeTotal JavaScript heap size

Sources: packages/puppeteer-core/src/api/Page.ts:260-280

Heap Snapshot

The captureHeapSnapshot method captures a snapshot of the JavaScript heap:

await page.captureHeapSnapshot({ path: 'screenshot.png' });

Sources: packages/puppeteer-core/src/api/Page.ts:285-290

Locator API

The Page API integrates with Puppeteer's Locator API for reliable element interactions:

Available Locator Methods

// Query elements using various selector types
const element = page.locator('button.submit');
const elements = page.locator('.item');

// ARIA selectors
const searchInput = page.locator('::-p-aria(Search)');

// Text selectors
const title = page.locator('::-p-text(Customize and automate)');

// XPath selectors
const para = page.locator('::-p-xpath(//p[@class="intro"])');

// CSS with pierce (shadow DOM)
const shadowElement = page.locator(':scope >>> .shadow-content');

Sources: packages/puppeteer-core/src/api/locators/locators.ts:1-50

LazyArg System

The LazyArg system provides lazy evaluation of arguments passed to page functions:

export class LazyArg<T, Context = PuppeteerUtilWrapper> {
  static create = <T>(
    get: (context: PuppeteerUtilWrapper) => Promise<T> | T
  ): T => {
    return new LazyArg(get) as unknown as T;
  };

  async get(context: Context): Promise<T> {
    return await this.#get(context);
  }
}

This allows arguments to be evaluated on-demand in the browser context, avoiding serialization issues with complex objects.

Sources: packages/puppeteer-core/src/common/LazyArg.ts:1-40

Event Handling

The Page class extends EventEmitter and emits various events documented in the PageEvent enum:

Basic Event Usage

// Listen for a single event
page.once('load', () => console.log('Page loaded!'));

// Listen for ongoing events
page.on('request', request => {
  console.log('Request:', request.url());
});

// Unsubscribe from events
function logRequest(request) {
  console.log('A request was made:', request.url());
}
page.on('request', logRequest);
page.off('request', logRequest);

Sources: packages/puppeteer-core/src/api/Page.ts:180-200

Error Handling

Evaluation Errors

When JavaScript evaluation fails, Puppeteer throws a descriptive error:

const { exceptionDetails, result } = await this.#client.send(
  'Runtime.evaluate',
  {
    expression: expressionWithSourceUrl,
    contextId,
    returnByValue,
    awaitPromise: true,
    userGesture: true,
  }
).catch(rewriteError);

if (exceptionDetails) {
  throw createEvaluationError(exceptionDetails);
}

Sources: packages/puppeteer-core/src/cdp/ExecutionContext.ts:50-65

Implementation Backends

CDP (Chrome DevTools Protocol) Backend

The CDP implementation uses Chrome's native DevTools Protocol for communication:

WebDriver BiDi Backend

The BiDi implementation provides cross-browser compatibility:

Summary

The Page API provides a comprehensive abstraction layer for browser page automation in Puppeteer. Key capabilities include:

CategoryFeatures
NavigationURL access, goto, reload, back, forward
JavaScriptevaluate, exposeFunction, handle serialization
EmulationMedia types, media features, CPU throttling, device profiles
MetricsPerformance metrics, heap snapshots
InteractionLocators, event handling, drag simulation
StateTimeout settings, tab identification, request tracking

The abstract Page class is implemented by both CDP and BiDi backends, ensuring flexibility and cross-browser compatibility while maintaining a consistent API surface for users.

Source: https://github.com/puppeteer/puppeteer / Human Manual

Locators and Element Handles

Related topics: Page API, Input Handling

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Purpose and Scope

Continue reading this section for the full explanation and source context.

Section Class Definition

Continue reading this section for the full explanation and source context.

Section Key Characteristics

Continue reading this section for the full explanation and source context.

Related topics: Page API, Input Handling

Locators and Element Handles

Overview

Puppeteer provides two complementary mechanisms for interacting with DOM elements in a browser page: Locators and Element Handles. Both serve the purpose of referencing and manipulating elements, but they differ significantly in their design philosophy, retry behavior, and use cases.

  • Element Handles provide direct, immediate references to DOM elements. They are point-in-time references that do not automatically retry if elements become stale or unavailable.
  • Locators are designed for reliability and resilience. They automatically retry actions until the element is in the correct state, making them ideal for modern web applications with dynamic content.

Sources: packages/puppeteer-core/src/api/ElementHandle.ts:1-50

graph TD
    A[User Code] --> B{Choose Strategy}
    B --> C[ElementHandle]
    B --> D[Locator]
    C --> E[Direct DOM Reference]
    C --> F[No Auto-Retry]
    D --> G[Query Strategy + Retry Logic]
    D --> H[State Awareness]
    D --> I[Action Chaining]

Element Handles

Purpose and Scope

Element Handles are direct references to DOM elements obtained through query methods like page.$() or page.$$(). They provide low-level access to elements but require manual management of element lifecycle.

Sources: packages/puppeteer-core/src/api/ElementHandle.ts:40-60

Class Definition

export abstract class ElementHandle<
  ElementType extends Node = Element,
> extends JSHandle<ElementType> {
  /**
   * @internal
   */
  declare [_isElementHandle]: boolean;

  /**
   * @internal
   * Cached isolatedHandle to prevent
   * trying to adopt it multiple times
   */
  isolatedHandle?: typeof this;

  /**
   * @internal
   */
  protected readonly handle;
}

Sources: packages/puppeteer-core/src/api/ElementHandle.ts:40-58

Key Characteristics

CharacteristicDescription
LifecycleAuto-disposed when frame navigates or context is destroyed
Garbage CollectionPrevents GC while handle exists unless explicitly disposed
Type SafetyGeneric type parameter for element type (e.g., ElementHandle<HTMLSelectElement>)
UsageUsed as arguments in Page.$eval and Page.evaluate

Query Methods

Element Handles can be created using the following Page/Frame methods:

MethodReturnsDescription
page.$(selector)`ElementHandle \null`First element matching selector
page.$$(selector)ElementHandle[]All elements matching selector
frame.$(selector)`ElementHandle \null`First element in frame
frame.$$(selector)ElementHandle[]All elements in frame

Sources: packages/puppeteer-core/src/api/Frame.ts:100-130

Memory Management with `using`

Puppeteer provides an ESLint rule to enforce proper disposal of Element Handles using the using keyword. This ensures handles are automatically cleaned up when they go out of scope.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');

// Using 'using' ensures proper cleanup
using element = await page.$('a');
await element.click();

Sources: tools/eslint/src/use-using.ts:1-50

const usingSymbols = ['ElementHandle', 'JSHandle'];

Sources: tools/eslint/src/use-using.ts:12

Locators

Purpose and Design Philosophy

Locators are Puppeteer's recommended approach for element interaction. They encapsulate both the query strategy and retry logic, providing a robust way to handle flaky tests in modern web applications where elements may appear, disappear, or change state dynamically.

Sources: packages/puppeteer-core/src/api/Page.ts:1-100

Locator API

Locators are created through the locator() method on Page or Frame:

locator<Selector extends string>(
  selector: Selector,
): Locator<NodeFor<Selector>>;

locator<Ret>(func: () => Awaitable<Ret>): Locator<Ret>;

Supported Selector Types

Puppeteer supports multiple selector types that can be used with both Element Handles and Locators:

Selector TypeSyntaxDescription
CSS'<css>'Standard CSS selectors
Text::-p-text(<text>)Elements containing text
ARIA::-p-aria(<role>[name])Accessibility-based selection
XPathxpath=<xpath>XPath expressions
Pierce>>> <selector>Cross-shadow-DOM queries
CustomCustom prefixUser-defined query handlers

Sources: packages/puppeteer-core/src/common/CSSQueryHandler.ts

Query Handlers Architecture

Query handlers are the pluggable components that process different selector types.

classDiagram
    class QueryHandler {
        <<interface>>
        +query(page, selector)
        +queryAll(page, selector)
    }
    class CSSQueryHandler {
        +query(page, selector)
        +queryAll(page, selector)
    }
    class AriaQueryHandler {
        +query(page, selector)
        +queryAll(page, selector)
    }
    class CustomQueryHandler {
        +query(page, selector)
        +queryAll(page, selector)
    }
    class XPathQueryHandler {
        +query(page, selector)
        +queryAll(page, selector)
    }
    
    QueryHandler <|.. CSSQueryHandler
    QueryHandler <|.. AriaQueryHandler
    QueryHandler <|.. CustomQueryHandler
    QueryHandler <|.. XPathQueryHandler

CSS Query Handler

The CSS Query Handler processes standard CSS selectors and is the default handler for selectors without a prefix.

// Internal implementation delegates to injected PQuerySelector
export class CSSQueryHandler extends QueryHandler {
  #pquerySelector: PQuerySelector;
  // Uses PuppeteerInjectedScript for DOM queries
}

Sources: packages/puppeteer-core/src/common/CSSQueryHandler.ts

Aria Query Handler

The ARIA Query Handler enables selection based on accessibility attributes:

// Select by role and optional name
await page.locator('::-p-aria(Search)').fill('query');
await page.locator('::-p-aria(Submit button[name])').click();

Sources: packages/puppeteer-core/src/common/AriaQueryHandler.ts

Custom Query Handlers

Puppeteer allows registration of custom query handlers for domain-specific selectors:

page.customQueryHandlers.set('mySelector', {
  queryOne: (self, selector) => { /* ... */ },
  queryAll: (self, selector) => { /* ... */ },
});

Comparison: Locators vs Element Handles

AspectElement HandlesLocators
Retry BehaviorNone - immediate resultAutomatic retry until element ready
State AwarenessNoneTracks element state
Flakiness HandlingManualBuilt-in
PerformanceFaster for single operationSlight overhead for retry logic
Use CaseSimple scripts, single operationsDynamic applications, tests
Stale Element HandlingManual detection and re-queryAutomatic re-query
graph LR
    A[Action Request] --> B{Locator}
    B --> C{Element visible?}
    C -->|No| D[Wait & Retry]
    D --> C
    C -->|Yes| E[Perform Action]
    
    F[Action Request] --> G{ElementHandle}
    G --> H[Immediate Result]
    H --> I[Perform Action]
    I --> J{Still valid?}
    J -->|No| K[StaleElementReference Error]

Best Practices

When to Use Locators

  • Recommended for most use cases
  • Testing modern web applications with dynamic content
  • When element availability timing is uncertain
  • Building resilient automation scripts

When to Use Element Handles

  • Quick scripts with predictable DOM
  • When performance is critical
  • Low-level DOM manipulation
  • Integration with other libraries expecting handles

Memory Management

Always dispose of handles to prevent memory leaks:

// Using async disposal
const handle = await page.$('div');
try {
  // Work with handle
} finally {
  await handle.dispose();
}

// Or use 'using' keyword where supported
using element = await page.$('a');

ESLint Integration

Enable the use-using rule to enforce proper handle disposal:

{
  "rules": {
    "@puppeteer/use-using": "error"
  }
}

Sources: tools/eslint/src/use-using.ts:20-60

Examples

Basic Element Handle Usage

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');

// Single element
const hrefElement = await page.$('a');
await hrefElement.click();

// Multiple elements
const links = await page.$$('a');
for (const link of links) {
  const text = await link.evaluate(el => el.textContent);
  console.log(text);
}

await browser.close();

Sources: packages/puppeteer-core/src/api/ElementHandle.ts:10-30

Locator with Action Chaining

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
const page = await browser.newPage();

await page.goto('https://example.com');

// Chain actions on locator
await page.locator('::-p-aria(Search)').fill('query');
await page.locator('.devsite-result-item-link').click();

// Wait for element with locator
const textSelector = await page
  .locator('::-p-text(Customize and automate)')
  .waitHandle();

await browser.close();

Using $$eval for Batch Operations

const allInputValues = await page.$$eval('input', elements =>
  elements.map(e => e.textContent),
);

Sources: packages/puppeteer-core/src/api/Page.ts:1-50

Architecture Summary

graph TD
    subgraph "User Layer"
        A[page.$()]
        B[page.locator()]
        C[frame.$$()]
    end
    
    subgraph "Query Handler Layer"
        D[CSSQueryHandler]
        E[AriaQueryHandler]
        F[CustomQueryHandler]
        G[XPathQueryHandler]
    end
    
    subgraph "Execution Layer"
        H[CDP Protocol]
        I[BiDi Protocol]
    end
    
    A --> D
    B --> D
    B --> E
    C --> F
    
    D --> H
    D --> I
    E --> H
    F --> H
    
    style A fill:#e1f5fe
    style B fill:#e8f5e8
    style D fill:#fff3e0
    style E fill:#fff3e0

See Also

Sources: [packages/puppeteer-core/src/api/ElementHandle.ts:1-50]()

Input Handling

Related topics: Locators and Element Handles, Page API

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Keyboard Interface Methods

Continue reading this section for the full explanation and source context.

Section Key Input Values

Continue reading this section for the full explanation and source context.

Section Type vs Press

Continue reading this section for the full explanation and source context.

Related topics: Locators and Element Handles, Page API

Input Handling

Input Handling in Puppeteer provides a unified API for simulating user interactions with web pages, including keyboard input, mouse operations, touch gestures, and drag-and-drop actions. The system abstracts away protocol-level differences between Chrome DevTools Protocol (CDP) and WebDriver BiDi, providing developers with a consistent interface for browser automation.

Architecture Overview

Puppeteer's Input Handling system follows a layered architecture:

graph TD
    A[User Code] --> B[Page API / ElementHandle API]
    B --> C[Protocol-Agnostic Input Interface]
    C --> D[CDP Implementation<br/>packages/puppeteer-core/src/cdp/Input.ts]
    C --> E[BiDi Implementation<br/>packages/puppeteer-core/src/bidi/Input.ts]
    D --> F[Chrome DevTools Protocol]
    E --> G[WebDriver BiDi Protocol]
    F --> H[Browser Instance]
    G --> H

The system is organized around three core input interfaces defined in the abstract layer:

InterfacePurpose
KeyboardSimulates keyboard input including key presses, typing, and modifier keys
MouseControls mouse movement, clicking, and wheel scrolling
TouchSimulates touch-based interactions on mobile devices
DragAndDropManages drag source and drop target operations

Sources: packages/puppeteer-core/src/api/Input.ts:1-200

Keyboard Input

Keyboard Interface Methods

The Keyboard interface provides four primary methods for simulating keyboard input:

MethodDescription
down(key, options?)Presses a key down without releasing it
up(key)Releases a pressed key
type(text, options?)Types text character by character
press(key, options?)Combines down + up (with optional delay)

Sources: packages/puppeteer-core/src/api/Input.ts:47-75

Key Input Values

Puppeteer uses the KeyInput enum to define all supported keyboard keys. Common values include:

  • Modifier Keys: Alt, Control, Meta, Shift
  • Arrow Keys: ArrowUp, ArrowDown, ArrowLeft, ArrowRight
  • Function Keys: F1 through F12
  • Special Keys: Enter, Tab, Escape, Backspace, Delete, Space
  • Alpha-Numeric: Standard letter and number keys (e.g., a, A, 1)

Type vs Press

The type() method sends keydown, keypress/input, and keyup events for each character in the text. Unlike press(), modifier keys do not affect type() - holding Shift will not type uppercase characters.

await page.keyboard.type('Hello'); // Types instantly
await page.keyboard.type('World', {delay: 100}); // Types with 100ms between each key

The press() method is a shortcut combining down() and up(). If the key is a single character with no modifiers besides Shift, a keypress/input event is also generated.

await page.keyboard.press('Enter');
await page.keyboard.press('Control', {delay: 100});
await page.keyboard.press('KeyA', {text: 'a'});

Sources: packages/puppeteer-core/src/api/Input.ts:35-75

Keyboard Options

OptionTypeDescription
delaynumberTime in milliseconds between keydown and keyup (default: 0)
textstringForces an input event with this text
commandsstring[]Browser command names for keyboard shortcuts

Sources: packages/puppeteer-core/src/api/Input.ts:26-33

Mouse Input

Mouse Interface Methods

The Mouse interface provides precise control over cursor movement and clicking:

MethodDescription
move(x, y, options?)Moves the mouse to the specified coordinates
down(options?)Presses the mouse button
up(options?)Releases the mouse button
click(x, y, options?)Performs a full click (down + up) at coordinates
wheel(options?)Scrolls the page

Sources: packages/puppeteer-core/src/api/Input.ts:92-132

Mouse Click Options

OptionTypeDefaultDescription
buttonMouseButton'left'Which button to click
clickCountnumber1Number of clicks (for double-click)
delaynumber0Delay between mousedown and mouseup in ms

Sources: packages/puppeteer-core/src/api/Input.ts:135-155

Mouse Move Options

OptionTypeDefaultDescription
stepsnumber1Number of intermediate mouse moves for smooth transitions

Sources: packages/puppeteer-core/src/api/Input.ts:157-170

Mouse Wheel Options

OptionTypeDefaultDescription
deltaXnumber0Horizontal scroll amount
deltaYnumber0Vertical scroll amount

Sources: packages/puppeteer-core/src/api/Input.ts:172-187

Click Workflow

sequenceDiagram
    participant User
    participant Mouse as Mouse Interface
    participant Page as Page
    
    User->>Mouse: click(x, y, {button: 'left', clickCount: 2})
    Mouse->>Page: mouseMoved(x, y)
    Mouse->>Page: mousePressed(x, y, button: 'left', clickCount: 1)
    Mouse->>Page: mouseReleased(x, y, button: 'left', clickCount: 1)
    Mouse->>Page: mousePressed(x, y, button: 'left', clickCount: 2)
    Mouse->>Page: mouseReleased(x, y, button: 'left', clickCount: 2)

Touch Input

The Touch interface simulates touch interactions for mobile device testing:

MethodDescription
tap(x, y)Performs a tap at the specified coordinates
touchStart(x, y)Starts a touch at the coordinates
touchMove(x, y)Moves the touch to new coordinates
touchEnd()Ends the current touch sequence

Sources: packages/puppeteer-core/src/api/Input.ts:194-210

Drag and Drop

The DragAndDrop interface handles drag interactions:

MethodDescription
drag(source, destination)Drags from source to destination, returns drag data
drop(x, y, data)Drops data at the specified coordinates

Sources: packages/puppeteer-core/src/api/Input.ts:212-220

High-Level Element Interactions

For common use cases, Puppeteer provides convenience methods on Page and ElementHandle that handle input internally.

Page-Level Input

The Page class exposes input methods that operate on the main frame:

// Type text into an element
await page.type('#mytextarea', 'Hello');
await page.type('#mytextarea', 'World', {delay: 100});

// Press a special key
await page.keyboard.press('Enter');
await page.keyboard.press('ArrowDown');

Sources: packages/puppeteer-core/src/api/Page.ts:1800-1820

ElementHandle Input

ElementHandle provides element-specific input methods:

const element = await page.$('#input-field');

// Focus the element and type
await element.type('Hello');

// Focus the element and press a key
await element.press('Enter');

Both methods automatically focus the element before performing the input action:

async type(
  text: string,
  options?: Readonly<KeyboardTypeOptions>,
): Promise<void> {
  await this.focus();
  await this.frame.page().keyboard.type(text, options);
}

async press(
  key: KeyInput,
  options?: Readonly<KeyPressOptions>,
): Promise<void> {
  await this.focus();
  await this.frame.page().keyboard.press(key, options);
}

Sources: packages/puppeteer-core/src/api/ElementHandle.ts:620-640

Implementation Strategies

CDP Implementation

The Chrome DevTools Protocol implementation translates abstract input calls into CDP commands:

The CDP implementation handles the translation of keyboard codes using US keyboard layout definitions.

BiDi Implementation

The WebDriver BiDi implementation uses the BiDi specification's input module:

  • Maps to BiDi input.performActions command
  • Handles serialization of input actions across the protocol wire

US Keyboard Layout

The USKeyboardLayout module provides key code mappings for US keyboards:

export const USKeyboardLayout: Map<string, number> = new Map([
  ['a', 0x61],
  ['A', 0x41],
  ['b', 0x62],
  // ... additional mappings
]);

Sources: packages/puppeteer-core/src/common/USKeyboardLayout.ts:1-100

Best Practices

  1. Use press() for special keys: Instead of type() for special characters, use press() with key names like Enter, Tab, or Escape.
  1. Add delays for realistic simulation: When testing UI behavior that depends on timing, use the delay option:

``typescript await page.type('#search', 'query', {delay: 100}); ``

  1. Focus elements before typing: When using ElementHandle input methods, the element is automatically focused. For direct keyboard access, ensure the target is focused first.
  1. Use click() over down()/up(): The click() method handles the complete click lifecycle and is less error-prone.
  1. Consider Locator API for reliability: For improved reliability in element interactions, consider using Puppeteer's experimental Locators API.
ComponentPurpose
PageExposes input methods on the main frame
ElementHandleElement-specific keyboard input
FrameFrame-level input access
KeyboardLow-level keyboard simulation
MouseLow-level mouse control
TouchTouch interaction simulation
DragAndDropDrag and drop operations

Sources: [packages/puppeteer-core/src/api/Input.ts:1-200]()

Browser Launching

Related topics: Package Structure

Section Related Pages

Continue reading this section for the full explanation and source context.

Section Class Hierarchy

Continue reading this section for the full explanation and source context.

Section Browser Launch Flow

Continue reading this section for the full explanation and source context.

Section Core Configuration

Continue reading this section for the full explanation and source context.

Related topics: Package Structure

Browser Launching

Overview

Browser launching is a core system in Puppeteer that handles the initialization and lifecycle management of browser instances. This system provides a unified interface for launching different browser types (Chrome, Firefox) while abstracting platform-specific details and managing process signals, timeouts, and executable paths.

The browser launching subsystem consists of several key components:

  • BrowserLauncher: Abstract base class defining the launching interface
  • ChromeLauncher: Implementation for Chrome/Chromium-based browsers
  • FirefoxLauncher: Implementation for Firefox
  • @puppeteer/browsers: Standalone package for programmatic browser management

Architecture

Class Hierarchy

graph TD
    A[BrowserLauncher] --> B[ChromeLauncher]
    A --> C[FirefoxLauncher]
    D[launch.ts] --> E[Browser Process]
    F[install.ts] --> G[Browser Binaries]
    
    style A fill:#e1f5fe
    style B fill:#e8f5e8
    style C fill:#fff3e0

Browser Launch Flow

sequenceDiagram
    participant User
    participant Puppeteer
    participant BrowserLauncher
    participant BrowserProcess
    participant CDP
    
    User->>Puppeteer: puppeteer.launch(options)
    Puppeteer->>BrowserLauncher: createLauncher(options)
    BrowserLauncher->>BrowserLauncher: resolveExecutablePath()
    BrowserLauncher->>BrowserLauncher: buildArguments()
    BrowserLauncher->>BrowserProcess: spawn(executable, args)
    BrowserProcess-->>BrowserLauncher: process started
    BrowserLauncher->>BrowserLauncher: setupSignalHandlers()
    BrowserLauncher->>CDP: connect(wsEndpoint)
    CDP-->>Puppeteer: Browser instance
    User->>Puppeteer: browser operations
    User->>Puppeteer: browser.close()
    Puppeteer->>BrowserProcess: terminate()

Launch Options

The LaunchOptions interface defines all configuration parameters available when launching a browser. These options control executable selection, argument passing, signal handling, and timeout behavior.

Core Configuration

OptionTypeDefaultDescription
executablePathstringbundled browserPath to a specific browser executable. When using this, Puppeteer cannot guarantee compatibility.
ignoreDefaultArgs`boolean \string[]`falseControls whether default arguments are passed to the browser. Array mode filters specific args.
enableExtensions`boolean \string[]`falseEnables browser extensions. String array loads extensions from paths.

Signal Handling

Puppeteer manages browser process lifecycle through POSIX signal handling:

OptionTypeDefaultDescription
handleSIGINTbooleantrueClose browser on Ctrl+C (SIGINT)
handleSIGTERMbooleantrueClose browser on termination signal (SIGTERM)
handleSIGHUPbooleantrueClose browser on terminal hangup (SIGHUP)

Timeout Configuration

OptionTypeDefaultDescription
timeoutnumber30,000 (30 seconds)Maximum time in milliseconds to wait for browser startup. Pass 0 to disable timeout.

Browser Installation

CLI Installation

The @puppeteer/browsers package provides command-line tools for downloading and managing browser binaries:

# Download latest stable Chrome
npx @puppeteer/browsers install chrome@stable

# Download specific version
npx @puppeteer/browsers install [email protected]

# Download by milestone
npx @puppeteer/browsers install chrome@117

# Download ChromeDriver
npx @puppeteer/browsers install chromedriver@canary

# List installed browsers
npx @puppeteer/browsers list

# Clear all browsers
npx @puppeteer/browsers clear

Configuration Options

The Configuration interface controls download behavior:

OptionEnvironment VariableDefaultDescription
skipDownloadPUPPETEER_SKIP_DOWNLOADfalseSkip browser download during installation
temporaryDirectoryPUPPETEER_TMP_DIRos.tmpdir()Directory for temporary files
logLevel-warnLogging level: silent, error, warn

Browser-Specific Settings

Each browser type supports independent configuration:

BrowserSkip Download Env VarDownload Base URL Env VarVersion Env Var
ChromePUPPETEER_CHROME_SKIP_DOWNLOADPUPPETEER_CHROME_DOWNLOAD_BASE_URLPUPPETEER_CHROME_VERSION
Chrome Headless ShellPUPPETEER_CHROME_HEADLESS_SHELL_SKIP_DOWNLOADPUPPETEER_CHROME_HEADLESS_SHELL_DOWNLOAD_BASE_URL-
FirefoxPUPPETEER_FIREFOX_SKIP_DOWNLOADPUPPETEER_FIREFOX_DOWNLOAD_BASE_URLPUPPETEER_FIREFOX_VERSION

Download Base URLs

BrowserDefault URL
Chromehttps://storage.googleapis.com/chrome-for-testing-public
Firefoxhttps://archive.mozilla.org/pub/firefox/releases

Chrome Launcher

The ChromeLauncher handles launching Chrome and Chromium-based browsers. It manages the Chrome DevTools Protocol (CDP) connection and applies Chrome-specific default arguments.

Key Responsibilities

  1. Executable Resolution: Locates the Chrome executable based on platform and configuration
  2. Argument Construction: Builds the complete argument list including default Chrome flags
  3. Profile Management: Creates temporary user data directories for isolated browser contexts
  4. CDP Connection: Establishes WebSocket connection to the browser's DevTools interface

Default Arguments

Chrome Launcher automatically includes secure defaults:

  • --no-sandbox (when not running as root on Linux)
  • --disable-dev-shm-usage (prevents crashes in Docker environments)
  • Remote debugging port selection

Firefox Launcher

The FirefoxLauncher provides Firefox-specific launching capabilities with support for Mozilla's remote debugging protocol.

Differences from Chrome

  • Uses Firefox's built-in DevTools protocol instead of CDP
  • Handles Firefox-specific argument syntax
  • Manages Firefox profile creation and cleanup

Browser Management

Programmatic Browser Management

The @puppeteer/browsers package allows programmatic browser control:

import {install, launch, clear, Browser} from '@puppeteer/browsers';

async function setupBrowser() {
  // Install browser
  const installOpts = {
    browser: Browser.CHROME,
    buildId: 'stable',
    cacheDir: './browser-cache'
  };
  
  await install(installOpts);
  
  // Launch browser
  const launchOpts = {
    executablePath: await getExecutablePath(installOpts),
    args: ['--no-sandbox']
  };
  
  const browserProcess = await launch(launchOpts);
  return browserProcess;
}

Browser Cleanup

Browsers installed by Puppeteer can be automatically cleaned up during version updates:

graph TD
    A[Puppeteer Launch] --> B[Load Installed Browsers]
    B --> C{Is Browser Current?}
    C -->|Yes| D[Keep Browser]
    C -->|No| E[Uninstall Old Build]
    F[New Version Available] --> C

The cleanup process:

  1. Compares installed browser versions against Puppeteer's pinned versions
  2. Identifies browsers no longer managed by current Puppeteer
  3. Removes outdated browser builds using uninstall() with buildId and platform

Signal Handling Lifecycle

stateDiagram-v2
    [*] --> Launching: launch()
    Launching --> Running: Browser Started
    Running --> Closing: close() / SIGINT / SIGTERM / SIGHUP
    Closing --> [*]: Process Terminated
    
    Running --> Running: New Page Created

Signal Handler Configuration

SignalDefaultPurpose
SIGINTEnabledCtrl+C interruption
SIGTERMEnabledProcess termination
SIGHUPEnabledTerminal disconnect

Disabling signal handlers is possible but not recommended as it may leave orphaned browser processes:

const browser = await puppeteer.launch({
  handleSIGINT: false,
  handleSIGTERM: false,
  handleSIGHUP: false
});

Timeout Behavior

graph LR
    A[launch()] --> B{timeout > 0?}
    B -->|Yes| C[Wait ms]
    B -->|No| D[No Timeout]
    C --> E{Browser Ready?}
    E -->|Yes| F[Return Browser]
    E -->|No| G[Throw Timeout Error]
    D --> F

Timeout of 0 disables the startup timeout entirely, useful for:

  • Debugging launch issues
  • Slow systems with many browser dependencies
  • Long initialization sequences

Best Practices

  1. Always use await browser.close() to properly terminate browser processes
  2. Set reasonable timeouts for production environments
  3. Use bundled browsers for guaranteed compatibility
  4. Enable signal handlers (default) for clean shutdowns
  5. Use --no-sandbox only when necessary for containerized environments
ComponentPurpose
PageBrowser page/tab abstraction
BrowserContextIsolated browser sessions
HTTPRequest/HTTPResponseNetwork request handling
TimeoutSettingsConfigurable timeout management

Source References

Source: https://github.com/puppeteer/puppeteer / Human Manual

Doramagic Pitfall Log

Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.

high Chrome Canary/Firefox Nightly test results

First-time setup may fail or require extra isolation and rollback planning.

high Puppeteer v25

First-time setup may fail or require extra isolation and rollback planning.

high [Bug]: GHSA issued a false malicious package alert for puppeteer

The project may affect permissions, credentials, data exposure, or host boundaries.

high [Task]: Flaky `[fixtures.spec] Fixtures should dump browser process stderr`

The project may affect permissions, credentials, data exposure, or host boundaries.

Doramagic Pitfall Log

Doramagic extracted 16 source-linked risk signals. Review them before installing or handing real data to the project.

1. Installation risk: Chrome Canary/Firefox Nightly test results

  • Severity: high
  • Finding: Installation risk is backed by a source signal: Chrome Canary/Firefox Nightly test results. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/puppeteer/puppeteer/issues/12379

2. Installation risk: Puppeteer v25

  • Severity: high
  • Finding: Installation risk is backed by a source signal: Puppeteer v25. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/puppeteer/puppeteer/issues/14342

3. Security or permission risk: [Bug]: GHSA issued a false malicious package alert for puppeteer

  • Severity: high
  • Finding: Security or permission risk is backed by a source signal: [Bug]: GHSA issued a false malicious package alert for puppeteer. Treat it as a review item until the current version is checked.
  • User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/puppeteer/puppeteer/issues/14986

4. Security or permission risk: [Task]: Flaky `[fixtures.spec] Fixtures should dump browser process stderr`

  • Severity: high
  • Finding: Security or permission risk is backed by a source signal: [Task]: Flaky [fixtures.spec] Fixtures should dump browser process stderr. Treat it as a review item until the current version is checked.
  • User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/puppeteer/puppeteer/issues/14774

5. Installation risk: [Bug]: @puppeteer/browsers silently corrupts Chrome cache on Node.js 26 (extract-zip 2.0.1)

  • Severity: medium
  • Finding: Installation risk is backed by a source signal: [Bug]: @puppeteer/browsers silently corrupts Chrome cache on Node.js 26 (extract-zip 2.0.1). Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/puppeteer/puppeteer/issues/14957

6. Installation risk: [Bug]: `setViewport` crashes on Firefox if uncaught

  • Severity: medium
  • Finding: Installation risk is backed by a source signal: [Bug]: setViewport crashes on Firefox if uncaught. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/puppeteer/puppeteer/issues/14989

7. Installation risk: [Bug]: chrome binary is not present when installing latest chrome

  • Severity: medium
  • Finding: Installation risk is backed by a source signal: [Bug]: chrome binary is not present when installing latest chrome. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/puppeteer/puppeteer/issues/14988

8. Installation risk: [Feature]: Make proxy-agent dependency optional

  • Severity: medium
  • Finding: Installation risk is backed by a source signal: [Feature]: Make proxy-agent dependency optional. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/puppeteer/puppeteer/issues/13775

9. Installation risk: browsers: v3.0.0

  • Severity: medium
  • Finding: Installation risk is backed by a source signal: browsers: v3.0.0. Treat it as a review item until the current version is checked.
  • User impact: First-time setup may fail or require extra isolation and rollback planning.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/puppeteer/puppeteer/releases/tag/browsers-v3.0.0

10. Capability assumption: browsers: v3.0.2

  • Severity: medium
  • Finding: Capability assumption is backed by a source signal: browsers: v3.0.2. Treat it as a review item until the current version is checked.
  • User impact: The project should not be treated as fully validated until this signal is reviewed.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/puppeteer/puppeteer/releases/tag/browsers-v3.0.2

11. Capability assumption: puppeteer-core: v25.0.2

  • Severity: medium
  • Finding: Capability assumption is backed by a source signal: puppeteer-core: v25.0.2. Treat it as a review item until the current version is checked.
  • User impact: The project should not be treated as fully validated until this signal is reviewed.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: Source-linked evidence: https://github.com/puppeteer/puppeteer/releases/tag/puppeteer-core-v25.0.2

12. Capability assumption: README/documentation is current enough for a first validation pass.

  • Severity: medium
  • Finding: README/documentation is current enough for a first validation pass.
  • User impact: The project should not be treated as fully validated until this signal is reviewed.
  • Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
  • Evidence: capability.assumptions | github_repo:90796663 | https://github.com/puppeteer/puppeteer | README/documentation is current enough for a first validation pass.

Source: Doramagic discovery, validation, and Project Pack records

Community Discussion Evidence

These external discussion links are review inputs, not standalone proof that the project is production-ready.

Sources 12

Count of project-level external discussion links exposed on this manual page.

Use Review before install

Open the linked issues or discussions before treating the pack as ready for your environment.

Community Discussion Evidence

Doramagic exposes project-level community discussion separately from official documentation. Review these links before using puppeteer with real data or production workflows.

  • [[Bug]: GHSA issued a false malicious package alert for puppeteer](https://github.com/puppeteer/puppeteer/issues/14986) - github / github_issue
  • Chrome Canary/Firefox Nightly test results - github / github_issue
  • [[Bug]: setViewport crashes on Firefox if uncaught](https://github.com/puppeteer/puppeteer/issues/14989) - github / github_issue
  • [[Bug]: chrome binary is not present when installing latest chrome](https://github.com/puppeteer/puppeteer/issues/14988) - github / github_issue
  • [[Bug]: @puppeteer/browsers silently corrupts Chrome cache on Node.js 26](https://github.com/puppeteer/puppeteer/issues/14957) - github / github_issue
  • [[Task]: Flaky `[fixtures.spec] Fixtures should dump browser process stde](https://github.com/puppeteer/puppeteer/issues/14774) - github / github_issue
  • [[Feature]: Reducing dependencies](https://github.com/puppeteer/puppeteer/issues/13552) - github / github_issue
  • [[Feature]: Make proxy-agent dependency optional](https://github.com/puppeteer/puppeteer/issues/13775) - github / github_issue
  • Puppeteer v25 - github / github_issue
  • puppeteer-core: v25.0.2 - github / github_release
  • browsers: v3.0.2 - github / github_release
  • puppeteer-core: v25.0.1 - github / github_release

Source: Project Pack community evidence and pitfall evidence