Skip to main content

playwright_stealth

Fork of AtuboDad's port of puppeteer-extra-plugin-stealth, with some improvements. Don't expect this to bypass anything but the simplest of bot detection methods. Consider this a proof-of-concept starting point.

I've merged some of the outstanding PRs, added some features, and cleaned up the API surface. See the changelog. The latest major version includes breaking changes.

Install

Install from PyPi:

$ pip install playwright-stealth

Example Usage

Recommended Usage

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())

Specifying config options and applying evasions manually to an entire context

import asyncio
from playwright.async_api import async_playwright
from playwright_stealth import Stealth, ALL_EVASIONS_DISABLED_KWARGS


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()
        await stealth.apply_stealth_async(context)

        # Test stealth on multiple pages
        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}")

    # Example of selective evasion usage
    no_evasions = Stealth(**ALL_EVASIONS_DISABLED_KWARGS)
    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))


asyncio.run(advanced_example())

Todo

  • make this work with playwright.launch_persistent_context
    • the difficult because sometimes we sniff the UA if an override isn't provided, and this is difficult to do when launch_persistent_context is launched
  • sec-platform (we have navigator_platform)
  • docs

A set of Test results

playwright with stealth

playwright without stealth

playwright without stealth

playwright with stealth

Release files for playwright-stealth 2.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for playwright-stealth 2.0.3
File Size Uploaded
playwright_stealth-2.0.3.tar.gz 25.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for playwright-stealth 2.0.3
File Interpreter ABI Platform
playwright_stealth-2.0.3-py3-none-any.whl Python 3 none any Details

Total release size: 60.1 kB

Release files / playwright_stealth-2.0.3.tar.gz

Download URL playwright_stealth-2.0.3.tar.gz
Size 25.8 kB
Tags Source
SHA-256 checksum
How to use checksums
1d8e488fbdd8f190f1269ea8cf5d57d14df3a9f1af1001c41ee3588b2aac3133
BLAKE2b-256 checksum
How to use checksums
a4db6ade5d539c7d151b9defc78fafa8b65aa52352617d0e7699b47008bd801f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.3.1 CPython/3.11.13 Linux/6.19.8-arch1-1

Release files / playwright_stealth-2.0.3-py3-none-any.whl

Download URL playwright_stealth-2.0.3-py3-none-any.whl
Size 34.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1887ade423ab7ff8ae16d363a30a38de0b5817e1e4a29d47b74bf3a0e3dbfcb4
BLAKE2b-256 checksum
How to use checksums
b510607c409712c02a26c4cb794820514cb7fdaaeac15fb05bed917fb8a354b3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.3.1 CPython/3.11.13 Linux/6.19.8-arch1-1

Release history Release notifications | RSS feed

This release

2.0.3 This release

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page