How to use Patchright with a proxy
Proxy Compare read four browser signals under Playwright 1.60.0 and Patchright 1.62.1 on 27 Aug 2026, then re-read them under Patchright with channel=chrome, and recorded which ones changed. The channel setting moves more of them than the library swap does.
3 Sept 2026 · 4 min read
Point in time. The figures below were read on 27 Aug 2026 and are not updated after publication. For current numbers see the comparison table.

What is Patchright?
Patchright is a patched fork of Playwright. Same API, same commands, same code: you change the import line and nothing else.
What it patches is the set of traces Playwright leaves in the browser it drives.
Automation frameworks announce themselves in ways an ordinary page can read,
most famously navigator.webdriver, which Playwright sets to true and a real
browser leaves undefined. Sites that would rather not be scraped check for
exactly those properties, so a Playwright script can work for months and then
start collecting blocks without a line of it having changed.
People reach for Patchright when that happens. It is the smallest possible change to an existing Playwright codebase, which is most of its appeal: no new API to learn and no rewrite.
Installing it
pip install patchright
patchright install chromium
Then change one line:
# from playwright.sync_api import sync_playwright
from patchright.sync_api import sync_playwright
Everything else in your script stays as it is. That is the whole migration.
What it looks like running
Drop headless=True and you can watch it work:

Note which browser that is. macOS reports the window as belonging to Google Chrome for Testing, the Chromium build Playwright and Patchright download for
themselves. It is not the Chrome you have installed, and that distinction is
what the channel="chrome" argument below changes.
What it actually changes
"Stealth Playwright" is accurate and tells you nothing about which signals move, so we read four of them under both.
What changes, and what does not
| Signal | Playwright | Patchright, default | Patchright, channel="chrome" |
|---|---|---|---|
navigator.webdriver | true | false | false |
| user agent | HeadlessChrome | HeadlessChrome | HeadlessChrome |
window.chrome | undefined | undefined | object |
navigator.plugins.length | 0 | 0 | 5 |
Out of the box it fixes exactly one of these. navigator.webdriver is the
signal it exists to clear and it clears it. The other three are untouched, and
they are not obscure: a real desktop Chrome has a window.chrome object, reports
plugins, and does not put HeadlessChrome in its user agent.
That is not a criticism of what the project claims. It patches the automation layer, and the headless surface is a different problem. It is a criticism of every guide that stops at "use Patchright instead" and lets you assume the rest came with it.
The one line that closes two of them
from patchright.sync_api import sync_playwright
with sync_playwright() as pw:
browser = pw.chromium.launch(headless=True, channel="chrome")
page = browser.new_page()
page.goto("https://example.com")
channel="chrome" drives the Chrome you have installed rather than the Chromium
that ships with Playwright. window.chrome becomes an object and
navigator.plugins goes from 0 to 5, because those things are genuinely present
in a real Chrome build and genuinely absent from the bundled one.
It costs you a dependency on Chrome being installed and on its version, which is the trade the undetected-chromedriver version pin makes visible from the other direction.
The tell it does not fix
The user agent still says HeadlessChrome in both configurations. That is
the single cheapest check a page can run, and neither the patching nor the
channel switch touches it. If you want it gone you set it yourself:
context = browser.new_context(
user_agent=("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/151.0.0.0 Safari/537.36"),
)
Then make sure the rest of the fingerprint agrees with the story you just
told. A Macintosh user agent with a Win32 platform is a contradiction, and we
measured a tool shipping exactly that in
how to choose an anti-detect browser.
Overriding one field is how you create that problem rather than solve it.
Why those two signals are the ones that moved
window.chrome and navigator.plugins are not stealth features anybody added.
They are ordinary properties of a real Chrome install that the bundled Chromium
does not have, so switching channel does not spoof them, it simply stops removing
them. That is why the switch is durable in a way a patch is not: nothing has to
keep up with a detector.
navigator.plugins reporting 5 rather than 0 matters more than the number
suggests. An empty plugin list has been a headless marker for years and is
trivially read, and a browser reporting none while claiming to be a desktop Chrome
is making the same kind of contradiction as a mismatched platform.
Adding a proxy
Patchright takes the Playwright shape unchanged:
browser = pw.chromium.launch(
headless=True,
channel="chrome",
proxy={"server": "http://gate.example.com:7000",
"username": "user-session-abc123",
"password": "secret"},
)
Two provider-side things decide whether that works, and neither is Patchright's
doing. The session token is not in the same field at every provider, so a
string that belongs in the username and is pasted into the password produces a
407 with nothing naming the cause. And some providers do not take a username
and password at all, expecting your IP on an allowlist instead.
We record what each provider states about both on its provider page, with the date we read it, and say so where a provider states nothing. The format converter reshapes a credential into the separate fields this call wants.
Limitations
We did not run this against any anti-bot system and make no claim about what it evades. Four signals, two configurations, one machine, one day. The value is that you can re-read the same four in a minute and see whether the answer has changed, which on a project shipping this quickly it will.
Sources
- patchright PyPI, read 27 Aug 2026
patchright 1.62.1
Questions
What does Patchright actually change?
In our reading on 27 August 2026, one signal of the four we checked: navigator.webdriver went from true to false. The user agent still said HeadlessChrome, window.chrome was still undefined and navigator.plugins was still empty, which are three of the most-checked signals in the category.
Is Patchright better than Playwright for scraping?
It removes a tell Playwright leaves, so on that one signal yes. It is not a complete fingerprint and does not claim to be. Passing channel=chrome so it drives installed Chrome rather than bundled Chromium closed two more of the signals we checked.
Does Patchright hide headless mode?
Not by default. The user agent still contained the string HeadlessChrome in both configurations we tested, which is the single easiest thing for a page to check. Overriding the user agent is a separate step you have to take yourself.
