patchright-cli 0.3.0__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.
- patchright_cli-0.4.0/.claude-plugin/marketplace.json +21 -0
- patchright_cli-0.4.0/.claude-plugin/skills/browser-automation.json +5 -0
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/.github/workflows/publish.yml +5 -2
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/PKG-INFO +1 -1
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/pyproject.toml +13 -1
- patchright_cli-0.4.0/skills/patchright-cli/SKILL.md +492 -0
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/src/patchright_cli/__init__.py +1 -1
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/src/patchright_cli/cli.py +26 -20
- patchright_cli-0.4.0/src/patchright_cli/daemon.py +1462 -0
- patchright_cli-0.4.0/src/patchright_cli/ref_registry.py +74 -0
- patchright_cli-0.4.0/src/patchright_cli/snapshot.py +46 -0
- patchright_cli-0.4.0/tests/__init__.py +0 -0
- patchright_cli-0.4.0/tests/fixture.html +30 -0
- patchright_cli-0.4.0/tests/test_daemon_handlers.py +124 -0
- patchright_cli-0.4.0/tests/test_e2e.py +144 -0
- patchright_cli-0.4.0/tests/test_ref_registry.py +75 -0
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/uv.lock +285 -129
- patchright_cli-0.3.0/skills/patchright-cli/SKILL.md +0 -274
- patchright_cli-0.3.0/src/patchright_cli/daemon.py +0 -1088
- patchright_cli-0.3.0/src/patchright_cli/snapshot.py +0 -346
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/.gitignore +0 -0
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/.pre-commit-config.yaml +0 -0
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/CLAUDE.md +0 -0
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/CONTRIBUTING.md +0 -0
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/LICENSE +0 -0
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/README.md +0 -0
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/docs/installation.md +0 -0
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/patchright-cli +0 -0
- {patchright_cli-0.3.0 → patchright_cli-0.4.0}/patchright-cli.cmd +0 -0
- {patchright_cli-0.3.0 → 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
|
+
}
|
|
@@ -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@
|
|
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@
|
|
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
|
+
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
|
+
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
|
|
@@ -0,0 +1,492 @@
|
|
|
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
|
+
## 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
|
+
|
|
23
|
+
## How it works: the snapshot-driven loop
|
|
24
|
+
|
|
25
|
+
Every interaction follows the same cycle:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
open browser → snapshot → read refs → interact → snapshot again → repeat
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
1. **Open** a browser session — this launches a real Chrome window
|
|
32
|
+
2. **Snapshot** the page — this uses Playwright's accessibility tree and assigns refs (`e1`, `e2`, ...) to interactive elements
|
|
33
|
+
3. **Read the snapshot** — it's a YAML file showing the element tree with refs
|
|
34
|
+
4. **Interact** using refs — `click e5`, `fill e3 "hello"`, etc.
|
|
35
|
+
5. **Check the result** — most commands auto-snapshot, so you get updated refs
|
|
36
|
+
|
|
37
|
+
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.
|
|
38
|
+
|
|
39
|
+
## Quick start
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
patchright-cli open https://example.com # launch browser + navigate
|
|
43
|
+
patchright-cli snapshot # get element refs
|
|
44
|
+
# read the snapshot YAML to find the right ref, then:
|
|
45
|
+
patchright-cli click e5 # interact by ref
|
|
46
|
+
patchright-cli fill e3 "search query" # type into an input
|
|
47
|
+
patchright-cli press Enter # press a key
|
|
48
|
+
patchright-cli screenshot # capture the page
|
|
49
|
+
patchright-cli close # done
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
### CLI tool
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Recommended — always runs latest version
|
|
58
|
+
uvx patchright-cli <command>
|
|
59
|
+
|
|
60
|
+
# Or install globally
|
|
61
|
+
pip install patchright-cli
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Skill (for AI coding agents)
|
|
65
|
+
|
|
66
|
+
Install the skill so your agent knows how to use patchright-cli. The same command also works to update to the latest version.
|
|
67
|
+
|
|
68
|
+
**macOS / Linux (bash/zsh):**
|
|
69
|
+
|
|
70
|
+
| Agent | Install / update command |
|
|
71
|
+
|-------|--------------------------|
|
|
72
|
+
| **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` |
|
|
73
|
+
| **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` |
|
|
74
|
+
| **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` |
|
|
75
|
+
| **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` |
|
|
76
|
+
|
|
77
|
+
**Windows (PowerShell):**
|
|
78
|
+
|
|
79
|
+
| Agent | Install / update command |
|
|
80
|
+
|-------|--------------------------|
|
|
81
|
+
| **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"` |
|
|
82
|
+
| **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"` |
|
|
83
|
+
| **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"` |
|
|
84
|
+
| **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"` |
|
|
85
|
+
|
|
86
|
+
**IDE-based agents (Cursor / Windsurf / Aider):** Copy `SKILL.md` to `.<tool>/skills/patchright-cli/` in your project.
|
|
87
|
+
|
|
88
|
+
**Or just tell your agent:**
|
|
89
|
+
> Install patchright-cli skill from https://raw.githubusercontent.com/AhaiMk01/patchright-cli/main/skills/patchright-cli/SKILL.md
|
|
90
|
+
|
|
91
|
+
## Global options
|
|
92
|
+
|
|
93
|
+
These go before the command:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
--headless # Run headless (default: headed — headed is less detectable)
|
|
97
|
+
--persistent # Use persistent profile (keeps cookies/storage across sessions)
|
|
98
|
+
--profile=/path # Custom profile directory
|
|
99
|
+
--proxy=<url> # Proxy server (http, https, socks5) — supports user:pass@host auth
|
|
100
|
+
-s=mysession # Named session (default: "default")
|
|
101
|
+
--port=9322 # Custom daemon port (default: 9321)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Core commands
|
|
107
|
+
|
|
108
|
+
### Browser lifecycle
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
patchright-cli open # Launch browser
|
|
112
|
+
patchright-cli open https://example.com # Launch and navigate
|
|
113
|
+
patchright-cli open --persistent # Keep cookies/storage between runs
|
|
114
|
+
patchright-cli open --headless # Headless mode
|
|
115
|
+
patchright-cli open --profile=/path/to/dir # Custom profile directory
|
|
116
|
+
patchright-cli --proxy=http://host:port open # Route traffic through HTTP proxy
|
|
117
|
+
patchright-cli --proxy=socks5://host:port open # SOCKS5 proxy
|
|
118
|
+
patchright-cli --proxy=http://user:pass@host:port open # Authenticated proxy
|
|
119
|
+
patchright-cli close # Close session
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Navigation
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
patchright-cli goto https://example.com
|
|
126
|
+
patchright-cli go-back # Uses internal history stack
|
|
127
|
+
patchright-cli go-forward
|
|
128
|
+
patchright-cli reload
|
|
129
|
+
patchright-cli url # Print current URL
|
|
130
|
+
patchright-cli title # Print page title
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Snapshots
|
|
134
|
+
|
|
135
|
+
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`.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
patchright-cli snapshot # Full page snapshot
|
|
139
|
+
patchright-cli snapshot e3 # Subtree of a specific element
|
|
140
|
+
patchright-cli snapshot --filename=snap.yml # Save to custom path
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
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.
|
|
144
|
+
|
|
145
|
+
### Clicking and interacting
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
patchright-cli click e3 # Left-click
|
|
149
|
+
patchright-cli click e3 right # Right-click
|
|
150
|
+
patchright-cli click e3 --modifiers=Alt,Shift # Click with modifier keys
|
|
151
|
+
patchright-cli dblclick e7 # Double-click
|
|
152
|
+
patchright-cli dblclick e7 --modifiers=Shift
|
|
153
|
+
patchright-cli hover e4
|
|
154
|
+
patchright-cli drag e2 e8 # Drag element to target
|
|
155
|
+
```
|
|
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
|
+
|
|
159
|
+
### Form input
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
patchright-cli fill e5 "user@example.com" # Clear field and type value
|
|
163
|
+
patchright-cli fill e5 "query" --submit # Fill and press Enter
|
|
164
|
+
patchright-cli type "search query" # Type via keyboard (no target element)
|
|
165
|
+
patchright-cli type "query" --submit # Type and press Enter
|
|
166
|
+
patchright-cli select e9 "option-value" # Select dropdown option
|
|
167
|
+
patchright-cli check e12 # Check checkbox/radio
|
|
168
|
+
patchright-cli uncheck e12
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`fill` targets a specific input by ref and replaces its contents. `type` types via the keyboard into whatever is focused.
|
|
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
|
+
|
|
180
|
+
### Screenshots
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
patchright-cli screenshot # Page screenshot
|
|
184
|
+
patchright-cli screenshot e3 # Element screenshot
|
|
185
|
+
patchright-cli screenshot --filename=page.png # Custom filename
|
|
186
|
+
patchright-cli screenshot --full-page # Full scrollable page
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Screenshots save to `.patchright-cli/` in the current directory.
|
|
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
|
+
|
|
201
|
+
### Keyboard and mouse
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# Keyboard
|
|
205
|
+
patchright-cli press Enter # Single keypress
|
|
206
|
+
patchright-cli press ArrowDown
|
|
207
|
+
patchright-cli keydown Shift # Hold key down
|
|
208
|
+
patchright-cli keyup Shift # Release key
|
|
209
|
+
|
|
210
|
+
# Mouse
|
|
211
|
+
patchright-cli mousemove 150 300 # Move to coordinates
|
|
212
|
+
patchright-cli mousedown # Left button down
|
|
213
|
+
patchright-cli mousedown right # Right button down
|
|
214
|
+
patchright-cli mouseup
|
|
215
|
+
patchright-cli mousewheel 0 100 # Scroll (dx, dy)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Tabs
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
patchright-cli tab-list # List open tabs
|
|
222
|
+
patchright-cli tab-new https://example.com # Open new tab
|
|
223
|
+
patchright-cli tab-select 0 # Switch to tab by index
|
|
224
|
+
patchright-cli tab-close # Close current tab
|
|
225
|
+
patchright-cli tab-close 2 # Close tab by index
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## JavaScript execution
|
|
231
|
+
|
|
232
|
+
**Always use `--file` or stdin for `eval` and `run-code`.** Inline JS breaks because quotes get mangled through shell layers (bash -> uvx -> python).
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
# WRONG — nested quotes break
|
|
236
|
+
patchright-cli eval "document.querySelector('a').href"
|
|
237
|
+
|
|
238
|
+
# RIGHT — write to a temp file
|
|
239
|
+
cat > /tmp/check.js << 'JSEOF'
|
|
240
|
+
JSON.stringify({title: document.title, links: document.querySelectorAll('a').length})
|
|
241
|
+
JSEOF
|
|
242
|
+
patchright-cli eval --file=/tmp/check.js
|
|
243
|
+
|
|
244
|
+
# RIGHT — pipe via stdin (simple expressions)
|
|
245
|
+
echo 'document.title' | patchright-cli eval
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
`eval` returns the expression result. `run-code` wraps your code in `async () => { ... }` so you can use `return` and `await`.
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
# run-code example
|
|
252
|
+
cat > /tmp/scroll.js << 'JSEOF'
|
|
253
|
+
window.scrollTo(0, document.body.scrollHeight);
|
|
254
|
+
return document.body.scrollHeight;
|
|
255
|
+
JSEOF
|
|
256
|
+
patchright-cli run-code --file=/tmp/scroll.js
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Common patterns
|
|
262
|
+
|
|
263
|
+
### Using a proxy
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# HTTP proxy
|
|
267
|
+
patchright-cli --proxy=http://host:port open https://example.com
|
|
268
|
+
|
|
269
|
+
# SOCKS5 proxy
|
|
270
|
+
patchright-cli --proxy=socks5://host:port open https://example.com
|
|
271
|
+
|
|
272
|
+
# Authenticated proxy (credentials are parsed and injected automatically)
|
|
273
|
+
patchright-cli --proxy=http://user:pass@host:port open https://example.com
|
|
274
|
+
|
|
275
|
+
# Combine with persistent profile and named session
|
|
276
|
+
patchright-cli --proxy=http://host:port -s=proxied open https://example.com --persistent
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
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.
|
|
280
|
+
|
|
281
|
+
### Login flow
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
patchright-cli open https://example.com/login --persistent
|
|
285
|
+
patchright-cli snapshot
|
|
286
|
+
# Find the username/password fields and login button in the snapshot
|
|
287
|
+
patchright-cli fill e3 "user@example.com"
|
|
288
|
+
patchright-cli fill e5 "password123"
|
|
289
|
+
patchright-cli click e8 # Click login button
|
|
290
|
+
# Wait a moment for redirect, then snapshot to verify
|
|
291
|
+
patchright-cli snapshot
|
|
292
|
+
# With --persistent, cookies survive across sessions
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Extracting data from a page
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
patchright-cli open https://example.com/data
|
|
299
|
+
patchright-cli snapshot # Get the page structure
|
|
300
|
+
# Use eval to extract structured data
|
|
301
|
+
cat > /tmp/extract.js << 'JSEOF'
|
|
302
|
+
JSON.stringify(
|
|
303
|
+
[...document.querySelectorAll('table tr')].map(row =>
|
|
304
|
+
[...row.cells].map(cell => cell.textContent.trim())
|
|
305
|
+
)
|
|
306
|
+
)
|
|
307
|
+
JSEOF
|
|
308
|
+
patchright-cli eval --file=/tmp/extract.js
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Waiting for dynamic content
|
|
312
|
+
|
|
313
|
+
```bash
|
|
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
|
|
319
|
+
|
|
320
|
+
# If you need a custom condition, use run-code
|
|
321
|
+
cat > /tmp/wait.js << 'JSEOF'
|
|
322
|
+
for (let i = 0; i < 30; i++) {
|
|
323
|
+
if (document.querySelector('.results-loaded')) return true;
|
|
324
|
+
await new Promise(r => setTimeout(r, 500));
|
|
325
|
+
}
|
|
326
|
+
return false;
|
|
327
|
+
JSEOF
|
|
328
|
+
patchright-cli run-code --file=/tmp/wait.js
|
|
329
|
+
patchright-cli snapshot
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Multi-page workflow with persistent session
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
# Use a named persistent session to maintain state
|
|
336
|
+
patchright-cli -s=myproject open https://app.example.com --persistent
|
|
337
|
+
patchright-cli -s=myproject snapshot
|
|
338
|
+
patchright-cli -s=myproject click e5
|
|
339
|
+
# ... do work ...
|
|
340
|
+
patchright-cli -s=myproject close
|
|
341
|
+
# Later, reopen — cookies and localStorage are preserved
|
|
342
|
+
patchright-cli -s=myproject open https://app.example.com --persistent
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Handling dialogs (alert/confirm/prompt)
|
|
346
|
+
|
|
347
|
+
Dialogs must be pre-armed *before* the action that triggers them:
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
patchright-cli dialog-accept # Accept next dialog
|
|
351
|
+
patchright-cli click e5 # This click triggers the dialog
|
|
352
|
+
# Or:
|
|
353
|
+
patchright-cli dialog-accept "OK" # Accept with text input
|
|
354
|
+
patchright-cli dialog-dismiss # Dismiss instead
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Storage and state
|
|
360
|
+
|
|
361
|
+
### Cookies
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
patchright-cli cookie-list # All cookies
|
|
365
|
+
patchright-cli cookie-list --domain=example.com # Filter by domain
|
|
366
|
+
patchright-cli cookie-list --path=/api # Filter by path
|
|
367
|
+
patchright-cli cookie-get session_id # Get specific cookie
|
|
368
|
+
patchright-cli cookie-set session_id abc123 # Set cookie (current page URL)
|
|
369
|
+
patchright-cli cookie-set token xyz --domain=example.com --path=/ --httpOnly --secure --sameSite=Lax --expires=1735689600
|
|
370
|
+
patchright-cli cookie-delete session_id
|
|
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
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### localStorage / sessionStorage
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
# localStorage
|
|
380
|
+
patchright-cli localstorage-list
|
|
381
|
+
patchright-cli localstorage-get theme
|
|
382
|
+
patchright-cli localstorage-set theme dark
|
|
383
|
+
patchright-cli localstorage-delete theme
|
|
384
|
+
patchright-cli localstorage-clear
|
|
385
|
+
|
|
386
|
+
# sessionStorage (same pattern)
|
|
387
|
+
patchright-cli sessionstorage-list
|
|
388
|
+
patchright-cli sessionstorage-get step
|
|
389
|
+
patchright-cli sessionstorage-set step 3
|
|
390
|
+
patchright-cli sessionstorage-delete step
|
|
391
|
+
patchright-cli sessionstorage-clear
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Save/load full state (cookies + storage)
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
patchright-cli state-save auth.json # Save cookies + localStorage
|
|
398
|
+
patchright-cli state-load auth.json # Restore (navigate to matching origin first for localStorage)
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## Network tools
|
|
404
|
+
|
|
405
|
+
### Request mocking
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
patchright-cli route "**/*.jpg" --status=404 # Block images
|
|
409
|
+
patchright-cli route "https://api.example.com/**" --body='{"mock": true}' # Mock API
|
|
410
|
+
patchright-cli route "**/*" --content-type=application/json --body='{"ok":true}'
|
|
411
|
+
patchright-cli route "**/*" --header=X-Custom:value
|
|
412
|
+
patchright-cli route "**/*" --remove-header=Content-Type
|
|
413
|
+
patchright-cli route-list # List active routes
|
|
414
|
+
patchright-cli unroute "**/*.jpg" # Remove specific route
|
|
415
|
+
patchright-cli unroute # Remove all routes
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Network state
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
patchright-cli network-state-set offline # Simulate offline
|
|
422
|
+
patchright-cli network-state-set online # Restore connectivity
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### DevTools inspection
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
patchright-cli console # Show console messages (last 50)
|
|
429
|
+
patchright-cli console warning # Filter by level
|
|
430
|
+
patchright-cli console --clear # Clear buffer after printing
|
|
431
|
+
|
|
432
|
+
patchright-cli network # Show requests (excludes static assets)
|
|
433
|
+
patchright-cli network --static # Include images, fonts, scripts, etc.
|
|
434
|
+
patchright-cli network --clear # Clear log after printing
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## Recording and capture
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
# Tracing (Playwright trace format)
|
|
443
|
+
patchright-cli tracing-start
|
|
444
|
+
patchright-cli tracing-stop # Saves .zip to .patchright-cli/
|
|
445
|
+
|
|
446
|
+
# Video (CDP screencast, requires ffmpeg for .webm output)
|
|
447
|
+
patchright-cli video-start
|
|
448
|
+
patchright-cli video-stop # Save as .webm (or frames if no ffmpeg)
|
|
449
|
+
patchright-cli video-stop --filename=rec.webm
|
|
450
|
+
|
|
451
|
+
# PDF
|
|
452
|
+
patchright-cli pdf # Save page as PDF
|
|
453
|
+
patchright-cli pdf --filename=page.pdf
|
|
454
|
+
|
|
455
|
+
# File upload
|
|
456
|
+
patchright-cli upload ./document.pdf # Upload to first file input
|
|
457
|
+
patchright-cli upload ./photo.jpg e5 # Upload to specific input
|
|
458
|
+
|
|
459
|
+
# Viewport resize
|
|
460
|
+
patchright-cli resize 1920 1080
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
## Session management
|
|
466
|
+
|
|
467
|
+
```bash
|
|
468
|
+
# Named sessions allow multiple independent browsers
|
|
469
|
+
patchright-cli -s=session1 open https://site-a.com --persistent
|
|
470
|
+
patchright-cli -s=session2 open https://site-b.com --persistent
|
|
471
|
+
|
|
472
|
+
patchright-cli list # List all active sessions
|
|
473
|
+
patchright-cli close-all # Gracefully close all
|
|
474
|
+
patchright-cli kill-all # Force-kill all + stop daemon
|
|
475
|
+
|
|
476
|
+
# Delete persistent profile data
|
|
477
|
+
patchright-cli delete-data # Delete default session's profile
|
|
478
|
+
patchright-cli -s=mysession delete-data # Delete named session's profile
|
|
479
|
+
```
|
|
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
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## Anti-detect notes
|
|
486
|
+
|
|
487
|
+
- Uses real Chrome (not Chromium) — this is what makes it undetectable
|
|
488
|
+
- Patchright patches `navigator.webdriver` and other detection vectors automatically
|
|
489
|
+
- Headed by default — headless mode is more detectable, use only when necessary
|
|
490
|
+
- No custom user-agent or headers — preserves Chrome's natural fingerprint
|
|
491
|
+
- Persistent profiles maintain realistic browser history and cookies
|
|
492
|
+
- The daemon architecture means Chrome stays running between commands, behaving like a real user's browser
|