Skip to content

Commit 682ed2b

Browse files
committed
Update the Stealthy Playwright Mode ReadMe
1 parent d6ebb52 commit 682ed2b

File tree

1 file changed

+70
-16
lines changed

1 file changed

+70
-16
lines changed

examples/cdp_mode/playwright/ReadMe.md

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@
1313

1414
### 🎭 Getting started with <b translate="no">Stealthy Playwright Mode</b>:
1515

16-
If `playwright` isn't already installed, then install it first:
16+
🎭 If `playwright` isn't already installed, then install it first:
1717

1818
```zsh
1919
pip install playwright
2020
```
2121

22-
Stealthy Playwright Mode comes in 3 formats:
22+
🎭 Stealthy Playwright Mode comes in 3 formats:
2323
1. `sb_cdp` sync format
24-
2. `SB` nested sync format
24+
2. `SB()` nested sync format
2525
3. `cdp_driver` async format
2626

2727

28-
#### `sb_cdp` sync format (minimal boilerplate):
28+
#### 🎭 `sb_cdp` sync format (minimal boilerplate):
2929

3030
```python
3131
from playwright.sync_api import sync_playwright
@@ -41,7 +41,7 @@ with sync_playwright() as p:
4141
page.goto("https://example.com")
4242
```
4343

44-
#### `SB` nested sync format (minimal boilerplate):
44+
#### 🎭 `SB()` nested sync format (minimal boilerplate):
4545

4646
```python
4747
from playwright.sync_api import sync_playwright
@@ -58,7 +58,7 @@ with SB(uc=True) as sb:
5858
page.goto("https://example.com")
5959
```
6060

61-
#### `cdp_driver` async format (minimal boilerplate):
61+
#### 🎭 `cdp_driver` async format (minimal boilerplate):
6262

6363
```python
6464
import asyncio
@@ -80,25 +80,25 @@ if __name__ == "__main__":
8080
loop.run_until_complete(main())
8181
```
8282

83+
--------
84+
8385
### 🎭 <b translate="no">Stealthy Playwright Mode</b> details:
8486

8587
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.
8688

87-
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.
88-
89-
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.
89+
The `SB()` format requires WebDriver, therefore `chromedriver` will be downloaded, modified for stealth, and renamed as `uc_driver` if not already present. 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). When using Stealthy Playwright Mode from the `SB()` format, all the APIs are accessible: 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.
9090

9191
Default timeout values are different between Playwright and SeleniumBase. For instance, a 30-second default timeout in a Playwright method might only be 10 seconds in the equivalent SeleniumBase method.
9292

93-
When specifying custom timeout values, Playwright uses milliseconds, whereas SeleniumBase uses seconds. Eg. `page.wait_for_timeout(2000)` is the equivalent of `sb.sleep(2)`. Although adding random sleeps to a script is generally discouraged, it helps the automation look more human-like for stealth, and it can prevent exceeding rate limits that trigger a block when automation performs actions too quickly.
93+
When specifying custom timeout values, Playwright uses milliseconds, whereas SeleniumBase uses seconds. Eg. `page.wait_for_timeout(2000)` in Playwright is the equivalent of `sb.sleep(2)` in SeleniumBase.
9494

95-
Playwright's `:has-text()` selector is the equivalent of SeleniumBase's `:contains()` selector, except for one small difference: `:has-text()` isn't case-sensitive, but `:contains()` is.
95+
Although hard sleeps are generally discouraged, they become a tactical tool in stealth mode because that extra waiting helps the automation look more human. Hard sleeps are used in multiple examples to prevent rate limits from being exceeded.
9696

97-
Unlike normal Playwright, you don't need to run `playwright install` before running Stealthy Playwright Mode scripts because the system Chrome will be used. There's also the option of setting `use_chromium=True` to use the unbranded Chromium browser instead, which still supports extensions.
97+
--------
9898

