npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

playwright-ghost

v0.16.0

Published

Playwright with plugins to be a ghost.

Readme

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

Humanize

Utils

Debug

Anti-bots

Pass

This 20 anti-bots don't detect Playwright-ghost: Anubis, Brotector, BrowserScan, Chromedriver Detector, Detect CDP, 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, 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 3 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).