@zorilla/playwright-extra
v1.0.1
Published
Teach playwright new tricks through plugins.
Maintainers
Readme
playwright-extra

A modular plugin framework for playwright to enable cool plugins through a clean interface.
Part of the zorilla monorepo - a maintained fork of puppeteer-extra with modern tooling and ESM support.
Requirements
- Node.js 20+ (ESM only)
- Playwright 1.x
Installation
npm install playwright playwright-extraAfter installing, make sure to install the Playwright browsers:
npx playwright installQuickstart
// playwright-extra is a drop-in replacement for playwright,
// it augments the installed playwright with plugin functionality
import { chromium } from 'playwright-extra'
// Load the stealth plugin and use defaults (all tricks to hide playwright usage)
// Note: playwright-extra is compatible with most puppeteer-extra plugins
import StealthPlugin from '@zorilla/puppeteer-extra-plugin-stealth'
// Add the plugin to playwright (any number of plugins can be added)
chromium.use(StealthPlugin())
// That's it, the rest is playwright usage as normal 😊
const browser = await chromium.launch({ headless: true })
const page = await browser.newPage()
console.log('Testing the stealth plugin..')
await page.goto('https://bot.sannysoft.com', { waitUntil: 'networkidle' })
await page.screenshot({ path: 'stealth.png', fullPage: true })
console.log('All done, check the screenshot. ✨')
await browser.close()The above example uses the compatible stealth plugin, which needs to be installed as well:
npm install @zorilla/puppeteer-extra-plugin-stealthIf you'd like to see debug output just run your script like so:
# macOS/Linux (Bash)
DEBUG=playwright-extra*,puppeteer-extra-plugin* node myscript.js
# Windows (Powershell)
$env:DEBUG='playwright-extra*,puppeteer-extra-plugin*'; node myscript.jsMore examples
playwright-extra and most plugins are written in TS, so you get perfect type support out of the box. :)
import { chromium } from 'playwright-extra'
import StealthPlugin from '@zorilla/puppeteer-extra-plugin-stealth'
chromium.use(StealthPlugin())
const browser = await chromium.launch({ headless: true })
const page = await browser.newPage()
console.log('Testing the stealth plugin..')
await page.goto('https://bot.sannysoft.com', { waitUntil: 'networkidle' })
await page.screenshot({ path: 'stealth.png', fullPage: true })
console.log('All done, check the screenshot. ✨')
await browser.close()New to TypeScript? Here's a quick setup:
# Create new package.json if it's a new project
pnpm init
# Add TypeScript and dependencies
pnpm add -D typescript @types/node tsx
# Add dependencies used in the quick start example
pnpm add playwright playwright-extra @zorilla/puppeteer-extra-plugin-stealth
# Create a TypeScript config
pnpm tsc --init
# Create source folder for the .ts files
mkdir src
# Now place the example code above in `src/index.ts`
# Run the TypeScript code directly (no compilation needed)
pnpm tsx src/index.ts// Any browser supported by playwright can be used with plugins
import { chromium, firefox, webkit } from 'playwright-extra'
chromium.use(plugin)
firefox.use(plugin)
webkit.use(plugin)Node.js imports are cached, therefore the default chromium, firefox, webkit exports from playwright-extra will always return the same playwright instance.
// Use `addExtra` to create fresh and independent instances
import playwright from 'playwright'
import { addExtra } from 'playwright-extra'
const chromium1 = addExtra(playwright.chromium)
const chromium2 = addExtra(playwright.chromium)
chromium1.use(pluginA)
chromium2.use(pluginB)
// chromium1 and chromium2 are independent instancesPlugins
The following plugins are compatible with playwright-extra:
🔥 @zorilla/puppeteer-extra-plugin-stealth
- Applies various evasion techniques to make detection of automated browsers harder
- Compatible with Puppeteer & Playwright and chromium-based browsers
// The stealth plugin is optimized for chromium based browsers
import { chromium } from 'playwright-extra'
import StealthPlugin from '@zorilla/puppeteer-extra-plugin-stealth'
chromium.use(StealthPlugin())
// Customize options for specific evasion techniques
chromium.plugins.setDependencyDefaults('stealth/evasions/webgl.vendor', {
vendor: 'Bob',
renderer: 'Alice'
})
// That's it, the rest is playwright usage as normal 😊
const browser = await chromium.launch({ headless: true })
const page = await browser.newPage()
console.log('Testing the webgl spoofing feature of the stealth plugin..')
await page.goto('https://webglreport.com', { waitUntil: 'networkidle' })
await page.screenshot({ path: 'webgl.png', fullPage: true })
console.log('All done, check the screenshot. ✨')
await browser.close()🏴 puppeteer-extra-plugin-recaptcha
- Solves reCAPTCHAs and hCaptchas automatically, using a single line of code:
page.solveRecaptchas() - Compatible with Puppeteer & Playwright and all browsers (chromium, firefox, webkit)
// Any browser (chromium, webkit, firefox) can be used
import { firefox } from 'playwright-extra'
import RecaptchaPlugin from 'puppeteer-extra-plugin-recaptcha'
firefox.use(
RecaptchaPlugin({
provider: {
id: '2captcha',
token: process.env.TWOCAPTCHA_TOKEN || 'YOUR_API_KEY'
}
})
)
// Works in headless as well
const browser = await firefox.launch({ headless: false })
const context = await browser.newContext()
const page = await context.newPage()
await page.goto('https://www.google.com/recaptcha/api2/demo', {
waitUntil: 'networkidle'
})
console.log('Solving captchas..')
await page.solveRecaptchas()
await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle' }),
page.click('#recaptcha-demo-submit')
])
const content = await page.content()
const isSuccess = content.includes('Verification Success')
console.log('Done', { isSuccess })
await browser.close()📡 @zorilla/plugin-proxy-router
- Use multiple proxies dynamically with flexible per-host routing
- Compatible with Puppeteer & Playwright and all browsers (chromium, firefox, webkit)
🔌 @zorilla/puppeteer-extra-plugin-anonymize-ua
- Anonymizes the user-agent on all pages
- Compatible with Puppeteer & Playwright
Additional Resources
- For adblocking, consider using @cliqz/adblocker-playwright or blocking resources natively
- To write your own plugins, check out the
@zorilla/puppeteer-extra-pluginbase class
Development
This package is part of the zorilla monorepo and uses:
- TypeScript for type safety (ESM only, no CommonJS support)
- Playwright Test for testing across chromium, firefox, and webkit
- c8 for coverage reporting
- Biome for linting and formatting
Building and Testing
# Install dependencies (from monorepo root)
pnpm install
# Build the package
pnpm build
# Run tests (requires Playwright browsers to be installed)
pnpm test
# Run tests with coverage
pnpm test:coverageCode Quality
# Check code formatting and linting
npx biome check .
# Auto-fix formatting issues
npx biome check --write .Browser Installation
Tests require Playwright browsers. Install them with:
pnpm exec playwright installAPI
Default Export
The package exports augmented browser launchers that work as drop-in replacements for playwright:
import { chromium, firefox, webkit } from 'playwright-extra'addExtra(launcher)
Create a fresh playwright-extra instance with its own plugin registry:
import { addExtra } from 'playwright-extra'
import playwright from 'playwright'
const chromium = addExtra(playwright.chromium)launcher.use(plugin)
Register a plugin with the browser launcher:
chromium.use(StealthPlugin())launcher.plugins
Access the plugin registry to configure plugins:
// Set default options for a plugin dependency
chromium.plugins.setDependencyDefaults('stealth/evasions/webgl.vendor', {
vendor: 'Custom',
renderer: 'Custom'
})
// List registered plugins
console.log(chromium.plugins.names)