Reputation: 21011
I'm using Playwright with Chrome.
In other tools, one can easily change navigator.webdriver
like so:
Object.defineProperty(navigator, 'webdriver', { get: () => false });
In Playwright + Chrome (using .NET bindings, but same idea in Node / Python), I tried:
// attempt 1
await context.AddInitScriptAsync("""
Object.defineProperty(navigator, 'webdriver', { get: () => false });
""");
// attempt 2
await page.EvaluateAsync("""
Object.defineProperty(navigator, 'webdriver', { get: () => false });
""");
// attempt 3
await page.EvaluateAsync("""
delete Object.getPrototypeOf(navigator).webdriver;
Object.defineProperty(navigator, 'webdriver', { get: () => false });
""");
// attempt 4
await page.EvaluateAsync("""
const newProto = navigator.__proto__;
delete newProto.webdriver;
navigator.__proto__ = newProto;
""");
In all cases the browser still reports that it is using webdriver (e.g. here).
How do I do this with Playwright?
Upvotes: 1
Views: 4125
Reputation: 395
Updated version 2024:
await page.addInitScript("delete Object.getPrototypeOf(navigator).webdriver")
Upvotes: 1
Reputation: 11789
A radical but ultimate method is to hex-edit chrome
binary (in ~/.cache/ms-playwright/chromium-<whatever>
and replace the webdriver
string there with some other nine characters, i.e. aaaaaaaaa
.
Upvotes: 2
Reputation: 3797
For patching properties in playwright, consider using page.add_init_script
instead (or it's equivalent in other languages, this is for python). This is because the script you add through this method will automatically be called every time the page is navigated or whenever a child frame is attached, in their respective contexts. This will save you the hassle of doing it manually.
Example:
await page.add_init_script("delete Object.getPrototypeOf(navigator).webdriver")
The reason page.evaluate
seemingly does not work has to do with the fact that it is run after the page has navigated (calling the method before that does not make sense because the changes will be overwritten after navigation anyway). Since the webpage cannot react to changes you do after it has already completed its tests, it makes it seem that page.evaluate
is not working, which is not true.
Update:
Here's a more robust patch, courtesy of playwright-stealth
:
s = """
if (navigator.webdriver === false) {
// Post Chrome 89.0.4339.0 and already good
} else if (navigator.webdriver === undefined) {
// Pre Chrome 89.0.4339.0 and already good
} else {
// Pre Chrome 88.0.4291.0 and needs patching
delete Object.getPrototypeOf(navigator).webdriver
}
"""
await page.add_init_script(s)
Upvotes: 4