99-
### 🎭 <b translate="no">Stealthy Playwright Mode</b> examples:
99+
### 🎭 A few examples of <b translate="no">Stealthy Playwright Mode</b>:
100100

101-
Here's an example that queries Microsoft Copilot:
101+
🎭 Here's an example that queries Microsoft Copilot:
102102

103103
```python
104104
from playwright.sync_api import sync_playwright
@@ -128,7 +128,9 @@ with sync_playwright() as p:
128128
print(result.replace("\n\n", " \n"))
129129
```
130130

131-
Here's an example that solves the Bing CAPTCHA:
131+
(From [examples/cdp_mode/playwright/raw_copilot_sync.py](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/raw_copilot_sync.py))
132+
133+
🎭 Here's an example that solves the Bing CAPTCHA:
132134

133135
```python
134136
from playwright.sync_api import sync_playwright
@@ -147,6 +149,52 @@ with sync_playwright() as p:
147149
page.wait_for_timeout(2000)
148150
```
149151

152+
(From [examples/cdp_mode/playwright/raw_bing_cap_sync.py](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/playwright/raw_bing_cap_sync.py))
153+
154+
#### 🎭 For all included examples, see [examples/cdp_mode/playwright](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode/playwright).
155+
156+
--------
157+
158+
### 🎭 Converting regular <b translate="no">Playwright</b> scripts to <b translate="no">Stealthy Playwright Mode</b>:
159+
160+
If you have a regular Playwright script that looks like this:
161+
162+
```python
163+
from playwright.sync_api import sync_playwright
164+
165+
with sync_playwright() as p:
166+
browser = p.chromium.launch(channel="chrome", headless=False)
167+
context = browser.new_context()
168+
page = context.new_page()
169+
page.goto("https://example.com")
170+
```
171+
172+
Then the Stealthy Playwright Mode version of that would look like this:
173+
174+
```python
175+
from playwright.sync_api import sync_playwright
176+
from seleniumbase import sb_cdp
177+
178+
sb = sb_cdp.Chrome()
179+
endpoint_url = sb.get_endpoint_url()
180+
181+
with sync_playwright() as p:
182+
browser = p.chromium.connect_over_cdp(endpoint_url)
183+
context = browser.contexts[0]
184+
page = context.pages[0]
185+
page.goto("https://example.com")
186+
```
187+
188+
--------
189+
190+
### 🎭 More details about <b translate="no">Stealthy Playwright Mode</b>:
191+
192+
Stealthy Playwright Mode uses the system's Chrome browser by default. There's also the option of setting `use_chromium=True` to use the unbranded Chromium browser instead, which still supports extensions. (With regular Playwright, you would generally need to run `playwright install` to download a special version of Chrome before running Playwright scripts, unless you set `channel="chrome"` to use the system's Chrome browser instead.)
193+
194+
Playwright's `:has-text()` selector is the equivalent of SeleniumBase's `:contains()` selector, except for one small difference: `:has-text()` isn't case-sensitive, but `:contains()` is.
195+
196+
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.
197+
150198
--------
151199

152200
### 🎭 Proxy with auth in <b translate="no">Stealthy Playwright Mode</b>:
@@ -214,7 +262,13 @@ if __name__ == "__main__":
214262

215263
--------
216264

217-
For more examples, see [examples/cdp_mode/playwright](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode/playwright).
265+
#### 🎭 This flowchart shows how Stealthy Playwright Mode fits into CDP Mode:</h3>
266+
267+
<img src="https://seleniumbase.github.io/other/sb_stealth.png" width="596" alt="Stealthy architecture flowchart" />
268+
269+
(See the [**CDP Mode** ReadMe](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/cdp_mode/ReadMe.md) for more information about that.)
270+
271+
#### 🎭 See [examples/cdp_mode/playwright](https://github.com/seleniumbase/SeleniumBase/tree/master/examples/cdp_mode/playwright) for Stealthy Playwight Mode examples.
218272

219273
--------
220274

0 commit comments

Comments
 (0)