A modular plugin framework for Playwright to enable enhanced browser automation through plugins.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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. This enables reuse of the extensive puppeteer-extra plugin ecosystem.
Augment Playwright objects with compatibility methods for Puppeteer plugins.
/**
* Augment a Playwright object with compatibility with certain Puppeteer methods
* @param object - Playwright Page, Frame, Browser, or null
* @returns The same object enhanced with Puppeteer compatibility methods
*/
function addPuppeteerCompat<Input extends Page | Frame | Browser | null>(
object: Input
): Input;Usage Examples:
import { addPuppeteerCompat } from "playwright-extra";
import { chromium } from "playwright";
// Manually add compatibility to Playwright objects
const browser = await chromium.launch();
const compatBrowser = addPuppeteerCompat(browser);
// Now browser has puppeteer-style methods
const userAgent = await compatBrowser.userAgent();
const pages = await compatBrowser.pages();Enhanced browser interface that provides Puppeteer-compatible methods for browser objects.
interface PuppeteerBrowserShim {
/** Indicates this is a compatibility shim */
isCompatShim?: boolean;
/** Indicates this is a Playwright object */
isPlaywright?: boolean;
/** Get all pages across all browser contexts */
pages?: BrowserContext['pages'];
/** Get the browser's user agent string */
userAgent(): Promise<string>;
}Usage Examples:
import { chromium } from "playwright-extra";
const browser = await chromium.launch();
// Puppeteer-style methods available on browser
const userAgent = await browser.userAgent();
console.log('User agent:', userAgent);
// Get all pages across contexts (Puppeteer style)
const pages = await browser.pages();
console.log('All pages:', pages.length);
// Check if object is shimmed
if (browser.isCompatShim) {
console.log('Browser has Puppeteer compatibility');
}Enhanced page and frame interface that provides Puppeteer-compatible methods.
interface PuppeteerPageShim {
/** Indicates this is a compatibility shim */
isCompatShim?: boolean;
/** Indicates this is a Playwright object */
isPlaywright?: boolean;
/** Get the browser instance (Puppeteer style) */
browser?(): Browser;
/** Puppeteer-style script evaluation on new documents */
evaluateOnNewDocument?: Page['addInitScript'];
/** Get CDP session client for advanced browser control */
_client(): CDPSession;
}Usage Examples:
import { chromium } from "playwright-extra";
const browser = await chromium.launch();
const page = await browser.newPage();
// Puppeteer-style browser access
const browserFromPage = page.browser();
console.log('Browser from page:', browserFromPage);
// Puppeteer-style script injection
await page.evaluateOnNewDocument(() => {
// This script runs on every new document
console.log('Script injected via Puppeteer compatibility');
});
// CDP client access for advanced control
const client = page._client();
await client.send('Runtime.evaluate', {
expression: 'console.log("CDP command executed")'
});The compatibility layer provides access to Chrome DevTools Protocol sessions for advanced browser control.
/**
* Get or create a CDP session for a page or frame
* @param page - Page or Frame object to get CDP session for
* @returns CDP session for the page/frame, or dummy client for non-Chromium browsers
*/
async function getPageCDPSession(page: Page | Frame): Promise<CDPSession>;
/**
* Get or create a CDP session for a browser
* @param browser - Browser object to get CDP session for
* @returns CDP session for the browser, or dummy client for non-Chromium browsers
*/
async function getBrowserCDPSession(browser: Browser): Promise<CDPSession>;
/**
* Create a compatibility shim for a page or frame object
* @param page - Page or Frame to enhance with Puppeteer compatibility
* @returns Enhanced page/frame with Puppeteer-compatible methods
*/
function createPageShim(page: Page | Frame): Page | Frame;
/**
* Create a compatibility shim for a browser object
* @param browser - Browser to enhance with Puppeteer compatibility
* @returns Enhanced browser with Puppeteer-compatible methods
*/
function createBrowserShim(browser: Browser): Browser;Usage Examples:
import { chromium } from "playwright-extra";
const browser = await chromium.launch();
const page = await browser.newPage();
// Access CDP through compatibility layer
const client = page._client();
// Send CDP commands
await client.send('Runtime.enable');
await client.send('Page.enable');
// Listen to CDP events
client.on('Runtime.consoleAPICalled', (event) => {
console.log('Console API called:', event);
});
// Execute JavaScript via CDP
const result = await client.send('Runtime.evaluate', {
expression: '2 + 2',
returnByValue: true
});
console.log('Result:', result.result.value); // 4The compatibility layer includes several advanced features for seamless integration:
User Agent Override:
import { chromium } from "playwright-extra";
const browser = await chromium.launch();
const page = await browser.newPage();
// Puppeteer-style user agent setting
await page.setUserAgent('Mozilla/5.0 (Custom Browser)');CSP Bypass:
import { chromium } from "playwright-extra";
const browser = await chromium.launch();
const page = await browser.newPage();
// Puppeteer-style CSP bypass
await page.setBypassCSP(true);Browser Version Info:
import { chromium } from "playwright-extra";
const browser = await chromium.launch();
// Get browser user agent (works even with launchPersistentContext)
const userAgent = await browser.userAgent();
console.log('Browser user agent:', userAgent);Utility functions to detect and work with compatibility-enhanced objects:
/**
* Check if an object is a Playwright Page
* @param obj - Object to check
* @returns true if object is a Playwright Page
*/
function isPlaywrightPage(obj: unknown): obj is Page;
/**
* Check if an object is a Playwright Frame
* @param obj - Object to check
* @returns true if object is a Playwright Frame
*/
function isPlaywrightFrame(obj: unknown): obj is Frame;
/**
* Check if an object is a Playwright Browser
* @param obj - Object to check
* @returns true if object is a Playwright Browser
*/
function isPlaywrightBrowser(obj: unknown): obj is Browser;
/**
* Check if an object has Puppeteer compatibility shim applied
* @param obj - Object to check
* @returns true if object has compatibility shim
*/
function isPuppeteerCompat(obj?: unknown): obj is PlaywrightObject;Usage Examples:
import {
isPlaywrightPage,
isPlaywrightBrowser,
isPuppeteerCompat
} from "playwright-extra";
const browser = await chromium.launch();
const page = await browser.newPage();
// Type detection
console.log('Is Playwright browser:', isPlaywrightBrowser(browser)); // true
console.log('Is Playwright page:', isPlaywrightPage(page)); // true
console.log('Has compat shim:', isPuppeteerCompat(browser)); // true
// Safe method access based on type
if (isPlaywrightBrowser(browser) && isPuppeteerCompat(browser)) {
const userAgent = await browser.userAgent();
console.log('User agent:', userAgent);
}The compatibility layer automatically applies to plugin lifecycle events:
class MyPuppeteerPlugin extends PuppeteerExtraPlugin {
constructor(opts = {}) {
super(opts);
}
get name() {
return 'my-puppeteer-plugin';
}
async onPageCreated(page) {
// page is automatically enhanced with Puppeteer compatibility
const browser = page.browser(); // Puppeteer-style method
const client = page._client(); // CDP client access
// Original Playwright methods still work
await page.goto('https://example.com');
}
async onBrowser(browser) {
// browser is automatically enhanced with compatibility
const pages = await browser.pages(); // Get all pages
const userAgent = await browser.userAgent(); // Get user agent
}
}Plugins can opt out of the compatibility layer if needed:
class NativePlaywrightPlugin extends PuppeteerExtraPlugin {
constructor(opts = {}) {
super(opts);
// Disable Puppeteer compatibility shim
this.noPuppeteerShim = true;
}
get name() {
return 'native-playwright-plugin';
}
async onPageCreated(page) {
// page is the raw Playwright page object
// No Puppeteer compatibility methods available
await page.goto('https://example.com');
}
}type PlaywrightObject = Page | Frame | Browser;
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;
}
interface CDPSession {
send(method: string, params?: any): Promise<any>;
on(event: string, listener: (...args: any[]) => void): void;
}Install with Tessl CLI
npx tessl i tessl/npm-playwright-extra