|
| 1 | +<!-- SeleniumBase Docs --> |
| 2 | + |
| 3 | +<h2><a href="https://github.com/seleniumbase/SeleniumBase/"><img src="https://seleniumbase.github.io/img/logo6.png" title="SeleniumBase" width="32"></a> Stealthy Playwright 🎭</h2> |
| 4 | + |
| 5 | +🎭 <b translate="no">Stealthy Playwright Mode</b> is a special mode of <b translate="no">SeleniumBase</b> that launches <a href="https://github.com/microsoft/playwright-python">Playwright</a> from <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md" translate="no">SeleniumBase CDP Mode</a> in order to grant <b translate="no">Playwright</b> new stealth features, such as the ability to click CAPTCHA checkboxes successfully. <b translate="no">Playwright</b> uses <code>connect_over_cdp()</code> to attach itself onto an existing <b translate="no">SeleniumBase</b> session via the <code>remote-debugging-port</code>. From here, APIs of both frameworks can be used, giving you a hybrid approach that delivers the best experience of both worlds. |
| 6 | + |
| 7 | +-------- |
| 8 | + |
| 9 | +### 🎭 Getting started with <b translate="no">Stealthy Playwright Mode</b>: |
| 10 | + |
| 11 | +If `playwright` isn't already installed, then install it first: |
| 12 | + |
| 13 | +```zsh |
| 14 | +pip install playwright |
| 15 | +``` |
| 16 | + |
| 17 | +Stealthy Playwright Mode comes in 3 formats: |
| 18 | +1. `sb_cdp` sync format |
| 19 | +2. `SB` nested sync format |
| 20 | +3. `cdp_driver` async format |
| 21 | + |
| 22 | + |
| 23 | +#### `sb_cdp` sync format (minimal boilerplate): |
| 24 | + |
| 25 | +```python |
| 26 | +from playwright.sync_api import sync_playwright |
| 27 | +from seleniumbase import sb_cdp |
| 28 | + |
| 29 | +sb = sb_cdp.Chrome() |
| 30 | +endpoint_url = sb.get_endpoint_url() |
| 31 | + |
| 32 | +with sync_playwright() as p: |
| 33 | + browser = p.chromium.connect_over_cdp(endpoint_url) |
| 34 | + context = browser.contexts[0] |
| 35 | + page = context.pages[0] |
| 36 | + page.goto("https://example.com") |
| 37 | +``` |
| 38 | + |
| 39 | +#### `SB` nested sync format (minimal boilerplate): |
| 40 | + |
| 41 | +```python |
| 42 | +from playwright.sync_api import sync_playwright |
| 43 | +from seleniumbase import SB |
| 44 | + |
| 45 | +with SB(uc=True) as sb: |
| 46 | + sb.activate_cdp_mode() |
| 47 | + endpoint_url = sb.cdp.get_endpoint_url() |
| 48 | + |
| 49 | + with sync_playwright() as p: |
| 50 | + browser = p.chromium.connect_over_cdp(endpoint_url) |
| 51 | + context = browser.contexts[0] |
| 52 | + page = context.pages[0] |
| 53 | + page.goto("https://example.com") |
| 54 | +``` |
| 55 | + |
| 56 | +#### `cdp_driver` async format (minimal boilerplate): |
| 57 | + |
| 58 | +```python |
| 59 | +import asyncio |
| 60 | +from seleniumbase import cdp_driver |
| 61 | +from playwright.async_api import async_playwright |
| 62 | + |
| 63 | +async def main(): |
| 64 | + driver = await cdp_driver.start_async() |
| 65 | + endpoint_url = driver.get_endpoint_url() |
| 66 | + |
| 67 | + async with async_playwright() as p: |
| 68 | + browser = await p.chromium.connect_over_cdp(endpoint_url) |
| 69 | + context = browser.contexts[0] |
| 70 | + page = context.pages[0] |
| 71 | + await page.goto("https://example.com") |
| 72 | + |
| 73 | +if __name__ == "__main__": |
| 74 | + loop = asyncio.new_event_loop() |
| 75 | + loop.run_until_complete(main()) |
| 76 | +``` |
| 77 | + |
| 78 | +### 🎭 <b translate="no">Stealthy Playwright Mode</b> details: |
| 79 | + |
| 80 | +The `sb_cdp` and `cdp_driver` formats don't use WebDriver at all, meaning that `chromedriver` isn't needed. From these two formats, Stealthy Playwright Mode can call [CDP Mode methods](https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/cdp_mode_methods.md) and Playwright methods. |
| 81 | + |
| 82 | +The `SB()` format requires WebDriver, therefore `chromedriver` will be downloaded (as `uc_driver`) if the driver isn't already present on the local machine. The `SB()` format has access to Selenium WebDriver methods via [the SeleniumBase API](https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/method_summary.md). Using Stealthy Playwright Mode from `SB()` grants access to all the APIs: Selenium, SeleniumBase, [UC Mode](https://github.com/seleniumbase/SeleniumBase/blob/master/help_docs/uc_mode.md), [CDP Mode](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md), and Playwright. |
| 83 | + |
| 84 | +In the sync formats, `get_endpoint_url()` also applies `nest-asyncio` so that nested event loops are allowed. (Python doesn't allow nested event loops by default). Without this, you'd get the error: `"Cannot run the event loop while another loop is running"` when calling CDP Mode methods (such as `solve_captcha()`) from within the Playwright context manager. This `nest-asyncio` call is done behind-the-scenes so that users don't need to handle this on their own. |
| 85 | + |
| 86 | +### 🎭 <b translate="no">Stealthy Playwright Mode</b> examples: |
| 87 | + |
| 88 | +Here's an example that queries Microsoft Copilot: |
| 89 | + |
| 90 | +```python |
| 91 | +from playwright.sync_api import sync_playwright |
| 92 | +from seleniumbase import sb_cdp |
| 93 | + |
| 94 | +sb = sb_cdp.Chrome() |
| 95 | +endpoint_url = sb.get_endpoint_url() |
| 96 | + |
| 97 | +with sync_playwright() as p: |
| 98 | + browser = p.chromium.connect_over_cdp(endpoint_url) |
| 99 | + context = browser.contexts[0] |
| 100 | + page = context.pages[0] |
| 101 | + page.goto("https://copilot.microsoft.com") |
| 102 | + page.wait_for_selector("textarea#userInput") |
| 103 | + sb.sleep(1) |
| 104 | + query = "Playwright Python connect_over_cdp() sync example" |
| 105 | + page.fill("textarea#userInput", query) |
| 106 | + page.click('button[data-testid="submit-button"]') |
| 107 | + sb.sleep(3) |
| 108 | + sb.solve_captcha() |
| 109 | + page.wait_for_selector('button[data-testid*="-thumbs-up"]') |
| 110 | + sb.sleep(4) |
| 111 | + page.click('button[data-testid*="scroll-to-bottom"]') |
| 112 | + sb.sleep(3) |
| 113 | + chat_results = '[data-testid="highlighted-chats"]' |
| 114 | + result = page.locator(chat_results).inner_text() |
| 115 | + print(result.replace("\n\n", " \n")) |
| 116 | +``` |
| 117 | + |
| 118 | +Here's an example that solves the Bing CAPTCHA: |
| 119 | + |
| 120 | +```python |
| 121 | +from playwright.sync_api import sync_playwright |
| 122 | +from seleniumbase import sb_cdp |
| 123 | + |
| 124 | +sb = sb_cdp.Chrome(locale="en") |
| 125 | +endpoint_url = sb.get_endpoint_url() |
| 126 | + |
| 127 | +with sync_playwright() as p: |
| 128 | + browser = p.chromium.connect_over_cdp(endpoint_url) |
| 129 | + context = browser.contexts[0] |
| 130 | + page = context.pages[0] |
| 131 | + page.goto("https://www.bing.com/turing/captcha/challenge") |
| 132 | + sb.sleep(3) |
| 133 | + sb.solve_captcha() |
| 134 | + sb.sleep(3) |
| 135 | +``` |
| 136 | + |
| 137 | +For more examples, see [examples/cdp_mode/playwright](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode/playwright). |
| 138 | + |
| 139 | +-------- |
| 140 | + |
| 141 | +<a href="https://github.com/seleniumbase/SeleniumBase"><img src="https://seleniumbase.github.io/img/logo6.png" alt="SeleniumBase" title="SeleniumBase" width="100" /></a><img src="https://seleniumbase.github.io/other/playwright_logo.png" alt="Playwright" title="SeleniumBase" height="100"> |
0 commit comments