# undetected-playwright
## Usage
1. **Download PyPi package**
```bash
pip install -U undetected-playwright
```
2. **Donload dependencies**
```bash
playwright install --with-deps
```
3. **Quick started**
```python
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
```python
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
```python
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
- [berstend/puppeteer-extra](https://github.com/berstend/puppeteer-extra)
- [AtuboDad/playwright_stealth: playwright stealth (github.com)](https://github.com/AtuboDad/playwright_stealth)
- [Granitosaurus/playwright-stealth (github.com)](https://github.com/Granitosaurus/playwright-stealth)
- [diprajpatra/selenium-stealth: Trying to make python selenium more stealthy. (github.com)](https://github.com/diprajpatra/selenium-stealth)
Raw data
{
"_id": null,
"home_page": "https://github.com/QIN2DIM/undetected-playwright",
"name": "undetected-playwright",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.8",
"maintainer_email": null,
"keywords": "undetected, playwright, steath",
"author": "QIN2DIM",
"author_email": "yaoqinse@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/52/6a/867b2fb3386e82f902e1d3da0be52266f854209f9f6a4b08b89b9d5d6f3f/undetected_playwright-0.3.0.tar.gz",
"platform": null,
"description": "# undetected-playwright\n\n## Usage\n\n1. **Download PyPi package**\n\n ```bash\n pip install -U undetected-playwright\n ```\n\n2. **Donload dependencies**\n\n ```bash\n playwright install --with-deps\n ```\n\n3. **Quick started**\n\n ```python\n import webbrowser\n from datetime import datetime\n from pathlib import Path\n \n from playwright.sync_api import sync_playwright, Page\n \n from undetected_playwright import Tarnished\n \n \n def cache_screenshot(page: Page):\n _now = datetime.now().strftime(\"%Y-%m-%d\")\n _suffix = f\"-view-new-{datetime.now().strftime('%H%M%S')}\"\n path = f\"result/{_now}/sannysoft{_suffix}.png\"\n page.screenshot(path=path, full_page=True)\n \n webbrowser.open(f\"file://{Path(path).resolve()}\")\n \n \n def main():\n # Chrome 112+\n args = [\"--headless=new\", \"--dump-dom\"]\n \n with sync_playwright() as p:\n browser = p.chromium.launch(args=args)\n context = browser.new_context(locale=\"en-US\")\n \n # Injecting Context\n Tarnished.apply_stealth(context)\n page = context.new_page()\n \n page.goto(\"https://bot.sannysoft.com/\", wait_until=\"networkidle\")\n cache_screenshot(page)\n \n browser.close()\n \n \n if __name__ == \"__main__\":\n main()\n \n ```\n\n## Demo: SyncPlaywright Sannysoft\n\n```python\nimport logging\nimport sys\nfrom datetime import datetime\nfrom enum import Enum\n\nfrom playwright.sync_api import sync_playwright, Page, Route\n\nfrom undetected_playwright import Tarnished\n\nlogging.basicConfig(\n level=logging.DEBUG, stream=sys.stdout, format=\"%(asctime)s - %(levelname)s - %(message)s\"\n)\n\n\nclass ViewMode(str, Enum):\n new = \"new\"\n headless = \"headless\"\n headful = \"headful\"\n\n\ndef _hijacker(route: Route):\n logging.debug(f\"{route.request.method} {route.request.url}\")\n route.continue_()\n\n\ndef worker(page: Page, view_mode: ViewMode | None = None):\n logging.info(f\"Worker started - {view_mode=}\")\n\n page.route(\"**/*\", _hijacker)\n page.goto(\"https://bot.sannysoft.com/\", wait_until=\"networkidle\")\n\n # Save screenshot\n _now = datetime.now().strftime(\"%Y-%m-%d\")\n if view_mode:\n _suffix = f\"-view-{view_mode}\"\n else:\n _suffix = f\"-view-{datetime.now().strftime('%H%M%S')}\"\n page.screenshot(path=f\"result/{_now}/sannysoft{_suffix}.png\", full_page=True)\n\n logging.info(f\"Worker finished - {view_mode=}\")\n\n\ndef bytedance(view_mode: ViewMode):\n with sync_playwright() as p:\n match view_mode:\n case \"new\":\n args = [\"--headless=new\", \"--dump-dom\"]\n browser = p.chromium.launch(args=args)\n case \"headless\":\n browser = p.chromium.launch(headless=True)\n case _:\n browser = p.chromium.launch(headless=False)\n\n context = browser.new_context(locale=\"en-US\")\n Tarnished.apply_stealth(context)\n\n page = context.new_page()\n worker(page, view_mode)\n\n browser.close()\n\n\ndef main():\n bytedance(ViewMode.new)\n bytedance(ViewMode.headful)\n bytedance(ViewMode.headless)\n\n\nif __name__ == \"__main__\":\n main()\n\n```\n\n\n\n## Demo: AsyncPlaywright CloudFlare\n\n```python\nimport asyncio\nimport logging\nimport sys\nfrom datetime import datetime\nfrom enum import Enum\n\nfrom playwright.async_api import async_playwright, Page, Route\n\nfrom undetected_playwright import Malenia\n\nlogging.basicConfig(\n level=logging.DEBUG, stream=sys.stdout, format=\"%(asctime)s - %(levelname)s - %(message)s\"\n)\n\n\nclass ViewMode(str, Enum):\n new = \"new\"\n headless = \"headless\"\n headful = \"headful\"\n\n\nasync def _hijacker(route: Route):\n logging.debug(f\"{route.request.method} {route.request.url}\")\n await route.continue_()\n\n\nasync def worker(page: Page, view_mode: ViewMode | None = None):\n logging.info(f\"Worker started - {view_mode=}\")\n\n await page.route(\"**/*\", _hijacker)\n await page.goto(\"https://www.nowsecure.nl\", wait_until=\"networkidle\")\n\n # Just for demo\n await page.wait_for_timeout(8000)\n\n # Save screenshot\n _now = datetime.now().strftime(\"%Y-%m-%d\")\n if view_mode:\n _suffix = f\"-view-{view_mode}\"\n else:\n _suffix = f\"-view-{datetime.now().strftime('%H%M%S')}\"\n await page.screenshot(path=f\"result/{_now}/cloudflare{_suffix}.png\", full_page=True)\n\n logging.info(f\"Worker finished - {view_mode=}\")\n\n\nasync def bytedance(view_mode: ViewMode):\n async with async_playwright() as p:\n match view_mode:\n case \"new\":\n args = [\"--headless=new\", \"--dump-dom\"]\n browser = await p.chromium.launch(args=args)\n case \"headless\":\n browser = await p.chromium.launch(headless=True)\n case _:\n browser = await p.chromium.launch(headless=False)\n\n context = await browser.new_context(locale=\"en-US\")\n await Malenia.apply_stealth(context)\n\n page = await context.new_page()\n await worker(page, view_mode)\n\n await browser.close()\n\n\nasync def main():\n await bytedance(ViewMode.new)\n await bytedance(ViewMode.headful)\n await bytedance(ViewMode.headless)\n\n\nif __name__ == \"__main__\":\n asyncio.run(main())\n\n```\n\n\n\n\n\n## Reference\n\n- [berstend/puppeteer-extra](https://github.com/berstend/puppeteer-extra)\n- [AtuboDad/playwright_stealth: playwright stealth (github.com)](https://github.com/AtuboDad/playwright_stealth)\n- [Granitosaurus/playwright-stealth (github.com)](https://github.com/Granitosaurus/playwright-stealth)\n- [diprajpatra/selenium-stealth: Trying to make python selenium more stealthy. (github.com)](https://github.com/diprajpatra/selenium-stealth)\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "You know who I am",
"version": "0.3.0",
"project_urls": {
"Documentation": "https://github.com/QIN2DIM/undetected-playwright",
"Homepage": "https://github.com/QIN2DIM/undetected-playwright",
"Repository": "https://github.com/QIN2DIM/undetected-playwright"
},
"split_keywords": [
"undetected",
" playwright",
" steath"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "622687c3790c875d3331972ab0b809d4da0900793c26a700f007fed45d2ecf90",
"md5": "e57073c88ee4ed72b63fe014e33b3b78",
"sha256": "dbcc76a6bfdd4ebc849a26c8f084355295ec415af316b1e4fd0a2a011397df92"
},
"downloads": -1,
"filename": "undetected_playwright-0.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "e57073c88ee4ed72b63fe014e33b3b78",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.8",
"size": 55567,
"upload_time": "2024-05-19T02:12:45",
"upload_time_iso_8601": "2024-05-19T02:12:45.341177Z",
"url": "https://files.pythonhosted.org/packages/62/26/87c3790c875d3331972ab0b809d4da0900793c26a700f007fed45d2ecf90/undetected_playwright-0.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "526a867b2fb3386e82f902e1d3da0be52266f854209f9f6a4b08b89b9d5d6f3f",
"md5": "d0f0f1e14e12508fac7542c80c99f43a",
"sha256": "c476baf095eaea6ee320dd8739e83811da6006227fa9b2492a4e3a8c0cb2b315"
},
"downloads": -1,
"filename": "undetected_playwright-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "d0f0f1e14e12508fac7542c80c99f43a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.8",
"size": 35105,
"upload_time": "2024-05-19T02:12:47",
"upload_time_iso_8601": "2024-05-19T02:12:47.723460Z",
"url": "https://files.pythonhosted.org/packages/52/6a/867b2fb3386e82f902e1d3da0be52266f854209f9f6a4b08b89b9d5d6f3f/undetected_playwright-0.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-19 02:12:47",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "QIN2DIM",
"github_project": "undetected-playwright",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "playwright",
"specs": []
}
],
"lcname": "undetected-playwright"
}