Skip to content

Engineering

What Patchright hides and what it can’t: detecting automated browsers without punishing people

We read Patchright’s public source, ran it and four other automation tools against our Verify challenge, and kept only the checks that never flagged a person. What it hides, what still shows, and what still passes.

By the OpenWAF security team

9 min read

Share

In short. Patchright, a patched build of Playwright, hides most of what our Verify challenge used to tell a scripted Chromium from a person. We read its public source, ran it and four other automation tools in a lab, and added browser checks to Verify’s risk scoring. Here is what we learned, described as categories rather than as individual checks.

  • Patchright closes the classic leaks: the DevTools runtime and console domains, scripts in the page’s own JavaScript world, and the launch flags that announce automation.
  • What stays visible: how input is produced, environments that don’t add up, a network handshake that doesn’t match the claimed browser, and behaviour across many requests.
  • The default use of Playwright, Patchright, a stealth plugin and zendriver was flagged. Carefully humanised Patchright, Camoufox and operating-system input still passed.
  • We dropped every check that flagged real people. The new checks run in log mode, and on their own they can ask for a click, never block.

Why we looked

OpenWAF Verify is the challenge our edge shows instead of a CAPTCHA: a proof of work the browser solves in the background and, when the risk is higher, a one-click «Verify you are human» step. It can’t prove that someone is human; nothing on the web can. Its job is to make automation slower and more expensive than browsing.

On 28 October we pointed Patchright at the managed Verify widget on our own demo page. In the three modes we tried, it got through without being asked to click. Plain Playwright did not: Chromium in automation mode reports itself through the standard navigator.webdriver flag, and the widget escalated it to the click. Closing that gap is what Patchright is for, so we went to see exactly what it changes.

We analysed public source code only: the Patchright driver and its Python and Node packages as published on GitHub, next to Playwright 1.62.0. Every lab run was against a local copy of our own challenge; no third-party site or service was involved.

What Patchright changes

Patchright is an open-source project that applies around thirty source patches to Playwright’s Chromium driver and ships the result as a drop-in replacement. The changes that matter here:

  • The DevTools runtime. Playwright, like most tools built on the Chrome DevTools Protocol, enables the protocol’s Runtime domain, which has side effects a page can observe. Patchright never enables it, nor the Console domain.
  • Isolated worlds. Scripts the automation runs go to a separate JavaScript world by default, so they leave nothing in the page.
  • Launch flags. It drops the switches that put Chromium in automation mode, so navigator.webdriver is false and the «controlled by automated test software» bar is gone, along with other flags typical of test runs.

Patchright doesn’t fake JavaScript APIs: no invented navigator properties, plugins or screen sizes. That is a sound choice. In our lab, every tool that patched JavaScript to look like a normal browser ended up contradicting itself somewhere.

The lab

A local page reproduced Verify’s interactive step. Five tools ran against it on macOS with Google Chrome 156: Playwright; Patchright; Puppeteer with the puppeteer-extra stealth plugin; zendriver, which drives a real Chrome over the DevTools Protocol without WebDriver; and Camoufox, a Firefox build modified in C++. Each ran headless and in a window, in several configurations, and pressed the box three ways: its default click, the keyboard, and a scripted «human» path. That made 110 automated runs. For the human side, a person on the same Mac pressed the box 31 times in Brave and Safari, with a trackpad and a mouse. Raw observations stayed on that machine.

WhoFlaggedNotes
Playwright12 of 12Visible to the edge and in the page.
Patchright: headless, bundled Chromium, emulated viewport, init scripts or an overridden User-Agent47 of 47An environment that doesn’t add up, the default input, or both.
Patchright, recommended setup, default click or keyboard6 of 6Input only.
Patchright, recommended setup, humanised input0 of 3Passed.
Puppeteer with the stealth plugin12 of 12Its JavaScript patches contradict the rest of the browser.
zendriver18 of 18Input only. Our humanised script for it was simpler than for the others.
Camoufox1 of 12Engine-level changes; most of what we look for is specific to Chromium automation.
Chrome with operating-system input0 of 2Passed.
People (Brave and Safari, trackpad and mouse)0 of 31No false positives.

The recommended setup is the one Patchright’s maintainers suggest: the installed Chrome, a real window, a persistent profile and no emulated viewport. Three runs per configuration show which families the checks see, not detection rates, and a determined operator will tune further than we did.

What still gives automation away

  • How input is synthesised. Input sent through the DevTools Protocol is trusted by the browser (isTrusted is true), so a page can’t just ask whether a click was real. But default input methods are written for reliable tests, and their movement, placement and timing are measurably unlike a hand on a mouse, trackpad or keyboard. It is also the cheapest tell to remove.
  • Environments that don’t add up. Headless modes and emulated viewports describe a browser that doesn’t match a desktop browser in a real window. A User-Agent can be overridden; the rest of the browser keeps telling the truth.
  • Patches that contradict each other. A browser has more places than any stealth patch set covers, and faked values end up disagreeing with real ones.
  • The network against the claim. The edge compares the TLS handshake with the browser the request claims to be, before any JavaScript runs. That catches HTTP libraries dressed as browsers, not Patchright driving the installed Chrome, which uses Chrome’s own network stack.
  • Behaviour across many requests. One visit says little. Volume, failures, reuse and timing patterns across a network’s challenges say much more, whatever the browser.

