playwright-ghost
v0.17.0
Published
Playwright with plugins to be a ghost.
Maintainers
Readme
Playwright-ghost
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-ghostplaywright-ghost can also be used with
patchright or
rebrowser-playwright.
npm install patchright playwright-ghost
npm install rebrowser-playwright playwright-ghostUse
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.headlesshas no options;polyfill.screensets other values for screen size;utils.adblockeruses 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
Humanize
Utils
Debug
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:
- CreepJS: 44% like headless
- Score detector (reCAPTCHA v3): 0.3
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 thelaunch()method of theBrowserTypeclass."BrowserContext.newPage:after": modify the return parameter of thenewPage()method of theBrowserContextclass.
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).
