Playwright Stealth
Playwright Stealth is a Python package designed to make Playwright browser automation sessions less detectable by anti-bot systems. It achieves this by patching various browser fingerprints and automation-specific properties. Actively maintained, it currently stands at version 2.0.3 and utilizes a modern context-manager API for integration with Playwright.
Warnings
- breaking The API for `playwright-stealth` underwent a breaking change from v1.x to v2.x. Older patterns like `stealth_async(page)` or `stealth_sync(page)` are no longer supported. The current recommended approach uses a `Stealth().use_async(async_playwright())` context manager or `stealth.apply_stealth_async(context)` method for explicit control.
- gotcha While `playwright-stealth` helps bypass many common bot detection methods by patching browser fingerprints (e.g., `navigator.webdriver`, User-Agent), it does not provide complete immunity against advanced anti-bot systems. These systems might analyze IP reputation, TLS fingerprints, behavioral patterns, and other infrastructure-level signals, which `playwright-stealth` does not address.
- gotcha The `playwright` library (on which `playwright-stealth` depends) no longer automatically downloads browser binaries (Chromium, Firefox, WebKit) when installed via `pip` since version 1.38+. If you forget to install the browsers, `playwright-stealth` will fail to launch a browser.
- gotcha Stealth techniques that work for small-scale testing often fail when scaled up. Consistent browser fingerprints, repeated access patterns from the same IP, and rapid requests can lead to detection and blocking by anti-bot services, even with stealth plugins.
Install
-
pip install playwright-stealth -
playwright install chromium
Imports
- Stealth
from playwright_stealth import Stealth
- stealth_async / stealth_sync
Quickstart
import asyncio
import os
from playwright.async_api import async_playwright
from playwright_stealth import Stealth
async def main():
async with Stealth().use_async(async_playwright()) as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
# Example: Go to a test page and check navigator.webdriver property
# An actual stealth check would involve visiting sannysoft.com or similar
await page.goto("https://www.google.com")
is_webdriver = await page.evaluate("navigator.webdriver")
print(f"Is navigator.webdriver set? {is_webdriver}")
# Navigate to another page
await page.goto("https://web-scraping.dev/products")
title = await page.title()
print(f"Page title: {title}")
await browser.close()
if __name__ == "__main__":
asyncio.run(main())