The human baseline

Every check was run against people before it shipped. The baseline is small, but it killed several ideas that looked solid against the tools:

  • Short presses. Automation presses quickly, so a minimum press duration looked obvious. Then trackpad tap-to-click produced presses of a few milliseconds, as short as any script.
  • No movement before the click. Scripts often jump straight to the target. So do people: in 14 of the 31 presses the cursor was already resting where the box appeared.
  • Clicking too soon. A minimum time before the click flagged people whose cursor was already in place. We removed it.
  • Hardware, not people. One idea turned out to measure the visitor’s mouse and screen rather than the visitor.

What survived gave no false positives on those 31 presses: a small sample, from one operating system, with no keyboard baseline yet. Some people may still look unusual to a check: anyone with the developer tools open, or using voice control or switch access, whose input can look synthetic. That is why browser checks alone can at most ask for a click.

What still passes

  • Patchright in its recommended setup, with input its operator has bothered to humanise.
  • Camoufox, in most of our runs.
  • Any real browser whose input comes from the operating system rather than from the browser’s debugging protocol.
  • People paid to solve challenges.

Browser checks catch the defaults. Defaults matter, because most automation at scale runs on them, but a check that falls to a one-line change in a script is friction, not a barrier. We built them knowing that.

Why the server side and cost matter more

A browser can be made to look clean, so what holds up is what a script can’t change from inside the page:

  • Proof of work. It doesn’t stop one visitor, but it changes the price of a million.
  • An interactive step. It forces automation to produce real input and costs it time on every challenge.
  • Reputation and network. Threat feeds, the edge’s own record of an address, whether the network belongs to a hosting provider, and how its recent challenges went.
  • Coherence of the request. Headers, client hints and the TLS handshake against the browser the client says it is.

All of this feeds Verify’s risk scoring: a score per challenge that, in enforce mode, makes the proof of work harder, asks for a click or blocks. Browser checks are one input among many and only weigh enough to block when the server side agrees. For a site under sustained attack, under attack mode puts every visitor through the challenge and the click.

What we don’t collect

  • No canvas, WebGL, audio or font fingerprinting, no plugin lists and no high-entropy client hints.
  • Each check answers yes or no inside the page. Only those answers leave it, never the values behind them, and nothing in them identifies a visitor.
  • First party only: the challenge and its scripts are served by our edge from the protected site’s own domain, with no third-party scripts or calls.
  • Network counters live in each edge node’s memory for a few minutes, keyed by a hash of the network prefix. The analytics get levels, score ranges and which signals fired, per site and minute, with no IP addresses.

Log mode first

Risk scoring, browser checks included, ships in log mode, its default: each challenge is scored and counted, and nothing is applied. We are not enforcing on these signals yet.

The reason is the baseline: one operating system, two browsers, no keyboard users. Before any check weighs more or enforcement is switched on, we want to see how often each one fires on real traffic on Windows, Linux, Android and iOS, with mouse, touch and keyboard. Site owners get the same view: the Verify analytics show what each level would have done, so the move to enforce is made with their own numbers. Next on our side is a fuller TLS fingerprint at the edge, for clients whose handshake doesn’t match the browser version they claim.

Thanks to the Patchright and Playwright projects, whose code and documentation are public and clear. This is about what an edge can see, not a judgement on either. If you think we got something wrong, write to security@openwaf.dev.

Frequently asked questions

Can OpenWAF detect Patchright?

Its default use, yes, in our lab: headless runs, emulated viewports and its default click and keyboard input were all flagged. Patchright in its maintainers’ recommended setup with humanised input passed, and so does any browser driven by operating-system input. That is why Verify relies on server-side signals and on cost, not only on browser checks.

Does Verify fingerprint my visitors?

No. It doesn’t use canvas, WebGL, audio or font fingerprinting, plugin lists or high-entropy client hints. Each browser check answers yes or no inside the page, only those answers leave it, and everything is served first party from the protected site’s domain.

Will these checks block real people?

Not on their own. They run in log mode by default, where nothing is applied, and even in enforce mode browser checks alone can at most ask for a click. Every check we tried that flagged a person in our baseline was dropped, and the baseline still has to grow before anything is enforced.

Why publish this if attackers can read it?

We describe categories and outcomes, not the checks, their thresholds or how answers are encoded. The automation projects already document what they hide, and defenders and site owners deserve to know what a challenge can and can’t tell them.

How do I use it on my site?

Risk scoring is part of Verify and starts in log mode. Watch what each level would have done in the Verify analytics for a few days, then decide whether to switch to enforce. The developer docs cover the settings and the report.

Sources

Topics

  • Patchright
  • Playwright
  • browser automation
  • bot detection
  • headless Chrome
  • Camoufox
  • puppeteer-extra-plugin-stealth
  • Chrome DevTools Protocol
  • OpenWAF Verify
  • proof of work
  • privacy

Author

OpenWAF

Keep reading

View all

Bring your agency’s sites into early access.

OpenWAF is free while it is in early access. Create your account, add your clients’ domains and switch their nameservers or add a CNAME: the dashboard guides you through each step.