Skip to content

Playwright with plugins to be a ghost.

License

Notifications You must be signed in to change notification settings

regseb/playwright-ghost

Repository files navigation

Playwright-ghost

npm build coverage semver

Playwright-ghost is an overlay on Playwright, adding plugins to conceal the differences between a browser used by a human being and a headless browser controlled by a program.

The Playwright-ghost API is identical to that of Playwright, except for the addition of the plugins option to the BrowserType.launch([options]) and BrowserType.launchPersistentContext(userDataDir, [options]) methods.

The plugins property is an array containing the plugins to be added.

Disclaimer

This project is not officially commissioned or supported by Microsoft and Playwright.

Install

playwright-ghost doesn't provide playwright, so you need to add it to your dependencies.

npm install playwright playwright-ghost

playwright-ghost can also be used with patchright or rebrowser-playwright.

npm install patchright playwright-ghost
npm install rebrowser-playwright playwright-ghost

Use

Here's an example with the recommended plugins.

import { chromium } from "playwright-ghost";
// Or to use patchright or rebrowser-playwright:
// import { chromium } from "playwright-ghost/patchright";
// import { chromium } from "playwright-ghost/rebrowser";
import plugins from "playwright-ghost/plugins";

const browser = await chromium.launch({
  plugins: plugins.recommended(),
});
const context = await browser.newContext();
const page = await context.newPage();

await page.goto("https://example.com/");
const title = await page.locator("h1").textContent();
console.log(title);

await context.close();
await browser.close();

In this other example, three plugins are added:

  • polyfill.headless has no options;
  • polyfill.screen sets other values for screen size;
  • utils.adblocker uses default options.
import { chromium } from "playwright-ghost";
import plugins from "playwright-ghost/plugins";

const browser = await chromium.launch({
  plugins: [
    plugins.polyfill.headless(),
    plugins.polyfill.screen({ width: 2560, height: 1440 }),
    plugins.utils.adblocker(),
  ],
});
// ...

And for this example, the recommended plugins and the utils.locale plugin are added.

import { chromium } from "playwright-ghost";
import plugins from "playwright-ghost/plugins";

const browser = await chromium.launch({
  plugins: [...plugins.recommended(), plugins.utils.locale()],
});
// ...

Plugins

⭐️ is in recommended / ⚙️ has options

Polyfill

⭐️ ⚙️ Name Description
⭐️ polyfill.automation Disable --enable-automation in Chromium.
⭐️ polyfill.headless Correct many differences in JavaScript APIs between the headful and headless versions of Chromium.
⭐️ ⚙️ polyfill.screen Set a realistic value for screen size: 1920x1080.
⚙️ polyfill.userAgent Change the browser's user agent.
⭐️ ⚙️ polyfill.viewport Vary viewport size with random values between 1000x500 and 1800x800.
⭐️ polyfill.webdriver Set navigator.webdriver to false.
polyfill.webGL Modify WebGL parameter values.

Humanize

⭐️ ⚙️ Name Description
⭐️ ⚙️ humanize.click Add delay between mousedown and mouseup for clicks and double-clicks.
⭐️ ⚙️ humanize.cursor Move the cursor with human-like movements.
⭐️ ⚙️ humanize.dialog Close <dialog> within a humanly possible time (between 1 and 5 seconds).

Utils

⭐️ ⚙️ Name Description
️⚙️ utils.adblocker Add Ghostery adblocker.
️⚙️ utils.camoufox Replace Firefox by Camoufox.
⚙️ utils.fingerprint Change the browser fingerprint.
⚙️ utils.locale Use the locally installed browser.
⚙️ utils.weston Run browser in weston (a Wayland compositor).
⚙️ utils.xvfb Run browser in Xvfb (X Virtual Frame Buffer).

Debug

⭐️ ⚙️ Name Description
️⚙️ debug.console Display console messages and error from the browser in the program console.
debug.cursor Show cursor in page.
debug.sniffer Monitor all JavaScript properties used in a page.

Anti-bots

Pass

This 24 anti-bots don't detect Playwright-ghost: Anubis, Bing, bounty-nodejs, Brotector, BrowserScan, Chromedriver Detector, Detect CDP, detectIncognito, Deviceandbrowserinfo, Device Info Disable-devtool, Fingerprint, Fingerprint Pro Playground, Fingerprint-Scan, HeadlessDetectJS, infosimples, Chrome Headless Detection (Intoli), Check browser fingerprints (iphey), OverpoweredJS Fingerprinting Demo, Pixelscan, rebrowser-bot-detector, Antibot (Sannysoft), Simple Service Workers Fingerprinting Leaks Test and Cloudflare turnstile demo.

To find out which plugins are used, see the anti-bots integration tests.

Fail

This 2 anti-bots detect Playwright-ghost:

Contributions are welcome to fix these defects.

Customize

You can write your own plugins. A plugin is a function that returns an object containing the hooks. The keys of this object are made up of the class, method and hook type. For example:

  • "BrowserType.launch:before": modify the input arguments of the launch() method of the BrowserType class.
  • "BrowserContext.newPage:after": modify the return parameter of the newPage() method of the BrowserContext class.

The values of the object are functions applying the modifications.

  • For "before" types, the function receives an array containing the arguments of the hooked method. And it must return a new array containing the modified arguments.
  • For "after" types, the function receives the return value of the hooked method. And it must return the modified return value.
/// rickrollPlugin.js
export default function rickrollPlugin() {
  return {
    "BrowserType.launch:before": (args) => {
      return [
        {
          ...args[0],
          args: ["--disable-volume-adjust-sound"],
        },
      ];
    },

    "BrowserContext.newPage:after": (page) => {
      page.addInitScript(() => {
        // Execute script only in main frame.
        if (window !== top) {
          return;
        }
        addEventListener("load", () => {
          const iframe = document.createElement("iframe");
          iframe.src = "https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ";
          document.body.replaceChildren(iframe);
        });
      });
      return page;
    },
  };
}

To use your plugin, add it to the plugins option.

import { chromium } from "playwright-ghost";
import plugins from "playwright-ghost/plugins";
import rickrollPlugin from "./rickrollPlugin.js";

const browser = await chromium.launch({
  plugins: [...plugins.recommended(), rickrollPlugin()],
});
// ...

This plugin isn't perfect, so let's see how we can improve it (and also discover other features).

About

Playwright with plugins to be a ghost.

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Sponsor this project

Contributors 2

  •  
  •