patchright-cli 0.3.1__tar.gz → 0.4.0__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.
Files changed (29) hide show
  1. patchright_cli-0.4.0/.claude-plugin/marketplace.json +21 -0
  2. patchright_cli-0.4.0/.claude-plugin/skills/browser-automation.json +5 -0
  3. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/PKG-INFO +1 -1
  4. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/pyproject.toml +13 -1
  5. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/skills/patchright-cli/SKILL.md +49 -10
  6. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/src/patchright_cli/__init__.py +1 -1
  7. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/src/patchright_cli/cli.py +17 -20
  8. patchright_cli-0.4.0/src/patchright_cli/daemon.py +1462 -0
  9. patchright_cli-0.4.0/src/patchright_cli/ref_registry.py +74 -0
  10. patchright_cli-0.4.0/src/patchright_cli/snapshot.py +46 -0
  11. patchright_cli-0.4.0/tests/__init__.py +0 -0
  12. patchright_cli-0.4.0/tests/fixture.html +30 -0
  13. patchright_cli-0.4.0/tests/test_daemon_handlers.py +124 -0
  14. patchright_cli-0.4.0/tests/test_e2e.py +144 -0
  15. patchright_cli-0.4.0/tests/test_ref_registry.py +75 -0
  16. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/uv.lock +156 -1
  17. patchright_cli-0.3.1/src/patchright_cli/daemon.py +0 -1094
  18. patchright_cli-0.3.1/src/patchright_cli/snapshot.py +0 -346
  19. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/.github/workflows/publish.yml +0 -0
  20. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/.gitignore +0 -0
  21. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/.pre-commit-config.yaml +0 -0
  22. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/CLAUDE.md +0 -0
  23. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/CONTRIBUTING.md +0 -0
  24. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/LICENSE +0 -0
  25. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/README.md +0 -0
  26. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/docs/installation.md +0 -0
  27. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/patchright-cli +0 -0
  28. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/patchright-cli.cmd +0 -0
  29. {patchright_cli-0.3.1 → patchright_cli-0.4.0}/src/patchright_cli/__main__.py +0 -0
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "patchright-cli",
3
+ "owner": {
4
+ "name": "zpahai"
5
+ },
6
+ "metadata": {
7
+ "description": "Anti-detect browser automation CLI using Patchright (undetected Playwright fork)",
8
+ "version": "0.4.0"
9
+ },
10
+ "plugins": [
11
+ {
12
+ "name": "patchright-cli",
13
+ "description": "Anti-detect browser automation CLI for AI agents",
14
+ "source": "./",
15
+ "skills": [
16
+ "./skills/patchright-cli",
17
+ "./.claude-plugin/skills/browser-automation"
18
+ ]
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "browser-automation",
3
+ "description": "Control a headful or headless Chrome browser via patchright-cli commands",
4
+ "documentation": "./skills/patchright-cli/SKILL.md"
5
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patchright-cli
3
- Version: 0.3.1
3
+ Version: 0.4.0
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.1"
3
+ version = "0.4.0"
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"
@@ -43,6 +43,18 @@ build-backend = "hatchling.build"
43
43
  [tool.hatch.build.targets.wheel]
44
44
  packages = ["src/patchright_cli"]
45
45
 
46
+ [tool.pytest.ini_options]
47
+ asyncio_mode = "auto"
48
+ markers = [
49
+ "e2e: marks tests that launch a real browser",
50
+ ]
51
+
52
+ [dependency-groups]
53
+ dev = [
54
+ "pytest>=8.0",
55
+ "pytest-asyncio>=0.23",
56
+ ]
57
+
46
58
  [tool.ruff]
47
59
  target-version = "py310"
48
60
  line-length = 120
@@ -7,6 +7,19 @@ description: Anti-detect browser automation using Patchright (undetected Playwri
7
7
 
8
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
9
 
10
+ ## What's new in v0.4.0
11
+
12
+ - **Native accessibility snapshots** — uses Playwright's built-in `aria_snapshot()` instead of custom DOM injection. More accurate and immune to page-script interference.
13
+ - **Smart link clicks** — `click` on a link now navigates directly via `goto`, avoiding sticky-header timeouts and `target="_blank"` silences.
14
+ - **Custom history stack** — `go-back` and `go-forward` now use an internal history tracker instead of the browser History API, so they work reliably on anti-detect sites that spoof history.
15
+ - **Scroll & wait commands** — `scroll`, `scroll-to`, `wait`, and `wait-for` are now available.
16
+ - **`text` command** — quickly grab text content of an element by ref or CSS selector.
17
+ - **Cookie bulk import/export** — `cookie-import` and `cookie-export` for transferring cookie jars via JSON.
18
+ - **Authenticated proxy support** — `--proxy=http://user:pass@host:port` is parsed automatically; credentials are injected via `Proxy-Authorization`.
19
+ - **Daemon auto-restart** — the daemon respawns automatically if it isn't running, even for commands other than `open`.
20
+ - **Idle timeout** — daemon shuts itself down after 5 minutes of inactivity to free resources.
21
+ - **Test suite** — unit + async handler + e2e tests are included in `tests/`.
22
+
10
23
  ## How it works: the snapshot-driven loop
11
24
 
12
25
  Every interaction follows the same cycle:
@@ -16,7 +29,7 @@ open browser → snapshot → read refs → interact → snapshot again → repe
16
29
  ```
17
30
 
18
31
  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
32
+ 2. **Snapshot** the page — this uses Playwright's accessibility tree and assigns refs (`e1`, `e2`, ...) to interactive elements
20
33
  3. **Read the snapshot** — it's a YAML file showing the element tree with refs
21
34
  4. **Interact** using refs — `click e5`, `fill e3 "hello"`, etc.
22
35
  5. **Check the result** — most commands auto-snapshot, so you get updated refs
@@ -83,7 +96,7 @@ These go before the command:
83
96
  --headless # Run headless (default: headed — headed is less detectable)
84
97
  --persistent # Use persistent profile (keeps cookies/storage across sessions)
85
98
  --profile=/path # Custom profile directory
86
- --proxy=<url> # Proxy server (http, https, socks5)
99
+ --proxy=<url> # Proxy server (http, https, socks5) — supports user:pass@host auth
87
100
  -s=mysession # Named session (default: "default")
88
101
  --port=9322 # Custom daemon port (default: 9321)
89
102
  ```
@@ -102,6 +115,7 @@ patchright-cli open --headless # Headless mode
102
115
  patchright-cli open --profile=/path/to/dir # Custom profile directory
103
116
  patchright-cli --proxy=http://host:port open # Route traffic through HTTP proxy
104
117
  patchright-cli --proxy=socks5://host:port open # SOCKS5 proxy
118
+ patchright-cli --proxy=http://user:pass@host:port open # Authenticated proxy
105
119
  patchright-cli close # Close session
106
120
  ```
107
121
 
@@ -109,9 +123,11 @@ patchright-cli close # Close session
109
123
 
110
124
  ```bash
111
125
  patchright-cli goto https://example.com
112
- patchright-cli go-back
126
+ patchright-cli go-back # Uses internal history stack
113
127
  patchright-cli go-forward
114
128
  patchright-cli reload
129
+ patchright-cli url # Print current URL
130
+ patchright-cli title # Print page title
115
131
  ```
116
132
 
117
133
  ### Snapshots
@@ -138,6 +154,8 @@ patchright-cli hover e4
138
154
  patchright-cli drag e2 e8 # Drag element to target
139
155
  ```
140
156
 
157
+ `click` is smart about links: if the element (or an ancestor) is an `<a>` tag, the CLI navigates directly instead of performing a DOM click. This avoids sticky-header overlay timeouts and `target="_blank"` silences.
158
+
141
159
  ### Form input
142
160
 
143
161
  ```bash
@@ -152,6 +170,13 @@ patchright-cli uncheck e12
152
170
 
153
171
  `fill` targets a specific input by ref and replaces its contents. `type` types via the keyboard into whatever is focused.
154
172
 
173
+ ### Text extraction
174
+
175
+ ```bash
176
+ patchright-cli text e5 # Get text content by ref
177
+ patchright-cli text "h1" # Or by raw CSS selector
178
+ ```
179
+
155
180
  ### Screenshots
156
181
 
157
182
  ```bash
@@ -163,6 +188,16 @@ patchright-cli screenshot --full-page # Full scrollable page
163
188
 
164
189
  Screenshots save to `.patchright-cli/` in the current directory.
165
190
 
191
+ ### Scroll & wait
192
+
193
+ ```bash
194
+ patchright-cli scroll 0 200 # Scroll by (dx, dy) pixels
195
+ patchright-cli scroll-to e5 # Scroll element into view
196
+ patchright-cli wait 500 # Wait N milliseconds
197
+ patchright-cli wait-for e5 # Wait until element is visible
198
+ patchright-cli wait-for e5 --state=hidden # Wait until hidden
199
+ ```
200
+
166
201
  ### Keyboard and mouse
167
202
 
168
203
  ```bash
@@ -234,7 +269,7 @@ patchright-cli --proxy=http://host:port open https://example.com
234
269
  # SOCKS5 proxy
235
270
  patchright-cli --proxy=socks5://host:port open https://example.com
236
271
 
237
- # Authenticated proxy
272
+ # Authenticated proxy (credentials are parsed and injected automatically)
238
273
  patchright-cli --proxy=http://user:pass@host:port open https://example.com
239
274
 
240
275
  # Combine with persistent profile and named session
@@ -275,14 +310,14 @@ patchright-cli eval --file=/tmp/extract.js
275
310
 
276
311
  ### Waiting for dynamic content
277
312
 
278
- The page may not be fully loaded when you snapshot. If elements are missing, try:
279
-
280
313
  ```bash
281
- # Option 1: Just snapshot again after a short pause
282
- # (most commands auto-wait for navigation to settle)
283
- patchright-cli snapshot
314
+ # Wait for an element to appear
315
+ patchright-cli wait-for e12
316
+
317
+ # Or wait a fixed time
318
+ patchright-cli wait 1000
284
319
 
285
- # Option 2: Use run-code to wait for a specific condition
320
+ # If you need a custom condition, use run-code
286
321
  cat > /tmp/wait.js << 'JSEOF'
287
322
  for (let i = 0; i < 30; i++) {
288
323
  if (document.querySelector('.results-loaded')) return true;
@@ -334,6 +369,8 @@ patchright-cli cookie-set session_id abc123 # Set cookie (current pa
334
369
  patchright-cli cookie-set token xyz --domain=example.com --path=/ --httpOnly --secure --sameSite=Lax --expires=1735689600
335
370
  patchright-cli cookie-delete session_id
336
371
  patchright-cli cookie-clear # Clear all
372
+ patchright-cli cookie-export cookies.json # Export all cookies to JSON
373
+ patchright-cli cookie-import cookies.json # Import cookies from JSON
337
374
  ```
338
375
 
339
376
  ### localStorage / sessionStorage
@@ -441,6 +478,8 @@ patchright-cli delete-data # Delete default session's profile
441
478
  patchright-cli -s=mysession delete-data # Delete named session's profile
442
479
  ```
443
480
 
481
+ The daemon auto-starts on the first command and auto-shuts down after 5 minutes of inactivity. If it ever crashes, the next command you run will respawn it automatically.
482
+
444
483
  ---
445
484
 
446
485
  ## Anti-detect notes
@@ -1,3 +1,3 @@
1
1
  """patchright-cli — Undetected browser automation CLI using Patchright."""
2
2
 
3
- __version__ = "0.3.1"
3
+ __version__ = "0.4.0"
@@ -72,6 +72,7 @@ COMMANDS_HELP = {
72
72
  "uncheck": "uncheck <ref> Uncheck checkbox/radio",
73
73
  "snapshot": "snapshot [ref] Take accessibility snapshot",
74
74
  "eval": "eval <expr> Evaluate JavaScript [--file=F or stdin]",
75
+ "text": "text <ref|selector> Get text content of element",
75
76
  "screenshot": "screenshot [ref] Save screenshot [--full-page] [--filename=F]",
76
77
  "drag": "drag <from> <to> Drag element to target",
77
78
  "close": "close Close browser session",
@@ -79,6 +80,8 @@ COMMANDS_HELP = {
79
80
  "go-back": "go-back Go back",
80
81
  "go-forward": "go-forward Go forward",
81
82
  "reload": "reload Reload page",
83
+ "url": "url Print current URL",
84
+ "title": "title Print page title",
82
85
  # Keyboard
83
86
  "press": "press <key> Press key",
84
87
  "keydown": "keydown <key> Key down",
@@ -88,6 +91,11 @@ COMMANDS_HELP = {
88
91
  "mousedown": "mousedown [button] Mouse button down",
89
92
  "mouseup": "mouseup [button] Mouse button up",
90
93
  "mousewheel": "mousewheel <dx> <dy> Scroll mouse wheel",
94
+ # Scroll & Wait
95
+ "scroll": "scroll <dx> <dy> Scroll by pixel offset",
96
+ "scroll-to": "scroll-to <ref> Scroll element into view",
97
+ "wait": "wait <ms> Wait for milliseconds",
98
+ "wait-for": "wait-for <ref> Wait for element to appear [--state=hidden]",
91
99
  # Tabs
92
100
  "tab-list": "tab-list List tabs",
93
101
  "tab-new": "tab-new [url] Open new tab",
@@ -99,6 +107,8 @@ COMMANDS_HELP = {
99
107
  "cookie-set": "cookie-set <n> <v> Set cookie [--domain --path --expires --httpOnly --secure --sameSite]",
100
108
  "cookie-delete": "cookie-delete <name> Delete cookie",
101
109
  "cookie-clear": "cookie-clear Clear all cookies",
110
+ "cookie-import": "cookie-import <file> Import cookies from JSON",
111
+ "cookie-export": "cookie-export [file] Export cookies to JSON",
102
112
  "localstorage-list": "localstorage-list List localStorage",
103
113
  "localstorage-get": "localstorage-get <k> Get localStorage item",
104
114
  "localstorage-set": "localstorage-set <k> <v> Set localStorage item",
@@ -177,14 +187,16 @@ def _print_help():
177
187
  "uncheck",
178
188
  "snapshot",
179
189
  "eval",
190
+ "text",
180
191
  "screenshot",
181
192
  "drag",
182
193
  "close",
183
194
  ],
184
195
  ),
185
- ("Navigation", ["go-back", "go-forward", "reload"]),
196
+ ("Navigation", ["go-back", "go-forward", "reload", "url", "title"]),
186
197
  ("Keyboard", ["press", "keydown", "keyup"]),
187
198
  ("Mouse", ["mousemove", "mousedown", "mouseup", "mousewheel"]),
199
+ ("Scroll & Wait", ["scroll", "scroll-to", "wait", "wait-for"]),
188
200
  ("Tabs", ["tab-list", "tab-new", "tab-close", "tab-select"]),
189
201
  ("Dialog", ["dialog-accept", "dialog-dismiss"]),
190
202
  ("Upload/Resize", ["upload", "resize"]),
@@ -197,6 +209,8 @@ def _print_help():
197
209
  "cookie-set",
198
210
  "cookie-delete",
199
211
  "cookie-clear",
212
+ "cookie-import",
213
+ "cookie-export",
200
214
  "localstorage-list",
201
215
  "localstorage-get",
202
216
  "localstorage-set",
@@ -340,26 +354,9 @@ def main():
340
354
  if proxy:
341
355
  options["proxy"] = proxy
342
356
 
343
- # Ensure daemon is running (auto-start for 'open', require for others)
357
+ # Ensure daemon is running (auto-start for all commands)
344
358
  try:
345
- if command == "open":
346
- ensure_daemon_running(port, headless)
347
- else:
348
- # Try connecting first; if fails, tell user to open
349
- import socket as _socket
350
-
351
- sock = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM)
352
- try:
353
- sock.settimeout(1)
354
- sock.connect(("127.0.0.1", port))
355
- except (ConnectionRefusedError, OSError, TimeoutError):
356
- click.echo(
357
- f"Daemon is not running on port {port}. Run 'patchright-cli open' first.",
358
- err=True,
359
- )
360
- sys.exit(1)
361
- finally:
362
- sock.close()
359
+ ensure_daemon_running(port, headless)
363
360
  except RuntimeError as e:
364
361
  click.echo(str(e), err=True)
365
362
  sys.exit(1)