Install playwright-stealth via pip
mainInstall the package from PyPi using the following command:
$ pip install playwright-stealthrepository·main·Indexed 42 days ago
https://github.com/mattwmaster58/playwright_stealthA Python port of puppeteer-extra-plugin-stealth for Playwright version 2.0.3. It helps evade bot detection by applying browser fingerprinting evasions to Playwright instances, pages, or browser contexts. It provides the Stealth class for configuring overrides for User Agent, Platform, WebGL settings, and navigator properties, and supports both synchronous and asynchronous workflows via use_sync and use_async.
Install the package from PyPi using the following command:
$ pip install playwright-stealthThe recommended way to use playwright-stealth is to use the Stealth().use_async() context manager. This wraps the Playwright async_playwright instance, ensuring that all pages and contexts created within that session automatically have stealth evasions applied.
This approach is the most seamless as it handles the application of evasions to every new page and context created under the managed playwright instance.
import asyncio
from playwright.async_api import async_playwright
from playwright_stealth import Stealth
async def main():
# This is the recommended usage. All pages created will have stealth applied:
async with Stealth().use_async(async_playwright()) as p:
browser = await p.chromium.launch()
page = await browser.new_page()
webdriver_status = await page.evaluate("navigator.webdriver")
print("from new_page: ", webdriver_status)
different_context = await browser.new_context()
page_from_different_context = await different_context.new_page()
different_context_status = await page_from_different_context.evaluate("navigator.webdriver")
print("from new_context: ", different_context_status)
asyncio.run(main())You can create a Stealth instance with specific evasions disabled by using the ALL_EVASIONS_DISABLED_KWARGS dictionary. This is useful for debugging or when you only want to apply a subset of stealth features (e.g., only overriding navigator_webdriver).
To enable a specific evasion while keeping others disabled, you can unpack ALL_EVASIONS_DISABLED_KWARGS and then override the specific key you want to enable.
from playwright_stealth import Stealth, ALL_EVASIONS_DISABLED_KWARGS
# Instance with no evasions applied
no_evasions = Stealth(**ALL_EVASIONS_DISABLED_KWARGS)
# Instance with only 'navigator_webdriver' evasion enabled
single_evasion = Stealth(**{**ALL_EVASIONS_DISABLED_KWARGS, "navigator_webdriver": True})
print("Total evasions (none):", len(no_evasions.script_payload))
print("Total evasions (single):", len(single_evasion.script_payload))If you need more control or are working with an existing Playwright instance, you can instantiate a Stealth object and apply it to a specific BrowserContext using await stealth.apply_stealth_async(context).
This allows you to target specific contexts rather than the entire Playwright session. You can also configure the Stealth instance with custom options like navigator_languages_override or init_scripts_only.
import asyncio
from playwright.async_api import async_playwright
from playwright_stealth import Stealth
async def advanced_example():
# Custom configuration with specific languages
custom_languages = ("fr-FR", "fr")
stealth = Stealth(
navigator_languages_override=custom_languages,
init_scripts_only=True
)
async with async_playwright() as p:
browser = await p.chromium.launch()
context = await browser.new_context()
# Apply stealth to the specific context
await stealth.apply_stealth_async(context)
# Test stealth on multiple pages created from this context
page_1 = await context.new_page()
page_2 = await context.new_page()
# Verify language settings
for i, page in enumerate([page_1, page_2], 1):
is_mocked = await page.evaluate("navigator.languages") == custom_languages
print(f"Stealth applied to page {i}: {is_mocked}")
asyncio.run(advanced_example())The Stealth class is the main entry point for applying evasions to Playwright. You can configure which stealth strategies are enabled or disabled and provide overrides for specific browser properties like User Agent, Platform, or WebGL settings.
Key Configuration Options:
navigator_user_agent_override: Set a custom User Agent string.navigator_platform_override: Set a custom platform (e.g., 'Win32').navigator_languages_override: A tuple of (language, script) (e.g., ('en-US', 'en')).webgl_renderer_override: Override the WebGL renderer string.webgl_vendor_override: Override the WebGL vendor string.sec_ch_ua_override: Manually set the Sec-CH-UA header value.init_scripts_only: If True, only applies the init scripts without patching Playwright methods.from playwright_stealth import Stealth
stealth = Stealth(
navigator_user_agent_override="My Custom UA",
navigator_platform_override="Win32",
webgl_vendor_override="Intel Inc."
)Use use_sync to instrument a Playwright context manager for synchronous workflows. This ensures that any browser or page created within the block has stealth applied.
from playwright.sync_api import sync_playwright
from playwright_stealth import Stealth
stealth = Stealth()
with stealth.use_sync(sync_playwright()) as p:
browser = p.chromium.launch()
page = browser.new_page()
# Page already has stealth appliedfrom playwright.sync_api import sync_playwright
from playwright_stealth import Stealth
stealth = Stealth()
with stealth.use_sync(sync_playwright()) as p:
browser = p.chromium.launch()
page = browser.new_page()If you don't want to instrument the entire context, you can apply stealth manually to a specific Page or BrowserContext using apply_stealth_sync.
from playwright.sync_api import sync_playwright
from playwright_stealth import Stealth
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context()
page = context.new_page()
stealth = Stealth()
stealth.apply_stealth_sync(page)The playwright_stealth package provides the Stealth class, which is used to apply evasion techniques to Playwright browser contexts to avoid detection. You can import it directly from the package root.
from playwright_stealth import StealthIf you don't want to instrument the entire context, you can apply stealth manually to a specific Page or BrowserContext using apply_stealth_async.
from playwright.async_api import async_playwright
from playwright_stealth import Stealth
async def run():
async with async_playwright() as p:
browser = await p.chromium.launch()
context = await browser.new_context()
page = await context.new_page()
stealth = Stealth()
await stealth.apply_stealth_async(page)Use use_async to instrument a Playwright context manager. This ensures that any browser connected to or any page created via this context automatically has stealth evasions applied.
from playwright.async_api import async_playwright
from playwright_stealth import Stealth
async def run():
stealth = Stealth()
async with stealth.use_async(async_playwright()) as p:
browser = await p.chromium.launch()
page = await browser.new_page()
# Page already has stealth appliedfrom playwright.async_api import async_playwright
from playwright_stealth import Stealth
async def run():
stealth = Stealth()
async with stealth.use_async(async_playwright()) as p:
browser = await p.chromium.launch()
page = await browser.new_page()The following boolean flags control which JavaScript evasion scripts are injected into the page. Most are True by default.
| Option | Description |
|---|---|
chrome_app | Chrome App evasion |
chrome_csi | Chrome Client Hints evasion |
chrome_load_times | Chrome load times evasion |
chrome_runtime | Chrome runtime evasion |
hairline | Chrome hairline evasion |
iframe_content_window | Iframe contentWindow evasion |
media_codecs | Media codecs evasion |
navigator_hardware_concurrency | Hardware concurrency evasion |
navigator_languages | Navigator languages evasion |
navigator_permissions | Navigator permissions evasion |
navigator_platform | Navigator platform evasion |
navigator_plugins | Navigator plugins evasion |
navigator_user_agent | Navigator User Agent evasion |
navigator_user_agent_data | Navigator User Agent Data evasion |
navigator_vendor | Navigator vendor evasion |
navigator_webdriver | Navigator webdriver evasion |
error_prototype | Error prototype evasion |
sec_ch_ua | Sec-CH-UA header evasion |
webgl_vendor | WebGL vendor evasion |
The ALL_EVASIONS_DISABLED_KWARGS constant is exported from the package root. It can be used to identify or manage configuration settings when you want to disable all evasion techniques.
from playwright_stealth import ALL_EVASIONS_DISABLED_KWARGS