undetected-playwright
Usage
-
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()
Demo: SyncPlaywright Sannysoft
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()
Demo: AsyncPlaywright CloudFlare
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())
Reference
Metadata
Release files for undetected-playwright 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| undetected_playwright-0.3.0.tar.gz | 35.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| undetected_playwright-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 90.7 kB
Release files / undetected_playwright-0.3.0.tar.gz
| Download URL | undetected_playwright-0.3.0.tar.gz |
|---|---|
| Size | 35.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c476baf095eaea6ee320dd8739e83811da6006227fa9b2492a4e3a8c0cb2b315
|
|
BLAKE2b-256 checksum How to use checksums |
526a867b2fb3386e82f902e1d3da0be52266f854209f9f6a4b08b89b9d5d6f3f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.2 CPython/3.10.11 Windows/10
|
Release files / undetected_playwright-0.3.0-py3-none-any.whl
| Download URL | undetected_playwright-0.3.0-py3-none-any.whl |
|---|---|
| Size | 55.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dbcc76a6bfdd4ebc849a26c8f084355295ec415af316b1e4fd0a2a011397df92
|
|
BLAKE2b-256 checksum How to use checksums |
622687c3790c875d3331972ab0b809d4da0900793c26a700f007fed45d2ecf90
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.8.2 CPython/3.10.11 Windows/10
|
Security for undetected-playwright 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.