patchright-cli 0.3.0__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,9 @@ on:
8
8
  permissions:
9
9
  contents: write
10
10
 
11
+ env:
12
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
13
+
11
14
  jobs:
12
15
  build:
13
16
  runs-on: ubuntu-latest
@@ -15,7 +18,7 @@ jobs:
15
18
  - uses: actions/checkout@v4
16
19
 
17
20
  - name: Install uv
18
- uses: astral-sh/setup-uv@v4
21
+ uses: astral-sh/setup-uv@v5
19
22
 
20
23
  - name: Set up Python
21
24
  run: uv python install 3.12
@@ -43,7 +46,7 @@ jobs:
43
46
  path: dist/
44
47
 
45
48
  - name: Install uv
46
- uses: astral-sh/setup-uv@v4
49
+ uses: astral-sh/setup-uv@v5
47
50
 
48
51
  - name: Publish to PyPI
49
52
  run: uv publish
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patchright-cli
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Anti-detect browser automation CLI using Patchright (undetected Playwright fork)
5
5
  Project-URL: Homepage, https://github.com/AhaiMk01/patchright-cli
6
6
  Project-URL: Repository, https://github.com/AhaiMk01/patchright-cli
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "patchright-cli"
3
- version = "0.3.0"
3
+ version = "0.3.1"
4
4
  description = "Anti-detect browser automation CLI using Patchright (undetected Playwright fork)"
5
5
  license = "Apache-2.0"
6
6
  requires-python = ">=3.10"
