-
Download PyPi package
pip install -U undetected-playwright
-
Donload dependencies
playwright install --with-deps
-
Quick started
import webbrowser from datetime import datetime from pathlib import Path from playwright.sync_api import sync_playwright, Page from undetected_playwright import Tarnished def cache_screenshot(page: Page): _now = datetime.now().strftime("%Y-%m-%d") _suffix = f"-view-new-{datetime.now().strftime('%H%M%S')}" path = f"result/{_now}/sannysoft{_suffix}.png" page.screenshot(path=path, full_page=True) webbrowser.open(f"file://{Path(path).resolve()}") def main(): # Chrome 112+ args = ["--headless=new", "--dump-dom"] with sync_playwright() as p: browser = p.chromium.launch(args=args) context = browser.new_context(locale="en-US") # Injecting Context Tarnished.apply_stealth(context) page = context.new_page() page.goto("https://bot.sannysoft.com/", wait_until="networkidle") cache_screenshot(page) browser.close() if __name__ == "__main__": main()
from playwright.sync_api import sync_playwright, Page
+ from undetected_playwright import Tarnished
with sync_playwright() as p:
browser = p.chromium.launch()
context = browser.new_context()
+ Tarnished.apply_stealth(context)
page = context.new_page()
from playwright.sync_api import sync_playwright, Page
+ from undetected_playwright import Malenia
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
context = await browser.new_context()
+ await Malenia.apply_stealth(context)
page = await context.new_page()
import logging
import sys
from datetime import datetime
from enum import Enum
from playwright.sync_api import sync_playwright, Page, Route
from undetected_playwright import Tarnished
logging.basicConfig(
level=logging.DEBUG, stream=sys.stdout, format="%(asctime)s - %(levelname)s - %(message)s"
)
class ViewMode(str, Enum):
new = "new"
headless = "headless"
headful = "headful"
def _hijacker(route: Route):
logging.debug(f"{route.request.method} {route.request.url}")
route.continue_()
def worker(page: Page, view_mode: ViewMode | None = None):
logging.info(f"Worker started - {view_mode=}")
page.route("**/*", _hijacker)
page.goto("https://bot.sannysoft.com/", wait_until="networkidle")
# Save screenshot
_now = datetime.now().strftime("%Y-%m-%d")
if view_mode:
_suffix = f"-view-{view_mode}"
else:
_suffix = f"-view-{datetime.now().strftime('%H%M%S')}"
page.screenshot(path=f"result/{_now}/sannysoft{_suffix}.png", full_page=True)
logging.info(f"Worker finished - {view_mode=}")
def bytedance(view_mode: ViewMode):
with sync_playwright() as p:
match view_mode:
case "new":
args = ["--headless=new", "--dump-dom"]
browser = p.chromium.launch(args=args)
case "headless":
browser = p.chromium.launch(headless=True)
case _:
browser = p.chromium.launch(headless=False)
context = browser.new_context(locale="en-US")
Tarnished.apply_stealth(context)
page = context.new_page()
worker(page, view_mode)
browser.close()
def main():
bytedance(ViewMode.new)
bytedance(ViewMode.headful)
bytedance(ViewMode.headless)
if __name__ == "__main__":
main()
import asyncio
import logging
import sys
from datetime import datetime
from enum import Enum
from playwright.async_api import async_playwright, Page, Route
from undetected_playwright import Malenia
logging.basicConfig(
level=logging.DEBUG, stream=sys.stdout, format="%(asctime)s - %(levelname)s - %(message)s"
)
class ViewMode(str, Enum):
new = "new"
headless = "headless"
headful = "headful"
async def _hijacker(route: Route):
logging.debug(f"{route.request.method} {route.request.url}")
await route.continue_()
async def worker(page: Page, view_mode: ViewMode | None = None):
logging.info(f"Worker started - {view_mode=}")
await page.route("**/*", _hijacker)
await page.goto("https://www.nowsecure.nl", wait_until="networkidle")
# Just for demo
await page.wait_for_timeout(8000)
# Save screenshot
_now = datetime.now().strftime("%Y-%m-%d")
if view_mode:
_suffix = f"-view-{view_mode}"
else:
_suffix = f"-view-{datetime.now().strftime('%H%M%S')}"
await page.screenshot(path=f"result/{_now}/cloudflare{_suffix}.png", full_page=True)
logging.info(f"Worker finished - {view_mode=}")
async def bytedance(view_mode: ViewMode):
async with async_playwright() as p:
match view_mode:
case "new":
args = ["--headless=new", "--dump-dom"]
browser = await p.chromium.launch(args=args)
case "headless":
browser = await p.chromium.launch(headless=True)
case _:
browser = await p.chromium.launch(headless=False)
context = await browser.new_context(locale="en-US")
await Malenia.apply_stealth(context)
page = await context.new_page()
await worker(page, view_mode)
await browser.close()
async def main():
await bytedance(ViewMode.new)
await bytedance(ViewMode.headful)
await bytedance(ViewMode.headless)
if __name__ == "__main__":
asyncio.run(main())