A light-weight wrapper around puppeteer
to enable cool plugins through a clean interface.
Installation
yarn add puppeteer puppeteer-extra
npm install puppeteer puppeteer-extra
You can also use a specific puppeteer version:
yarn add puppeteer@next puppeteer-extra
Quickstart
// puppeteer-extra is a drop-in replacement for puppeteer,
// it augments the installed puppeteer with plugin functionality.
// Any number of plugins can be added through `puppeteer.use()`
const puppeteer = require('puppeteer-extra')
// Add stealth plugin and use defaults (all tricks to hide puppeteer usage)
const StealthPlugin = require('puppeteer-extra-plugin-stealth')
puppeteer.use(StealthPlugin())
// Add plugin to anonymize the User-Agent and signal Windows as platform
const UserAgentPlugin = require('puppeteer-extra-plugin-anonymize-ua')
puppeteer.use(UserAgentPlugin({ makeWindows: true }))
// That's it, the rest is puppeteer usage as normal 😊
puppeteer.launch({ headless: true }).then(async browser => {
const page = await browser.newPage()
await page.setViewport({ width: 800, height: 600 })
console.log(`Testing the user agent plugin..`)
await page.goto('https://httpbin.org/headers')
await page.waitFor(1000)
await page.screenshot({ path: 'headers.png', fullPage: true })
console.log(`Testing the stealth plugin..`)
await page.goto('https://bot.sannysoft.com')
await page.waitFor(5000)
await page.screenshot({ path: 'stealth.png', fullPage: true })
console.log(`All done, check the screenshots. ✨`)
await browser.close()
})
The above example uses the stealth
and anonymize-ua
plugin, which need to be installed as well:
yarn add puppeteer-extra-plugin-stealth puppeteer-extra-plugin-anonymize-ua
npm install puppeteer-extra-plugin-stealth puppeteer-extra-plugin-anonymize-ua
If you'd like to see debug output just run your script like so:
DEBUG=puppeteer-extra,puppeteer-extra-plugin:* node myscript.js
Plugins
- Solves reCAPTCHAs automatically, using a single line of code:
page.solveRecaptchas()
.
- Applies various evasion techniques to make detection of headless puppeteer harder.
- Makes puppeteer browser debugging possible from anywhere.
- Creates a secure tunnel to make the devtools frontend (incl. screencasting) accessible from the public internet
- Makes quick puppeteer debugging and exploration fun with an interactive REPL.
- Blocks resources (images, media, css, etc.) in puppeteer.
- Supports all resource types, blocking can be toggled dynamically.
- Allows flash content to run on all sites without user interaction.
- Anonymizes the user-agent on all pages.
- Supports dynamic replacing, so the browser version stays intact and recent.
Check out the packages folder for more plugins.
Contributing
PRs and new plugins are welcome! :tada: The plugin API for puppeteer-extra
is clean and fun to use. Have a look the PuppeteerExtraPlugin base class documentation to get going and check out the existing plugins (minimal example is the anonymize-ua plugin) for reference.
We use a monorepo powered by Lerna (and yarn workspaces), ava for testing, the standard style for linting and JSDoc heavily to auto-generate markdown documentation based on code. :-)
Kudos
Compatibility
puppeteer-extra
and all plugins are tested continously against all relevant NodeJS (v8-v13) and puppeteer versions.
We never broke compatibility and still support puppeteer down to version 1.6.2 (Released Aug 1, 2018).
A few plugins won't work in headless mode (it's noted if that's the case) due to Chrome limitations (e.g. the user-preferences
plugin), look into xvfb-run
if you still require a headless experience in these circumstances.
API
Table of Contents
Modular plugin framework to teach puppeteer
new tricks.
This module acts a drop-in replacement for puppeteer
.
Allows PuppeteerExtraPlugin's to register themselves and
to extend puppeteer with additional functionality.
Type: function ()
Example:
const puppeteer = require('puppeteer-extra')
puppeteer.use(require('puppeteer-extra-plugin-anonymize-ua')())
puppeteer.use(
require('puppeteer-extra-plugin-font-size')({ defaultFontSize: 18 })
)
;(async () => {
const browser = await puppeteer.launch({ headless: false })
const page = await browser.newPage()
await page.goto('http://example.com', { waitUntil: 'domcontentloaded' })
await browser.close()
})()
Outside interface to register plugins.
Type: function (plugin): this
plugin
PuppeteerExtraPlugin
Example:
const puppeteer = require('puppeteer-extra')
puppeteer.use(require('puppeteer-extra-plugin-anonymize-ua')())
puppeteer.use(require('puppeteer-extra-plugin-user-preferences')())
const browser = await puppeteer.launch(...)
Launch a new browser instance with given arguments.
Augments the original puppeteer.launch
method with plugin lifecycle methods.
All registered plugins that have a beforeLaunch
method will be called
in sequence to potentially update the options
Object before launching the browser.
Type: function (options): Puppeteer.Browser
Attach Puppeteer to an existing Chromium instance.
Augments the original puppeteer.connect
method with plugin lifecycle methods.
All registered plugins that have a beforeConnect
method will be called
in sequence to potentially update the options
Object before launching the browser.
Type: function (options)
options
{browserWSEndpoint: string, ignoreHTTPSErrors: boolean} (optional, default {}
)
Get all registered plugins.
Type: Array<PuppeteerExtraPlugin>
- See: puppeteer-extra-plugin/data
Collects the exposed data
property of all registered plugins.
Will be reduced/flattened to a single array.
Can be accessed by plugins that listed the dataFromPlugins
requirement.
Implemented mainly for plugins that need data from other plugins (e.g. user-preferences
).
Type: function (name)
name
string? Filter data by name property (optional, default null
)
Regular Puppeteer method that is being passed through.
Type: function (): string
Regular Puppeteer method that is being passed through.
Type: function ()
Regular Puppeteer method that is being passed through.
Type: function (options): PuppeteerBrowserFetcher