A modular plugin framework for Playwright to enable enhanced browser automation through plugins.
npx @tessl/cli install tessl/npm-playwright-extra@4.3.0Playwright Extra is a modular plugin framework for Playwright that extends browser automation capabilities through a clean plugin interface. It serves as a drop-in replacement for the standard Playwright library, adding plugin functionality while maintaining full compatibility with Playwright's API. The framework supports multiple browsers (Chromium, Firefox, WebKit) and enables easy integration of various automation enhancements such as stealth mode, CAPTCHA solving, and other browser automation tricks.
npm install playwright playwright-extraimport { chromium, firefox, webkit, addExtra } from "playwright-extra";For CommonJS:
const { chromium, firefox, webkit, addExtra } = require("playwright-extra");Re-exported Playwright modules:
import { devices, errors, selectors, request, _android, _electron } from "playwright-extra";import { chromium } from "playwright-extra";
import StealthPlugin from "puppeteer-extra-plugin-stealth";
// Add plugins to the browser launcher
chromium.use(StealthPlugin());
// Use exactly like standard Playwright
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
await page.goto("https://example.com");
await page.screenshot({ path: "screenshot.png" });
await browser.close();Playwright Extra is built around several key components:
chromium, firefox, and webkit with plugin functionalityEnhanced browser launchers that provide the same API as standard Playwright with additional plugin functionality. Each launcher supports plugin registration and manages plugin lifecycle events.
const chromium: AugmentedBrowserLauncher;
const firefox: AugmentedBrowserLauncher;
const webkit: AugmentedBrowserLauncher;
interface AugmentedBrowserLauncher extends PlaywrightBrowserLauncher {
use(plugin: CompatiblePlugin): this;
plugins: PluginList;
}Create independent plugin-enabled instances from any compatible Playwright launcher. Useful when you need multiple instances with different plugin configurations.
function addExtra<Launcher extends PlaywrightCompatibleLauncher>(
launcher?: Launcher
): PlaywrightExtraClass & Launcher;
interface PlaywrightCompatibleLauncher {
connect(...args: any[]): Promise<any>;
launch(...args: any[]): Promise<any>;
}Comprehensive plugin management system supporting plugin registration, dependency resolution, lifecycle management, and error handling.
class PluginList {
readonly list: Plugin[];
readonly names: string[];
add(plugin: Plugin): boolean;
setDependencyDefaults(dependencyPath: string, opts: any): this;
setDependencyResolution(dependencyPath: string, pluginModule: CompatiblePluginModule): this;
onPluginError(plugin: Plugin, method: PluginMethodName, err: Error): void;
}Interfaces and types for creating compatible plugins that work with both Playwright Extra and puppeteer-extra. Includes lifecycle methods and compatibility requirements.
interface PuppeteerExtraPlugin extends Partial<PluginLifecycleMethods> {
_isPuppeteerExtraPlugin: boolean;
name: string;
noPuppeteerShim?: boolean;
requirements?: PluginRequirements;
dependencies?: PluginDependencies;
}
abstract class PluginLifecycleMethods {
async onPluginRegistered(env?: PluginEnv): Promise<void>;
async beforeLaunch(options: LaunchOptions): Promise<LaunchOptions | void>;
async afterLaunch(browserOrContext?: Browser | BrowserContext): Promise<void>;
async beforeConnect(options: ConnectOptions): Promise<ConnectOptions | void>;
async afterConnect(browser: Browser): Promise<void>;
async onBrowser(browser: Browser): Promise<void>;
async onPageCreated(page: Page): Promise<void>;
async onPageClose(page: Page): Promise<void>;
async onDisconnected(browser?: Browser): Promise<void>;
async beforeContext(options?: BrowserContextOptions, browser?: Browser): Promise<BrowserContextOptions | void>;
async onContextCreated(context?: BrowserContext, options?: BrowserContextOptions): Promise<void>;
}Compatibility layer that allows puppeteer-extra plugins to work seamlessly with Playwright by providing a shim layer that translates Playwright objects to Puppeteer-compatible interfaces.
function addPuppeteerCompat<Input extends Page | Frame | Browser | null>(
object: Input
): Input;
interface PuppeteerBrowserShim {
isCompatShim?: boolean;
isPlaywright?: boolean;
pages?: BrowserContext['pages'];
userAgent(): Promise<string>;
}
interface PuppeteerPageShim {
isCompatShim?: boolean;
isPlaywright?: boolean;
browser?(): Browser;
evaluateOnNewDocument?: Page['addInitScript'];
_client(): CDPSession;
}type CompatiblePlugin =
| CompatiblePuppeteerPlugin
| CompatiblePlaywrightPlugin
| CompatibleExtraPlugin;
type PluginMethodName = keyof PluginLifecycleMethods;
type PluginRequirements = Set<'launch' | 'headful' | 'dataFromPlugins' | 'runLast'>;
type PluginDependencies = Set<string> | Map<string, any> | string[];
interface PluginEnv {
framework: 'playwright';
}Playwright Extra re-exports all standard Playwright APIs with lazy loading:
/** Standard Playwright device descriptors */
const devices: typeof import('playwright-core').devices;
/** Playwright error classes */
const errors: typeof import('playwright-core').errors;
/** Playwright selectors engine */
const selectors: typeof import('playwright-core').selectors;
/** Playwright request API */
const request: typeof import('playwright-core').request;
/** Android device support (lazy-loaded) */
const _android: typeof import('playwright-core')._android;
/** Electron app support (lazy-loaded) */
const _electron: typeof import('playwright-core')._electron;