playwright-stealth

repository·main·Indexed 42 days ago

https://github.com/mattwmaster58/playwright_stealth

A 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.

Tokens
3K
Snippets
11
Records
12
Agent score
53%

What's inside playwright-stealth

  1. Use the recommended Stealth context manager

    main

    The 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())
  2. Configure selective evasion using ALL_EVASIONS_DISABLED_KWARGS

    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))
  3. Apply stealth manually to a Playwright context

    main

    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())
  4. Initialize the Stealth class

    main

    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."
    )
  5. Apply stealth to an entire Playwright context (Sync)

    main

    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 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()
  6. Apply stealth to a specific Page or BrowserContext (Sync)

    main

    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)
  7. Apply stealth to a specific Page or BrowserContext (Async)

    main

    If 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)
  8. Apply stealth to an entire Playwright context (Async)

    main

    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 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()
  9. Reference: Stealth configuration options

    main

    The following boolean flags control which JavaScript evasion scripts are injected into the page. Most are True by default.

    OptionDescription
    chrome_appChrome App evasion
    chrome_csiChrome Client Hints evasion
    chrome_load_timesChrome load times evasion
    chrome_runtimeChrome runtime evasion
    hairlineChrome hairline evasion
    iframe_content_windowIframe contentWindow evasion
    media_codecsMedia codecs evasion
    navigator_hardware_concurrencyHardware concurrency evasion
    navigator_languagesNavigator languages evasion
    navigator_permissionsNavigator permissions evasion
    navigator_platformNavigator platform evasion
    navigator_pluginsNavigator plugins evasion
    navigator_user_agentNavigator User Agent evasion
    navigator_user_agent_dataNavigator User Agent Data evasion
    navigator_vendorNavigator vendor evasion
    navigator_webdriverNavigator webdriver evasion
    error_prototypeError prototype evasion
    sec_ch_uaSec-CH-UA header evasion
    webgl_vendorWebGL vendor evasion