CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-playwright-extra

A modular plugin framework for Playwright to enable enhanced browser automation through plugins.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

puppeteer-compatibility.mddocs/

Puppeteer Compatibility

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.

Capabilities

Add Puppeteer Compatibility

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();

Browser Compatibility Shim

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');
}

Page Compatibility Shim

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")'
});

CDP Session Management

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); // 4

Advanced Compatibility Features

The 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);

Compatibility Detection

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);
}

Plugin Integration

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
  }
}

Disabling Compatibility

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');
  }
}

Core Types

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

docs

browser-launchers.md

custom-integration.md

index.md

plugin-development.md

plugin-management.md

puppeteer-compatibility.md

tile.json