deja-browser 0.1.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.
- deja_browser-0.1.1/LICENSE +21 -0
- deja_browser-0.1.1/PKG-INFO +244 -0
- deja_browser-0.1.1/README.md +210 -0
- deja_browser-0.1.1/pyproject.toml +49 -0
- deja_browser-0.1.1/setup.cfg +4 -0
- deja_browser-0.1.1/src/deja_browser/__init__.py +2 -0
- deja_browser-0.1.1/src/deja_browser/browser.py +717 -0
- deja_browser-0.1.1/src/deja_browser/config.py +83 -0
- deja_browser-0.1.1/src/deja_browser/guard.py +145 -0
- deja_browser-0.1.1/src/deja_browser/hcaptcha.py +107 -0
- deja_browser-0.1.1/src/deja_browser/notify.py +36 -0
- deja_browser-0.1.1/src/deja_browser/recipe.py +751 -0
- deja_browser-0.1.1/src/deja_browser/secretstore.py +92 -0
- deja_browser-0.1.1/src/deja_browser.egg-info/PKG-INFO +244 -0
- deja_browser-0.1.1/src/deja_browser.egg-info/SOURCES.txt +20 -0
- deja_browser-0.1.1/src/deja_browser.egg-info/dependency_links.txt +1 -0
- deja_browser-0.1.1/src/deja_browser.egg-info/entry_points.txt +3 -0
- deja_browser-0.1.1/src/deja_browser.egg-info/requires.txt +17 -0
- deja_browser-0.1.1/src/deja_browser.egg-info/top_level.txt +1 -0
- deja_browser-0.1.1/tests/test_browser.py +376 -0
- deja_browser-0.1.1/tests/test_platform.py +220 -0
- deja_browser-0.1.1/tests/test_recipe.py +181 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 deja-browser authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: deja-browser
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: The agent browser that remembers: a separate Chromium profile your AI agent drives over CDP, with site recipes so the second visit skips reading the page.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/drpwchen/deja-browser
|
|
7
|
+
Project-URL: Changelog, https://github.com/drpwchen/deja-browser/blob/main/CHANGELOG.md
|
|
8
|
+
Project-URL: Issues, https://github.com/drpwchen/deja-browser/issues
|
|
9
|
+
Keywords: browser-automation,cdp,ai-agent,claude-code,playwright,captcha
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Classifier: Operating System :: MacOS
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: playwright>=1.45
|
|
22
|
+
Provides-Extra: stealth
|
|
23
|
+
Requires-Dist: patchright; extra == "stealth"
|
|
24
|
+
Provides-Extra: keyring
|
|
25
|
+
Requires-Dist: keyring; extra == "keyring"
|
|
26
|
+
Provides-Extra: audio
|
|
27
|
+
Requires-Dist: faster-whisper; extra == "audio"
|
|
28
|
+
Requires-Dist: av<19; extra == "audio"
|
|
29
|
+
Provides-Extra: ocr
|
|
30
|
+
Requires-Dist: ddddocr; extra == "ocr"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# deja-browser
|
|
36
|
+
|
|
37
|
+
*The agent browser that remembers.* (Formerly edge-recipes.)
|
|
38
|
+
|
|
39
|
+
**A browser for your AI agent that is not your browser.** A separate Chromium profile your agent
|
|
40
|
+
drives over CDP — with no telemetry, no extension in your everyday browser, and site *recipes*
|
|
41
|
+
so the second visit to a site does not need to read the page at all.
|
|
42
|
+
|
|
43
|
+
Works with any agent that can run shell commands (Claude Code, Codex CLI, Gemini CLI, Cursor,
|
|
44
|
+
Aider, …) and from plain Python.
|
|
45
|
+
|
|
46
|
+
> **Let your agent install it.** Tell it: *"Read
|
|
47
|
+
> https://github.com/drpwchen/deja-browser/blob/main/AGENTS.md and set this up with me."* It will
|
|
48
|
+
> ask you the few choices that matter, have you log in to your sites by hand, and run a smoke test.
|
|
49
|
+
|
|
50
|
+
> **Status: early release (0.1).** Tested on Windows 11 (Edge), macOS on Apple Silicon (Chrome)
|
|
51
|
+
> and Linux (headless Chromium, in the egress test). Feedback and recipes-in-the-wild welcome.
|
|
52
|
+
|
|
53
|
+
## Why
|
|
54
|
+
|
|
55
|
+
Browser-extension bridges for agents put an extension with full debugger access into the browser
|
|
56
|
+
where you are logged in to everything, and some of them phone home with no way to turn it off.
|
|
57
|
+
Browsers have also stopped letting you fence such extensions away from chosen sites. deja-browser
|
|
58
|
+
takes the other route:
|
|
59
|
+
|
|
60
|
+
- **Separation instead of a block list.** The agent gets its own profile. You log in there only to
|
|
61
|
+
the sites it should use. Your mail, bank and broker are simply not logged in.
|
|
62
|
+
- **No telemetry, tested.** The tool makes no outbound connection of its own.
|
|
63
|
+
[`tests/egress/run.sh`](tests/egress/run.sh) runs every action and a full recipe cycle inside a
|
|
64
|
+
network namespace with only loopback, traces every `connect()` of the tool's processes, and
|
|
65
|
+
fails on anything that is not `127.0.0.1` (its `SELFTEST=1` mode proves the check catches a
|
|
66
|
+
deliberate connection). The only outbound features are ones you switch on: ntfy notifications
|
|
67
|
+
and the opt-in hCaptcha solver.
|
|
68
|
+
- **No passwords in the browser.** On launch the profile's password, card and address autofill is
|
|
69
|
+
turned off, and a password-manager extension installed in it triggers a warning. Secrets the
|
|
70
|
+
agent may use stay in your OS keyring or password-manager CLI and are only named in recipes.
|
|
71
|
+
- **Cheap to read.** Snapshots can be cut to one subtree, to interactive elements, or to lines
|
|
72
|
+
matching a word; screenshots and PDFs come back as file paths, never as inline images.
|
|
73
|
+
- **Learn once, replay.** The first visit finds the JSON endpoint or the form; the recipe replays
|
|
74
|
+
it later, outside the browser when cookies are enough.
|
|
75
|
+
|
|
76
|
+
## What it does
|
|
77
|
+
|
|
78
|
+
- **Dedicated browser profile.** Drives any Chromium browser (Edge, Chrome, Chromium, Brave —
|
|
79
|
+
auto-detected) over CDP on `127.0.0.1` only, with its own user-data dir. Your everyday browser
|
|
80
|
+
profile is never touched. Kimi-WebBridge-compatible action names and return shapes, so scripts
|
|
81
|
+
written for that bridge port over.
|
|
82
|
+
- **Named sessions.** Every task names a session; its tabs are tracked across processes and
|
|
83
|
+
`close_session` closes only those.
|
|
84
|
+
- **API discovery.** `network_capture` records the requests one action triggers (bodies to files,
|
|
85
|
+
credential headers redacted) — the raw material for a recipe.
|
|
86
|
+
- **Recipes with a tier ladder** (cheapest first, falls through on failure, records what worked):
|
|
87
|
+
- `http` — plain HTTP outside the browser, with cookies read live from the browser (never stored)
|
|
88
|
+
- `page` — `fetch()` inside a tab on the site (native cookies, Cloudflare clearance, CSRF)
|
|
89
|
+
- `script` — the recipe's own JavaScript in the page (DOM read / form fill)
|
|
90
|
+
- **Shape checks.** Every response is compared with the JSON shape recorded at verify time; a
|
|
91
|
+
mismatch is reported as *stale*, never returned as data.
|
|
92
|
+
- **Write guard.** Recipes with side effects (`"writes": true`) only run with `--allow-write`.
|
|
93
|
+
- **Secrets by name.** Recipes reference `{secret:NAME}`; values are resolved in-process and are
|
|
94
|
+
never printed or returned, and never typed into a refused host.
|
|
95
|
+
- **CAPTCHA gate.** Waits for Turnstile / Cloudflare to clear, then tries one trusted checkbox
|
|
96
|
+
click. Local solvers (reCAPTCHA audio via `faster-whisper`, text CAPTCHAs via `ddddocr`) run only
|
|
97
|
+
if you install those extras; the hCaptcha solver only if you enable it. Otherwise it notifies you.
|
|
98
|
+
- **Guard rails.** `navigate` and recipes refuse mail, account sign-in, banking, brokerage and
|
|
99
|
+
payment hosts (built-in list, extendable); recipes also refuse ticketing / rail-booking hosts by
|
|
100
|
+
default. These stop accidents, not attackers — see *Safety model*.
|
|
101
|
+
|
|
102
|
+
## Options at a glance
|
|
103
|
+
|
|
104
|
+
| | Options | Notes |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| OS | Windows, macOS, Linux | Linux tested headless only |
|
|
107
|
+
| Browser | Edge, Chrome, Chromium, Brave, any Chromium (`[browser] executable`) | no Firefox / Safari (no CDP) |
|
|
108
|
+
| Driver | `patchright` (extra `stealth`, used when installed), `playwright` | patchright passes more bot checks |
|
|
109
|
+
| Secrets | `keyring` (default), `command`, `env`, `python` | `command` runs 1Password `op`, Bitwarden `bw`, macOS `security`, `pass`, … |
|
|
110
|
+
| Notifications | ntfy URL, any command, stderr (default) | for "a human is needed" |
|
|
111
|
+
| CAPTCHA extras | `audio` (local), `ocr` (local), hCaptcha solver (cloud, opt-in) | none installed by default |
|
|
112
|
+
| Agents | anything with a shell; Agent Skills folder in `skills/deja-browser/` | Python API: `from deja_browser.browser import wb` |
|
|
113
|
+
|
|
114
|
+
## Safety model
|
|
115
|
+
|
|
116
|
+
What protects you is **separation**: the agent profile is never logged in to mail, banking or
|
|
117
|
+
brokerage, and stores no passwords. The refused-host list is a guard rail: it stops an agent from
|
|
118
|
+
navigating there by mistake and keeps stored secrets from being typed into those sites, but a page
|
|
119
|
+
script can still redirect the tab, and an agent with shell access can edit your config. Treat it
|
|
120
|
+
as a seat belt, not a lock.
|
|
121
|
+
|
|
122
|
+
Password managers: do not install their extension in the agent profile — while unlocked it can
|
|
123
|
+
fill any saved password for whatever is driving the page. To let the agent log in to a few
|
|
124
|
+
low-risk sites by itself, give it a dedicated vault through the password manager's CLI
|
|
125
|
+
(`[secrets] backend = "command"`, see `config.example.toml`). 1Password service accounts can be
|
|
126
|
+
limited to one vault; an unlocked Bitwarden CLI can read the whole vault.
|
|
127
|
+
|
|
128
|
+
Two things no tool can change: the browser vendor's own services (e.g. Safe Browsing / SmartScreen
|
|
129
|
+
URL checks) still apply to the agent profile, and whatever page content your agent reads goes to
|
|
130
|
+
its model provider. Keep sensitive pages (health records, personal data) out of agent sessions.
|
|
131
|
+
|
|
132
|
+
## Install
|
|
133
|
+
|
|
134
|
+
Requires Python ≥ 3.11 and a Chromium-based browser.
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
pip install "deja-browser[stealth,keyring]" # recommended: patchright driver + OS keyring secrets
|
|
138
|
+
pip install "deja-browser[audio,ocr]" # reCAPTCHA audio (faster-whisper), text CAPTCHAs (ddddocr)
|
|
139
|
+
pip install -e ".[dev]" # from a clone: core + pytest
|
|
140
|
+
python -m playwright install-deps # Linux only, if system libraries are missing
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
`deja-browser` uses your installed browser; it does not need `playwright install`.
|
|
144
|
+
|
|
145
|
+
## Quick start
|
|
146
|
+
|
|
147
|
+
```sh
|
|
148
|
+
deja-cdp launch # start the dedicated browser; log in to sites by hand if needed
|
|
149
|
+
deja-cdp navigate '{"url": "https://example.com"}' --session demo
|
|
150
|
+
deja-cdp evaluate '{"code": "document.title"}' --session demo
|
|
151
|
+
deja-cdp close_session '{}' --session demo
|
|
152
|
+
|
|
153
|
+
deja-browser verify draft.json '{"q": "rust"}' # try every tier, print shape + preview
|
|
154
|
+
deja-browser save draft.json # only after a passing verify of this draft
|
|
155
|
+
deja-browser run hn.algolia.com/search '{"q": "rust"}'
|
|
156
|
+
deja-browser list
|
|
157
|
+
deja-browser gate https://example.com/login # open a URL, clear any challenge, report
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
From Python:
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
from deja_browser.browser import wb
|
|
164
|
+
wb("navigate", {"url": "https://example.com"}, session="task")
|
|
165
|
+
wb("snapshot", {"max_chars": 4000}, session="task")
|
|
166
|
+
wb("close_session", {}, session="task")
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`deja-cdp --help` and `deja-browser --help` list every action and the full recipe format.
|
|
170
|
+
|
|
171
|
+
## Recipe format (abridged)
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"version": 1,
|
|
176
|
+
"name": "search",
|
|
177
|
+
"description": "Hacker News full-text search (example)",
|
|
178
|
+
"entry_url": "https://hn.algolia.com/",
|
|
179
|
+
"params": [{"name": "q", "required": true}],
|
|
180
|
+
"request": {"method": "GET", "url": "https://hn.algolia.com/api/v1/search?query={q}"},
|
|
181
|
+
"pick": {"path": "hits", "fields": ["title", "url"], "limit": 20},
|
|
182
|
+
"writes": false
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
No recipes ship with the package — you (or your agent) build them per site. Recipes are stored as `<recipes dir>/<host>/<name>.json` and addressed as `<host>/<name>`.
|
|
187
|
+
|
|
188
|
+
## Configuration
|
|
189
|
+
|
|
190
|
+
Optional. Copy `config.example.toml` to:
|
|
191
|
+
|
|
192
|
+
| OS | Path |
|
|
193
|
+
|---|---|
|
|
194
|
+
| Windows | `%APPDATA%\deja-browser\config.toml` |
|
|
195
|
+
| macOS | `~/Library/Application Support/deja-browser/config.toml` |
|
|
196
|
+
| Linux | `~/.config/deja-browser/config.toml` |
|
|
197
|
+
|
|
198
|
+
or point `DEJA_BROWSER_CONFIG` at a file. It covers the browser executable and profile, the
|
|
199
|
+
recipes directory, extra denied hosts, the secret backend (`keyring` / `env` / `python`), and
|
|
200
|
+
notifications (an ntfy URL or any command; default is stderr).
|
|
201
|
+
|
|
202
|
+
## hCaptcha solver (opt-in, cloud)
|
|
203
|
+
|
|
204
|
+
Off by default. When enabled, the CAPTCHA gate hands hCaptcha to
|
|
205
|
+
[hcaptcha-challenger](https://github.com/QIN2DIM/hcaptcha-challenger), which asks Google Gemini to
|
|
206
|
+
answer the challenge. **This sends the cropped challenge image to Google** under your own API key
|
|
207
|
+
(not the page, not cookies). hcaptcha-challenger is GPL-3.0 and is not bundled — install it
|
|
208
|
+
yourself:
|
|
209
|
+
|
|
210
|
+
```sh
|
|
211
|
+
pip install "hcaptcha-challenger @ git+https://github.com/QIN2DIM/hcaptcha-challenger@28ee79b"
|
|
212
|
+
keyring set deja-browser GEMINI_API_KEY # or your configured secret backend
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
```toml
|
|
216
|
+
[captcha]
|
|
217
|
+
hcaptcha_solver = "gemini"
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Best effort: on the public demo the "drag the missing item into the grid" type passed 13/15, the
|
|
221
|
+
hexagon shape-matching type 1/5 (small samples). Failures fall through to the human step.
|
|
222
|
+
|
|
223
|
+
## Acceptable use
|
|
224
|
+
|
|
225
|
+
This is a personal automation tool for sites and accounts you are entitled to use. Respect each
|
|
226
|
+
site's terms of service and rate limits. Do not use it for ticket scalping, mass account
|
|
227
|
+
creation, credential stuffing, or to defeat protections on systems you do not own. Ticket and
|
|
228
|
+
rail-booking sites are refused by default: several jurisdictions criminalise automated ticket
|
|
229
|
+
purchase (e.g. Taiwan's Railway Act art. 65). `[recipes] allow_ticket_hosts` can lift that; we
|
|
230
|
+
recommend you don't, and the decision and its consequences are yours. The project
|
|
231
|
+
does not integrate paid CAPTCHA-solving services and will not.
|
|
232
|
+
|
|
233
|
+
## Tests
|
|
234
|
+
|
|
235
|
+
```sh
|
|
236
|
+
python -m pytest -q # pure functions; no browser, no network
|
|
237
|
+
sudo PY=$(which python) tests/egress/run.sh # Linux: no outbound connection (needs strace)
|
|
238
|
+
sudo PY=$(which python) SELFTEST=1 tests/egress/run.sh # must FAIL: proves the check catches one
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## License
|
|
242
|
+
|
|
243
|
+
MIT — see `LICENSE`. Optional dependencies keep their own licenses; GPL-licensed packages are
|
|
244
|
+
never vendored into this repository.
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# deja-browser
|
|
2
|
+
|
|
3
|
+
*The agent browser that remembers.* (Formerly edge-recipes.)
|
|
4
|
+
|
|
5
|
+
**A browser for your AI agent that is not your browser.** A separate Chromium profile your agent
|
|
6
|
+
drives over CDP — with no telemetry, no extension in your everyday browser, and site *recipes*
|
|
7
|
+
so the second visit to a site does not need to read the page at all.
|
|
8
|
+
|
|
9
|
+
Works with any agent that can run shell commands (Claude Code, Codex CLI, Gemini CLI, Cursor,
|
|
10
|
+
Aider, …) and from plain Python.
|
|
11
|
+
|
|
12
|
+
> **Let your agent install it.** Tell it: *"Read
|
|
13
|
+
> https://github.com/drpwchen/deja-browser/blob/main/AGENTS.md and set this up with me."* It will
|
|
14
|
+
> ask you the few choices that matter, have you log in to your sites by hand, and run a smoke test.
|
|
15
|
+
|
|
16
|
+
> **Status: early release (0.1).** Tested on Windows 11 (Edge), macOS on Apple Silicon (Chrome)
|
|
17
|
+
> and Linux (headless Chromium, in the egress test). Feedback and recipes-in-the-wild welcome.
|
|
18
|
+
|
|
19
|
+
## Why
|
|
20
|
+
|
|
21
|
+
Browser-extension bridges for agents put an extension with full debugger access into the browser
|
|
22
|
+
where you are logged in to everything, and some of them phone home with no way to turn it off.
|
|
23
|
+
Browsers have also stopped letting you fence such extensions away from chosen sites. deja-browser
|
|
24
|
+
takes the other route:
|
|
25
|
+
|
|
26
|
+
- **Separation instead of a block list.** The agent gets its own profile. You log in there only to
|
|
27
|
+
the sites it should use. Your mail, bank and broker are simply not logged in.
|
|
28
|
+
- **No telemetry, tested.** The tool makes no outbound connection of its own.
|
|
29
|
+
[`tests/egress/run.sh`](tests/egress/run.sh) runs every action and a full recipe cycle inside a
|
|
30
|
+
network namespace with only loopback, traces every `connect()` of the tool's processes, and
|
|
31
|
+
fails on anything that is not `127.0.0.1` (its `SELFTEST=1` mode proves the check catches a
|
|
32
|
+
deliberate connection). The only outbound features are ones you switch on: ntfy notifications
|
|
33
|
+
and the opt-in hCaptcha solver.
|
|
34
|
+
- **No passwords in the browser.** On launch the profile's password, card and address autofill is
|
|
35
|
+
turned off, and a password-manager extension installed in it triggers a warning. Secrets the
|
|
36
|
+
agent may use stay in your OS keyring or password-manager CLI and are only named in recipes.
|
|
37
|
+
- **Cheap to read.** Snapshots can be cut to one subtree, to interactive elements, or to lines
|
|
38
|
+
matching a word; screenshots and PDFs come back as file paths, never as inline images.
|
|
39
|
+
- **Learn once, replay.** The first visit finds the JSON endpoint or the form; the recipe replays
|
|
40
|
+
it later, outside the browser when cookies are enough.
|
|
41
|
+
|
|
42
|
+
## What it does
|
|
43
|
+
|
|
44
|
+
- **Dedicated browser profile.** Drives any Chromium browser (Edge, Chrome, Chromium, Brave —
|
|
45
|
+
auto-detected) over CDP on `127.0.0.1` only, with its own user-data dir. Your everyday browser
|
|
46
|
+
profile is never touched. Kimi-WebBridge-compatible action names and return shapes, so scripts
|
|
47
|
+
written for that bridge port over.
|
|
48
|
+
- **Named sessions.** Every task names a session; its tabs are tracked across processes and
|
|
49
|
+
`close_session` closes only those.
|
|
50
|
+
- **API discovery.** `network_capture` records the requests one action triggers (bodies to files,
|
|
51
|
+
credential headers redacted) — the raw material for a recipe.
|
|
52
|
+
- **Recipes with a tier ladder** (cheapest first, falls through on failure, records what worked):
|
|
53
|
+
- `http` — plain HTTP outside the browser, with cookies read live from the browser (never stored)
|
|
54
|
+
- `page` — `fetch()` inside a tab on the site (native cookies, Cloudflare clearance, CSRF)
|
|
55
|
+
- `script` — the recipe's own JavaScript in the page (DOM read / form fill)
|
|
56
|
+
- **Shape checks.** Every response is compared with the JSON shape recorded at verify time; a
|
|
57
|
+
mismatch is reported as *stale*, never returned as data.
|
|
58
|
+
- **Write guard.** Recipes with side effects (`"writes": true`) only run with `--allow-write`.
|
|
59
|
+
- **Secrets by name.** Recipes reference `{secret:NAME}`; values are resolved in-process and are
|
|
60
|
+
never printed or returned, and never typed into a refused host.
|
|
61
|
+
- **CAPTCHA gate.** Waits for Turnstile / Cloudflare to clear, then tries one trusted checkbox
|
|
62
|
+
click. Local solvers (reCAPTCHA audio via `faster-whisper`, text CAPTCHAs via `ddddocr`) run only
|
|
63
|
+
if you install those extras; the hCaptcha solver only if you enable it. Otherwise it notifies you.
|
|
64
|
+
- **Guard rails.** `navigate` and recipes refuse mail, account sign-in, banking, brokerage and
|
|
65
|
+
payment hosts (built-in list, extendable); recipes also refuse ticketing / rail-booking hosts by
|
|
66
|
+
default. These stop accidents, not attackers — see *Safety model*.
|
|
67
|
+
|
|
68
|
+
## Options at a glance
|
|
69
|
+
|
|
70
|
+
| | Options | Notes |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| OS | Windows, macOS, Linux | Linux tested headless only |
|
|
73
|
+
| Browser | Edge, Chrome, Chromium, Brave, any Chromium (`[browser] executable`) | no Firefox / Safari (no CDP) |
|
|
74
|
+
| Driver | `patchright` (extra `stealth`, used when installed), `playwright` | patchright passes more bot checks |
|
|
75
|
+
| Secrets | `keyring` (default), `command`, `env`, `python` | `command` runs 1Password `op`, Bitwarden `bw`, macOS `security`, `pass`, … |
|
|
76
|
+
| Notifications | ntfy URL, any command, stderr (default) | for "a human is needed" |
|
|
77
|
+
| CAPTCHA extras | `audio` (local), `ocr` (local), hCaptcha solver (cloud, opt-in) | none installed by default |
|
|
78
|
+
| Agents | anything with a shell; Agent Skills folder in `skills/deja-browser/` | Python API: `from deja_browser.browser import wb` |
|
|
79
|
+
|
|
80
|
+
## Safety model
|
|
81
|
+
|
|
82
|
+
What protects you is **separation**: the agent profile is never logged in to mail, banking or
|
|
83
|
+
brokerage, and stores no passwords. The refused-host list is a guard rail: it stops an agent from
|
|
84
|
+
navigating there by mistake and keeps stored secrets from being typed into those sites, but a page
|
|
85
|
+
script can still redirect the tab, and an agent with shell access can edit your config. Treat it
|
|
86
|
+
as a seat belt, not a lock.
|
|
87
|
+
|
|
88
|
+
Password managers: do not install their extension in the agent profile — while unlocked it can
|
|
89
|
+
fill any saved password for whatever is driving the page. To let the agent log in to a few
|
|
90
|
+
low-risk sites by itself, give it a dedicated vault through the password manager's CLI
|
|
91
|
+
(`[secrets] backend = "command"`, see `config.example.toml`). 1Password service accounts can be
|
|
92
|
+
limited to one vault; an unlocked Bitwarden CLI can read the whole vault.
|
|
93
|
+
|
|
94
|
+
Two things no tool can change: the browser vendor's own services (e.g. Safe Browsing / SmartScreen
|
|
95
|
+
URL checks) still apply to the agent profile, and whatever page content your agent reads goes to
|
|
96
|
+
its model provider. Keep sensitive pages (health records, personal data) out of agent sessions.
|
|
97
|
+
|
|
98
|
+
## Install
|
|
99
|
+
|
|
100
|
+
Requires Python ≥ 3.11 and a Chromium-based browser.
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
pip install "deja-browser[stealth,keyring]" # recommended: patchright driver + OS keyring secrets
|
|
104
|
+
pip install "deja-browser[audio,ocr]" # reCAPTCHA audio (faster-whisper), text CAPTCHAs (ddddocr)
|
|
105
|
+
pip install -e ".[dev]" # from a clone: core + pytest
|
|
106
|
+
python -m playwright install-deps # Linux only, if system libraries are missing
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`deja-browser` uses your installed browser; it does not need `playwright install`.
|
|
110
|
+
|
|
111
|
+
## Quick start
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
deja-cdp launch # start the dedicated browser; log in to sites by hand if needed
|
|
115
|
+
deja-cdp navigate '{"url": "https://example.com"}' --session demo
|
|
116
|
+
deja-cdp evaluate '{"code": "document.title"}' --session demo
|
|
117
|
+
deja-cdp close_session '{}' --session demo
|
|
118
|
+
|
|
119
|
+
deja-browser verify draft.json '{"q": "rust"}' # try every tier, print shape + preview
|
|
120
|
+
deja-browser save draft.json # only after a passing verify of this draft
|
|
121
|
+
deja-browser run hn.algolia.com/search '{"q": "rust"}'
|
|
122
|
+
deja-browser list
|
|
123
|
+
deja-browser gate https://example.com/login # open a URL, clear any challenge, report
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
From Python:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from deja_browser.browser import wb
|
|
130
|
+
wb("navigate", {"url": "https://example.com"}, session="task")
|
|
131
|
+
wb("snapshot", {"max_chars": 4000}, session="task")
|
|
132
|
+
wb("close_session", {}, session="task")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`deja-cdp --help` and `deja-browser --help` list every action and the full recipe format.
|
|
136
|
+
|
|
137
|
+
## Recipe format (abridged)
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"version": 1,
|
|
142
|
+
"name": "search",
|
|
143
|
+
"description": "Hacker News full-text search (example)",
|
|
144
|
+
"entry_url": "https://hn.algolia.com/",
|
|
145
|
+
"params": [{"name": "q", "required": true}],
|
|
146
|
+
"request": {"method": "GET", "url": "https://hn.algolia.com/api/v1/search?query={q}"},
|
|
147
|
+
"pick": {"path": "hits", "fields": ["title", "url"], "limit": 20},
|
|
148
|
+
"writes": false
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
No recipes ship with the package — you (or your agent) build them per site. Recipes are stored as `<recipes dir>/<host>/<name>.json` and addressed as `<host>/<name>`.
|
|
153
|
+
|
|
154
|
+
## Configuration
|
|
155
|
+
|
|
156
|
+
Optional. Copy `config.example.toml` to:
|
|
157
|
+
|
|
158
|
+
| OS | Path |
|
|
159
|
+
|---|---|
|
|
160
|
+
| Windows | `%APPDATA%\deja-browser\config.toml` |
|
|
161
|
+
| macOS | `~/Library/Application Support/deja-browser/config.toml` |
|
|
162
|
+
| Linux | `~/.config/deja-browser/config.toml` |
|
|
163
|
+
|
|
164
|
+
or point `DEJA_BROWSER_CONFIG` at a file. It covers the browser executable and profile, the
|
|
165
|
+
recipes directory, extra denied hosts, the secret backend (`keyring` / `env` / `python`), and
|
|
166
|
+
notifications (an ntfy URL or any command; default is stderr).
|
|
167
|
+
|
|
168
|
+
## hCaptcha solver (opt-in, cloud)
|
|
169
|
+
|
|
170
|
+
Off by default. When enabled, the CAPTCHA gate hands hCaptcha to
|
|
171
|
+
[hcaptcha-challenger](https://github.com/QIN2DIM/hcaptcha-challenger), which asks Google Gemini to
|
|
172
|
+
answer the challenge. **This sends the cropped challenge image to Google** under your own API key
|
|
173
|
+
(not the page, not cookies). hcaptcha-challenger is GPL-3.0 and is not bundled — install it
|
|
174
|
+
yourself:
|
|
175
|
+
|
|
176
|
+
```sh
|
|
177
|
+
pip install "hcaptcha-challenger @ git+https://github.com/QIN2DIM/hcaptcha-challenger@28ee79b"
|
|
178
|
+
keyring set deja-browser GEMINI_API_KEY # or your configured secret backend
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
```toml
|
|
182
|
+
[captcha]
|
|
183
|
+
hcaptcha_solver = "gemini"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Best effort: on the public demo the "drag the missing item into the grid" type passed 13/15, the
|
|
187
|
+
hexagon shape-matching type 1/5 (small samples). Failures fall through to the human step.
|
|
188
|
+
|
|
189
|
+
## Acceptable use
|
|
190
|
+
|
|
191
|
+
This is a personal automation tool for sites and accounts you are entitled to use. Respect each
|
|
192
|
+
site's terms of service and rate limits. Do not use it for ticket scalping, mass account
|
|
193
|
+
creation, credential stuffing, or to defeat protections on systems you do not own. Ticket and
|
|
194
|
+
rail-booking sites are refused by default: several jurisdictions criminalise automated ticket
|
|
195
|
+
purchase (e.g. Taiwan's Railway Act art. 65). `[recipes] allow_ticket_hosts` can lift that; we
|
|
196
|
+
recommend you don't, and the decision and its consequences are yours. The project
|
|
197
|
+
does not integrate paid CAPTCHA-solving services and will not.
|
|
198
|
+
|
|
199
|
+
## Tests
|
|
200
|
+
|
|
201
|
+
```sh
|
|
202
|
+
python -m pytest -q # pure functions; no browser, no network
|
|
203
|
+
sudo PY=$(which python) tests/egress/run.sh # Linux: no outbound connection (needs strace)
|
|
204
|
+
sudo PY=$(which python) SELFTEST=1 tests/egress/run.sh # must FAIL: proves the check catches one
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT — see `LICENSE`. Optional dependencies keep their own licenses; GPL-licensed packages are
|
|
210
|
+
never vendored into this repository.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "deja-browser"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "The agent browser that remembers: a separate Chromium profile your AI agent drives over CDP, with site recipes so the second visit skips reading the page."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
keywords = ["browser-automation", "cdp", "ai-agent", "claude-code", "playwright", "captcha"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 3 - Alpha",
|
|
13
|
+
"Environment :: Console",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"Operating System :: Microsoft :: Windows",
|
|
16
|
+
"Operating System :: MacOS",
|
|
17
|
+
"Operating System :: POSIX :: Linux",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Internet :: WWW/HTTP :: Browsers",
|
|
20
|
+
]
|
|
21
|
+
license = "MIT"
|
|
22
|
+
requires-python = ">=3.11"
|
|
23
|
+
dependencies = ["playwright>=1.45"]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Homepage = "https://github.com/drpwchen/deja-browser"
|
|
27
|
+
Changelog = "https://github.com/drpwchen/deja-browser/blob/main/CHANGELOG.md"
|
|
28
|
+
Issues = "https://github.com/drpwchen/deja-browser/issues"
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
stealth = ["patchright"] # default driver when installed (hides Runtime.enable)
|
|
32
|
+
keyring = ["keyring"] # default secret backend
|
|
33
|
+
audio = ["faster-whisper", "av<19"] # reCAPTCHA audio; faster-whisper 1.2.1 passes av.open(metadata_errors=), removed in av 19
|
|
34
|
+
ocr = ["ddddocr"] # text-image CAPTCHAs
|
|
35
|
+
# hCaptcha (GPL-3.0, optional, installed by the user). PyPI 0.19.0 fails the drag challenges;
|
|
36
|
+
# the tested build is git 28ee79b. Not installable from PyPI as an extra until upstream releases.
|
|
37
|
+
# pip install "hcaptcha-challenger @ git+https://github.com/QIN2DIM/hcaptcha-challenger@28ee79b"
|
|
38
|
+
dev = ["pytest"]
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
deja-browser = "deja_browser.recipe:main"
|
|
42
|
+
deja-cdp = "deja_browser.browser:main"
|
|
43
|
+
|
|
44
|
+
[tool.setuptools.packages.find]
|
|
45
|
+
where = ["src"]
|
|
46
|
+
|
|
47
|
+
[tool.pytest.ini_options]
|
|
48
|
+
testpaths = ["tests"]
|
|
49
|
+
pythonpath = ["src"]
|