@@ -0,0 +1,453 @@
1
+ ---
2
+ name: patchright-cli
3
+ description: Anti-detect browser automation using Patchright (undetected Playwright fork). Use when you need to interact with websites that block regular Playwright/Chrome DevTools, such as Akamai/Cloudflare-protected sites. Provides the same command interface as playwright-cli but bypasses bot detection. Use this skill whenever the user asks to automate a browser, scrape a website, fill forms, log into sites, take screenshots, or do anything involving Chrome automation — especially if the target site has bot protection like Cloudflare or Akamai.
4
+ ---
5
+
6
+ # Anti-Detect Browser Automation with patchright-cli
7
+
8
+ patchright-cli drives a real Chrome browser that passes bot detection (Cloudflare, Akamai, etc.). It works as a CLI: you issue commands, get back page state. This is the tool to reach for whenever regular Playwright or Chrome DevTools gets blocked.
9
+
10
+ ## How it works: the snapshot-driven loop
11
+
12
+ Every interaction follows the same cycle:
13
+
14
+ ```
15
+ open browser → snapshot → read refs → interact → snapshot again → repeat
16
+ ```
17
+
18
+ 1. **Open** a browser session — this launches a real Chrome window
19
+ 2. **Snapshot** the page — this scans the DOM and assigns refs (`e1`, `e2`, ...) to interactive elements
20
+ 3. **Read the snapshot** — it's a YAML file showing the element tree with refs
21
+ 4. **Interact** using refs — `click e5`, `fill e3 "hello"`, etc.
22
+ 5. **Check the result** — most commands auto-snapshot, so you get updated refs
23
+
24
+ Refs are ephemeral. They change every time the page updates. If a command fails with "Could not locate element for ref", the page has changed — just run `snapshot` to get fresh refs.
25
+
26
+ ## Quick start
27
+
28
+ ```bash
29
+ patchright-cli open https://example.com # launch browser + navigate
30
+ patchright-cli snapshot # get element refs
31
+ # read the snapshot YAML to find the right ref, then:
32
+ patchright-cli click e5 # interact by ref
33
+ patchright-cli fill e3 "search query" # type into an input
34
+ patchright-cli press Enter # press a key
35
+ patchright-cli screenshot # capture the page
36
+ patchright-cli close # done
37
+ ```
38
+
39
+ ## Installation
40
+
41
+ ### CLI tool
42
+
43
+ ```bash
44
+ # Recommended — always runs latest version
45
+ uvx patchright-cli <command>
46
+
47
+ # Or install globally
48
+ pip install patchright-cli
49
+ ```
50
+
51
+ ### Skill (for AI coding agents)
52
+
53
+ Install the skill so your agent knows how to use patchright-cli. The same command also works to update to the latest version.
54
+
55
+ **macOS / Linux (bash/zsh):**
56
+
57
+ | Agent | Install / update command |
58
+ |-------|--------------------------|
59
+ | **Claude Code** | `mkdir -p ~/.claude/skills/patchright-cli && curl -sL https://raw.githubusercontent.com/AhaiMk01/patchright-cli/main/skills/patchright-cli/SKILL.md -o ~/.claude/skills/patchright-cli/SKILL.md` |
60
+ | **Gemini CLI** | `mkdir -p ~/.gemini/skills/patchright-cli && curl -sL https://raw.githubusercontent.com/AhaiMk01/patchright-cli/main/skills/patchright-cli/SKILL.md -o ~/.gemini/skills/patchright-cli/SKILL.md` |
61
+ | **Codex CLI** | `mkdir -p ~/.codex/skills/patchright-cli && curl -sL https://raw.githubusercontent.com/AhaiMk01/patchright-cli/main/skills/patchright-cli/SKILL.md -o ~/.codex/skills/patchright-cli/SKILL.md` |
62
+ | **OpenCode** | `mkdir -p ~/.opencode/skills/patchright-cli && curl -sL https://raw.githubusercontent.com/AhaiMk01/patchright-cli/main/skills/patchright-cli/SKILL.md -o ~/.opencode/skills/patchright-cli/SKILL.md` |
63
+
64
+ **Windows (PowerShell):**
65
+
66
+ | Agent | Install / update command |
67
+ |-------|--------------------------|
68
+ | **Claude Code** | `New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude\skills\patchright-cli" | Out-Null; Invoke-WebRequest -Uri "https://raw.githubusercontent.com/AhaiMk01/patchright-cli/main/skills/patchright-cli/SKILL.md" -OutFile "$env:USERPROFILE\.claude\skills\patchright-cli\SKILL.md"` |
69
+ | **Gemini CLI** | `New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.gemini\skills\patchright-cli" | Out-Null; Invoke-WebRequest -Uri "https://raw.githubusercontent.com/AhaiMk01/patchright-cli/main/skills/patchright-cli/SKILL.md" -OutFile "$env:USERPROFILE\.gemini\skills\patchright-cli\SKILL.md"` |
70
+ | **Codex CLI** | `New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.codex\skills\patchright-cli" | Out-Null; Invoke-WebRequest -Uri "https://raw.githubusercontent.com/AhaiMk01/patchright-cli/main/skills/patchright-cli/SKILL.md" -OutFile "$env:USERPROFILE\.codex\skills\patchright-cli\SKILL.md"` |
71
+ | **OpenCode** | `New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.opencode\skills\patchright-cli" | Out-Null; Invoke-WebRequest -Uri "https://raw.githubusercontent.com/AhaiMk01/patchright-cli/main/skills/patchright-cli/SKILL.md" -OutFile "$env:USERPROFILE\.opencode\skills\patchright-cli\SKILL.md"` |
72
+
73
+ **IDE-based agents (Cursor / Windsurf / Aider):** Copy `SKILL.md` to `.<tool>/skills/patchright-cli/` in your project.
74
+
75
+ **Or just tell your agent:**
76
+ > Install patchright-cli skill from https://raw.githubusercontent.com/AhaiMk01/patchright-cli/main/skills/patchright-cli/SKILL.md
77
+
78
+ ## Global options
79
+
80
+ These go before the command:
81
+
82
+ ```bash
83
+ --headless # Run headless (default: headed — headed is less detectable)
84
+ --persistent # Use persistent profile (keeps cookies/storage across sessions)
85
+ --profile=/path # Custom profile directory
86
+ --proxy=<url> # Proxy server (http, https, socks5)
87
+ -s=mysession # Named session (default: "default")
88
+ --port=9322 # Custom daemon port (default: 9321)
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Core commands
94
+
95
+ ### Browser lifecycle
96
+
97
+ ```bash
98
+ patchright-cli open # Launch browser
99
+ patchright-cli open https://example.com # Launch and navigate
100
+ patchright-cli open --persistent # Keep cookies/storage between runs
101
+ patchright-cli open --headless # Headless mode
102
+ patchright-cli open --profile=/path/to/dir # Custom profile directory
103
+ patchright-cli --proxy=http://host:port open # Route traffic through HTTP proxy
104
+ patchright-cli --proxy=socks5://host:port open # SOCKS5 proxy
105
+ patchright-cli close # Close session
106
+ ```
107
+
108
+ ### Navigation
109
+
110
+ ```bash
111
+ patchright-cli goto https://example.com
112
+ patchright-cli go-back
113
+ patchright-cli go-forward
114
+ patchright-cli reload
115
+ ```
116
+
117
+ ### Snapshots
118
+
119
+ Snapshots are how you discover what's on the page. They produce a YAML tree of interactive elements, each tagged with a ref like `e1`, `e5`, `e12`.
120
+
121
+ ```bash
122
+ patchright-cli snapshot # Full page snapshot
123
+ patchright-cli snapshot e3 # Subtree of a specific element
124
+ patchright-cli snapshot --filename=snap.yml # Save to custom path
125
+ ```
126
+
127
+ After each state-changing command (click, fill, goto, etc.), a snapshot is automatically taken and returned. You don't need to manually snapshot after every action.
128
+
129
+ ### Clicking and interacting
130
+
131
+ ```bash
132
+ patchright-cli click e3 # Left-click
133
+ patchright-cli click e3 right # Right-click
134
+ patchright-cli click e3 --modifiers=Alt,Shift # Click with modifier keys
135
+ patchright-cli dblclick e7 # Double-click
136
+ patchright-cli dblclick e7 --modifiers=Shift
137
+ patchright-cli hover e4
138
+ patchright-cli drag e2 e8 # Drag element to target
139
+ ```
140
+
141
+ ### Form input
142
+
143
+ ```bash
144
+ patchright-cli fill e5 "user@example.com" # Clear field and type value
145
+ patchright-cli fill e5 "query" --submit # Fill and press Enter
146
+ patchright-cli type "search query" # Type via keyboard (no target element)
147
+ patchright-cli type "query" --submit # Type and press Enter
148
+ patchright-cli select e9 "option-value" # Select dropdown option
149
+ patchright-cli check e12 # Check checkbox/radio
150
+ patchright-cli uncheck e12
151
+ ```
152
+
153
+ `fill` targets a specific input by ref and replaces its contents. `type` types via the keyboard into whatever is focused.
154
+
155
+ ### Screenshots
156
+
157
+ ```bash
158
+ patchright-cli screenshot # Page screenshot
159
+ patchright-cli screenshot e3 # Element screenshot
160
+ patchright-cli screenshot --filename=page.png # Custom filename
161
+ patchright-cli screenshot --full-page # Full scrollable page
162
+ ```
163
+
164
+ Screenshots save to `.patchright-cli/` in the current directory.
165
+
166
+ ### Keyboard and mouse
167
+
168
+ ```bash
169
+ # Keyboard
170
+ patchright-cli press Enter # Single keypress
171
+ patchright-cli press ArrowDown
172
+ patchright-cli keydown Shift # Hold key down
173
+ patchright-cli keyup Shift # Release key
174
+
175
+ # Mouse
176
+ patchright-cli mousemove 150 300 # Move to coordinates
177
+ patchright-cli mousedown # Left button down
178
+ patchright-cli mousedown right # Right button down
179
+ patchright-cli mouseup
180
+ patchright-cli mousewheel 0 100 # Scroll (dx, dy)
181
+ ```
182
+
183
+ ### Tabs
184
+
185
+ ```bash
186
+ patchright-cli tab-list # List open tabs
187
+ patchright-cli tab-new https://example.com # Open new tab
188
+ patchright-cli tab-select 0 # Switch to tab by index
189
+ patchright-cli tab-close # Close current tab
190
+ patchright-cli tab-close 2 # Close tab by index
191
+ ```
192
+
193
+ ---
194
+
195
+ ## JavaScript execution
196
+
197
+ **Always use `--file` or stdin for `eval` and `run-code`.** Inline JS breaks because quotes get mangled through shell layers (bash -> uvx -> python).
198
+
199
+ ```bash
200
+ # WRONG — nested quotes break
201
+ patchright-cli eval "document.querySelector('a').href"
202
+
203
+ # RIGHT — write to a temp file
204
+ cat > /tmp/check.js << 'JSEOF'
205
+ JSON.stringify({title: document.title, links: document.querySelectorAll('a').length})
206
+ JSEOF
207
+ patchright-cli eval --file=/tmp/check.js
208
+
209
+ # RIGHT — pipe via stdin (simple expressions)
210
+ echo 'document.title' | patchright-cli eval
211
+ ```
212
+
213
+ `eval` returns the expression result. `run-code` wraps your code in `async () => { ... }` so you can use `return` and `await`.
214
+
215
+ ```bash
216
+ # run-code example
217
+ cat > /tmp/scroll.js << 'JSEOF'
218
+ window.scrollTo(0, document.body.scrollHeight);
219
+ return document.body.scrollHeight;
220
+ JSEOF
221
+ patchright-cli run-code --file=/tmp/scroll.js
222
+ ```
223
+
224
+ ---
225
+
226
+ ## Common patterns
227
+
228
+ ### Using a proxy
229
+
230
+ ```bash
231
+ # HTTP proxy
232
+ patchright-cli --proxy=http://host:port open https://example.com
233
+
234
+ # SOCKS5 proxy
235
+ patchright-cli --proxy=socks5://host:port open https://example.com
236
+
237
+ # Authenticated proxy
238
+ patchright-cli --proxy=http://user:pass@host:port open https://example.com
239
+
240
+ # Combine with persistent profile and named session
241
+ patchright-cli --proxy=http://host:port -s=proxied open https://example.com --persistent
242
+ ```
243
+
244
+ The proxy is set at browser launch and applies to all traffic in that session. Note: `--proxy` is a global option and must come before the command.
245
+
246
+ ### Login flow
247
+
248
+ ```bash
249
+ patchright-cli open https://example.com/login --persistent
250
+ patchright-cli snapshot
251
+ # Find the username/password fields and login button in the snapshot
252
+ patchright-cli fill e3 "user@example.com"
253
+ patchright-cli fill e5 "password123"
254
+ patchright-cli click e8 # Click login button
255
+ # Wait a moment for redirect, then snapshot to verify
256
+ patchright-cli snapshot
257
+ # With --persistent, cookies survive across sessions
258
+ ```
259
+
260
+ ### Extracting data from a page
261
+
262
+ ```bash
263
+ patchright-cli open https://example.com/data
264
+ patchright-cli snapshot # Get the page structure
265
+ # Use eval to extract structured data
266
+ cat > /tmp/extract.js << 'JSEOF'
267
+ JSON.stringify(
268
+ [...document.querySelectorAll('table tr')].map(row =>
269
+ [...row.cells].map(cell => cell.textContent.trim())
270
+ )
271
+ )
272
+ JSEOF
273
+ patchright-cli eval --file=/tmp/extract.js
274
+ ```
275
+
276
+ ### Waiting for dynamic content
277
+
278
+ The page may not be fully loaded when you snapshot. If elements are missing, try:
279
+
280
+ ```bash
281
+ # Option 1: Just snapshot again after a short pause
282
+ # (most commands auto-wait for navigation to settle)
283
+ patchright-cli snapshot
284
+
285
+ # Option 2: Use run-code to wait for a specific condition
286
+ cat > /tmp/wait.js << 'JSEOF'
287
+ for (let i = 0; i < 30; i++) {
288
+ if (document.querySelector('.results-loaded')) return true;
289
+ await new Promise(r => setTimeout(r, 500));
290
+ }
291
+ return false;
292
+ JSEOF
293
+ patchright-cli run-code --file=/tmp/wait.js
294
+ patchright-cli snapshot
295
+ ```
296
+
297
+ ### Multi-page workflow with persistent session
298
+
299
+ ```bash
300
+ # Use a named persistent session to maintain state
301
+ patchright-cli -s=myproject open https://app.example.com --persistent
302
+ patchright-cli -s=myproject snapshot
303
+ patchright-cli -s=myproject click e5
304
+ # ... do work ...
305
+ patchright-cli -s=myproject close
306
+ # Later, reopen — cookies and localStorage are preserved
307
+ patchright-cli -s=myproject open https://app.example.com --persistent
308
+ ```
309
+
310
+ ### Handling dialogs (alert/confirm/prompt)
311
+
312
+ Dialogs must be pre-armed *before* the action that triggers them:
313
+
314
+ ```bash
315
+ patchright-cli dialog-accept # Accept next dialog
316
+ patchright-cli click e5 # This click triggers the dialog
317
+ # Or:
318
+ patchright-cli dialog-accept "OK" # Accept with text input
319
+ patchright-cli dialog-dismiss # Dismiss instead
320
+ ```
321
+
322
+ ---
323
+
324
+ ## Storage and state
325
+
326
+ ### Cookies
327
+
328
+ ```bash
329
+ patchright-cli cookie-list # All cookies
330
+ patchright-cli cookie-list --domain=example.com # Filter by domain
331
+ patchright-cli cookie-list --path=/api # Filter by path
332
+ patchright-cli cookie-get session_id # Get specific cookie
333
+ patchright-cli cookie-set session_id abc123 # Set cookie (current page URL)
334
+ patchright-cli cookie-set token xyz --domain=example.com --path=/ --httpOnly --secure --sameSite=Lax --expires=1735689600
335
+ patchright-cli cookie-delete session_id
336
+ patchright-cli cookie-clear # Clear all
337
+ ```
338
+
339
+ ### localStorage / sessionStorage
340
+
341
+ ```bash
342
+ # localStorage
343
+ patchright-cli localstorage-list
344
+ patchright-cli localstorage-get theme
345
+ patchright-cli localstorage-set theme dark
346
+ patchright-cli localstorage-delete theme
347
+ patchright-cli localstorage-clear
348
+
349
+ # sessionStorage (same pattern)
350
+ patchright-cli sessionstorage-list
351
+ patchright-cli sessionstorage-get step
352
+ patchright-cli sessionstorage-set step 3
353
+ patchright-cli sessionstorage-delete step
354
+ patchright-cli sessionstorage-clear
355
+ ```
356
+
357
+ ### Save/load full state (cookies + storage)
358
+
359
+ ```bash
360
+ patchright-cli state-save auth.json # Save cookies + localStorage
361
+ patchright-cli state-load auth.json # Restore (navigate to matching origin first for localStorage)
362
+ ```
363
+
364
+ ---
365
+
366
+ ## Network tools
367
+
368
+ ### Request mocking
369
+
370
+ ```bash
371
+ patchright-cli route "**/*.jpg" --status=404 # Block images
372
+ patchright-cli route "https://api.example.com/**" --body='{"mock": true}' # Mock API
373
+ patchright-cli route "**/*" --content-type=application/json --body='{"ok":true}'
374
+ patchright-cli route "**/*" --header=X-Custom:value
375
+ patchright-cli route "**/*" --remove-header=Content-Type
376
+ patchright-cli route-list # List active routes
377
+ patchright-cli unroute "**/*.jpg" # Remove specific route
378
+ patchright-cli unroute # Remove all routes
379
+ ```
380
+
381
+ ### Network state
382
+
383
+ ```bash
384
+ patchright-cli network-state-set offline # Simulate offline
385
+ patchright-cli network-state-set online # Restore connectivity
386
+ ```
387
+
388
+ ### DevTools inspection
389
+
390
+ ```bash
391
+ patchright-cli console # Show console messages (last 50)
392
+ patchright-cli console warning # Filter by level
393
+ patchright-cli console --clear # Clear buffer after printing
394
+
395
+ patchright-cli network # Show requests (excludes static assets)
396
+ patchright-cli network --static # Include images, fonts, scripts, etc.
397
+ patchright-cli network --clear # Clear log after printing
398
+ ```
399
+
400
+ ---
401
+
402
+ ## Recording and capture
403
+
404
+ ```bash
405
+ # Tracing (Playwright trace format)
406
+ patchright-cli tracing-start
407
+ patchright-cli tracing-stop # Saves .zip to .patchright-cli/
408
+
409
+ # Video (CDP screencast, requires ffmpeg for .webm output)
410
+ patchright-cli video-start
411
+ patchright-cli video-stop # Save as .webm (or frames if no ffmpeg)
412
+ patchright-cli video-stop --filename=rec.webm
413
+
414
+ # PDF
415
+ patchright-cli pdf # Save page as PDF
416
+ patchright-cli pdf --filename=page.pdf
417
+
418
+ # File upload
419
+ patchright-cli upload ./document.pdf # Upload to first file input
420
+ patchright-cli upload ./photo.jpg e5 # Upload to specific input
421
+
422
+ # Viewport resize
423
+ patchright-cli resize 1920 1080
424
+ ```
425
+
426
+ ---
427
+
428
+ ## Session management
429
+
430
+ ```bash
431
+ # Named sessions allow multiple independent browsers
432
+ patchright-cli -s=session1 open https://site-a.com --persistent
433
+ patchright-cli -s=session2 open https://site-b.com --persistent
434
+
435
+ patchright-cli list # List all active sessions
436
+ patchright-cli close-all # Gracefully close all
437
+ patchright-cli kill-all # Force-kill all + stop daemon
438
+
439
+ # Delete persistent profile data
440
+ patchright-cli delete-data # Delete default session's profile
441
+ patchright-cli -s=mysession delete-data # Delete named session's profile
442
+ ```
443
+
444
+ ---
445
+
446
+ ## Anti-detect notes
447
+
448
+ - Uses real Chrome (not Chromium) — this is what makes it undetectable
449
+ - Patchright patches `navigator.webdriver` and other detection vectors automatically
450
+ - Headed by default — headless mode is more detectable, use only when necessary
451
+ - No custom user-agent or headers — preserves Chrome's natural fingerprint
452
+ - Persistent profiles maintain realistic browser history and cookies
453
+ - The daemon architecture means Chrome stays running between commands, behaving like a real user's browser
@@ -1,3 +1,3 @@
1
1
  """patchright-cli — Undetected browser automation CLI using Patchright."""
2
2
 
3
- __version__ = "0.3.0"
3
+ __version__ = "0.3.1"
@@ -154,6 +154,7 @@ def _print_help():
154
154
  click.echo(" --headless Run headless (default: headed)")
155
155
  click.echo(" --persistent Use persistent profile")
156
156
  click.echo(" --profile=<path> Custom profile directory")
157
+ click.echo(" --proxy=<url> Proxy server (e.g. http://host:port, socks5://host:port)")
157
158
  click.echo(" -s=<name> Named session (default: 'default')")
158
159
  click.echo(" --port=<n> Daemon port (default: 9321)")
159
160
  click.echo(" --version Show version")
@@ -231,6 +232,7 @@ def main():
231
232
  headless = False
232
233
  persistent = False
233
234
  profile = None
235
+ proxy = None
234
236
  session_name = "default"
235
237
  port = DEFAULT_PORT
236
238
 
@@ -248,6 +250,11 @@ def main():
248
250
  elif arg == "--profile" and i + 1 < len(argv):
249
251
  i += 1
250
252
  profile = argv[i]
253
+ elif arg.startswith("--proxy="):
254
+ proxy = arg.split("=", 1)[1]
255
+ elif arg == "--proxy" and i + 1 < len(argv):
256
+ i += 1
257
+ proxy = argv[i]
251
258
  elif arg.startswith("-s="):
252
259
  session_name = arg.split("=", 1)[1]
253
260
  elif arg == "-s" and i + 1 < len(argv):
@@ -330,6 +337,8 @@ def main():
330
337
  options["persistent"] = True
331
338
  if profile:
332
339
  options["profile"] = profile
340
+ if proxy:
341
+ options["proxy"] = proxy
333
342
 
334
343
  # Ensure daemon is running (auto-start for 'open', require for others)
335
344
  try:
@@ -137,6 +137,7 @@ class DaemonState:
137
137
  headless: bool | None = None,
138
138
  persistent: bool = True,
139
139
  profile: str | None = None,
140
+ proxy: str | None = None,
140
141
  url: str | None = None,
141
142
  ) -> Session:
142
143
  if name in self.sessions:
@@ -151,14 +152,18 @@ class DaemonState:
151
152
  profile_dir = profile or str(Path.home() / ".patchright-cli" / "profiles" / name)
152
153
  Path(profile_dir).mkdir(parents=True, exist_ok=True)
153
154
 
155
+ launch_kwargs = {
156
+ "channel": "chrome",
157
+ "headless": use_headless,
158
+ "no_viewport": True,
159
+ "args": ["--disable-blink-features=AutomationControlled"],
160
+ }
161
+ if proxy:
162
+ launch_kwargs["proxy"] = {"server": proxy}
163
+
154
164
  context = await self.playwright.chromium.launch_persistent_context(
155
165
  profile_dir,
156
- channel="chrome",
157
- headless=use_headless,
158
- no_viewport=True,
159
- args=[
160
- "--disable-blink-features=AutomationControlled",
161
- ],
166
+ **launch_kwargs,
162
167
  )
163
168
 
164
169
  pages = context.pages or []
@@ -263,6 +268,7 @@ async def handle_command(state: DaemonState, msg: dict) -> dict:
263
268
  headless=headless,
264
269
  persistent=options.get("persistent", True),
265
270
  profile=options.get("profile"),
271
+ proxy=options.get("proxy"),
266
272
  url=url,
267
273
  )
268
274
  return await _page_info(session, cwd)