@askjo/camoufox-browser 1.0.0

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.
package/.env.bak ADDED
@@ -0,0 +1,4 @@
1
+ PROXY_HOST=166.88.179.132
2
+ PROXY_PORT=46040
3
+ PROXY_USERNAME=NleQYPIiORIbOYT
4
+ PROXY_PASSWORD=936asYRvpdftjI6
@@ -0,0 +1,21 @@
1
+ name: Deploy to Fly.io
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ - main
8
+
9
+ jobs:
10
+ deploy:
11
+ name: Deploy to Fly.io
12
+ runs-on: ubuntu-latest
13
+ concurrency: deploy-group
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - uses: superfly/flyctl-actions/setup-flyctl@master
18
+
19
+ - run: flyctl deploy --remote-only
20
+ env:
21
+ FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
package/AGENTS.md ADDED
@@ -0,0 +1,153 @@
1
+ # camoufox-browser Agent Guide
2
+
3
+ Headless browser automation server for AI agents. Run locally or deploy to any cloud provider.
4
+
5
+ ## Quick Start for Agents
6
+
7
+ ```bash
8
+ # Install and start
9
+ npm install && npm start
10
+ # Server runs on http://localhost:3000
11
+ ```
12
+
13
+ ## Core Workflow
14
+
15
+ 1. **Create a tab** → Get `tabId`
16
+ 2. **Navigate** → Go to URL or use search macro
17
+ 3. **Get snapshot** → Receive page content with element refs (`e1`, `e2`, etc.)
18
+ 4. **Interact** → Click/type using refs
19
+ 5. **Repeat** steps 3-4 as needed
20
+
21
+ ## API Reference
22
+
23
+ ### Create Tab
24
+ ```bash
25
+ POST /tabs
26
+ {"userId": "agent1", "listItemId": "task1", "url": "https://example.com"}
27
+ ```
28
+ Returns: `{"tabId": "abc123", "url": "...", "title": "..."}`
29
+
30
+ ### Navigate
31
+ ```bash
32
+ POST /tabs/:tabId/navigate
33
+ {"userId": "agent1", "url": "https://google.com"}
34
+ # Or use macro:
35
+ {"userId": "agent1", "macro": "@google_search", "query": "weather today"}
36
+ ```
37
+
38
+ ### Get Snapshot
39
+ ```bash
40
+ GET /tabs/:tabId/snapshot?userId=agent1
41
+ ```
42
+ Returns accessibility tree with refs:
43
+ ```
44
+ [heading] Example Domain
45
+ [paragraph] This domain is for use in examples.
46
+ [link e1] More information...
47
+ ```
48
+
49
+ ### Click Element
50
+ ```bash
51
+ POST /tabs/:tabId/click
52
+ {"userId": "agent1", "ref": "e1"}
53
+ # Or CSS selector:
54
+ {"userId": "agent1", "selector": "button.submit"}
55
+ ```
56
+
57
+ ### Type Text
58
+ ```bash
59
+ POST /tabs/:tabId/type
60
+ {"userId": "agent1", "ref": "e2", "text": "hello world"}
61
+ # Add enter: {"userId": "agent1", "ref": "e2", "text": "search query", "pressEnter": true}
62
+ ```
63
+
64
+ ### Scroll
65
+ ```bash
66
+ POST /tabs/:tabId/scroll
67
+ {"userId": "agent1", "direction": "down", "amount": 500}
68
+ ```
69
+
70
+ ### Navigation
71
+ ```bash
72
+ POST /tabs/:tabId/back {"userId": "agent1"}
73
+ POST /tabs/:tabId/forward {"userId": "agent1"}
74
+ POST /tabs/:tabId/refresh {"userId": "agent1"}
75
+ ```
76
+
77
+ ### Get Links
78
+ ```bash
79
+ GET /tabs/:tabId/links?userId=agent1&limit=50
80
+ ```
81
+
82
+ ### Close Tab
83
+ ```bash
84
+ DELETE /tabs/:tabId?userId=agent1
85
+ ```
86
+
87
+ ## Search Macros
88
+
89
+ Use these instead of constructing URLs:
90
+
91
+ | Macro | Site |
92
+ |-------|------|
93
+ | `@google_search` | Google |
94
+ | `@youtube_search` | YouTube |
95
+ | `@amazon_search` | Amazon |
96
+ | `@reddit_search` | Reddit |
97
+ | `@wikipedia_search` | Wikipedia |
98
+ | `@twitter_search` | Twitter/X |
99
+ | `@yelp_search` | Yelp |
100
+ | `@linkedin_search` | LinkedIn |
101
+
102
+ ## Element Refs
103
+
104
+ Refs like `e1`, `e2` are stable identifiers for page elements:
105
+
106
+ 1. Call `/snapshot` to get current refs
107
+ 2. Use ref in `/click` or `/type`
108
+ 3. Refs reset on navigation - get new snapshot after
109
+
110
+ ## Session Management
111
+
112
+ - `userId` isolates cookies/storage between users
113
+ - `listItemId` groups tabs by conversation/task
114
+ - Sessions timeout after 30 minutes of inactivity
115
+ - Delete all user data: `DELETE /sessions/:userId`
116
+
117
+ ## Running Engines
118
+
119
+ ### Camoufox (Default - Recommended)
120
+ ```bash
121
+ npm start
122
+ # Or: ./run-camoufox.sh
123
+ ```
124
+ Firefox-based with anti-detection. Bypasses Google captcha.
125
+
126
+ ### Chrome (Legacy)
127
+ ```bash
128
+ npm run start:chrome
129
+ # Or: ./run.sh
130
+ ```
131
+ Playwright + stealth plugin. May be blocked by Google.
132
+
133
+ ## Testing
134
+
135
+ ```bash
136
+ npm test # E2E tests
137
+ npm run test:live # Live Google tests
138
+ npm run test:debug # With server output
139
+ ```
140
+
141
+ ## Docker
142
+
143
+ ```bash
144
+ docker build -f Dockerfile.camoufox -t camoufox-browser .
145
+ docker run -p 3000:3000 camoufox-browser
146
+ ```
147
+
148
+ ## Key Files
149
+
150
+ - `server-camoufox.js` - Camoufox engine (default)
151
+ - `server.js` - Chrome engine (legacy)
152
+ - `Dockerfile.camoufox` - Production container
153
+ - `fly.toml` - Fly.io deployment config
@@ -0,0 +1,59 @@
1
+ FROM node:20-slim
2
+
3
+ # Pinned Camoufox version for reproducible builds
4
+ # Update these when upgrading Camoufox
5
+ ARG CAMOUFOX_VERSION=135.0.1
6
+ ARG CAMOUFOX_RELEASE=beta.24
7
+ ARG CAMOUFOX_URL=https://github.com/daijro/camoufox/releases/download/v${CAMOUFOX_VERSION}-${CAMOUFOX_RELEASE}/camoufox-${CAMOUFOX_VERSION}-${CAMOUFOX_RELEASE}-lin.x86_64.zip
8
+
9
+ # Install dependencies for Camoufox (Firefox-based)
10
+ RUN apt-get update && apt-get install -y \
11
+ # Firefox dependencies
12
+ libgtk-3-0 \
13
+ libdbus-glib-1-2 \
14
+ libxt6 \
15
+ libasound2 \
16
+ libx11-xcb1 \
17
+ libxcomposite1 \
18
+ libxcursor1 \
19
+ libxdamage1 \
20
+ libxfixes3 \
21
+ libxi6 \
22
+ libxrandr2 \
23
+ libxrender1 \
24
+ libxss1 \
25
+ libxtst6 \
26
+ # Fonts
27
+ fonts-liberation \
28
+ fonts-noto-color-emoji \
29
+ fontconfig \
30
+ # Utils
31
+ ca-certificates \
32
+ curl \
33
+ unzip \
34
+ && rm -rf /var/lib/apt/lists/*
35
+
36
+ # Pre-bake Camoufox browser binary into image
37
+ # This avoids downloading at runtime and pins the version
38
+ # Note: unzip returns exit code 1 for warnings (Unicode filenames), so we use || true and verify
39
+ RUN mkdir -p /root/.cache/camoufox \
40
+ && curl -L -o /tmp/camoufox.zip "${CAMOUFOX_URL}" \
41
+ && (unzip -q /tmp/camoufox.zip -d /root/.cache/camoufox || true) \
42
+ && rm /tmp/camoufox.zip \
43
+ && chmod -R 755 /root/.cache/camoufox \
44
+ && echo "{\"version\":\"${CAMOUFOX_VERSION}\",\"release\":\"${CAMOUFOX_RELEASE}\"}" > /root/.cache/camoufox/version.json \
45
+ && test -f /root/.cache/camoufox/camoufox-bin && echo "Camoufox installed successfully"
46
+
47
+ WORKDIR /app
48
+
49
+ COPY package.json ./
50
+ RUN npm install --production
51
+
52
+ COPY server-camoufox.js ./
53
+
54
+ ENV NODE_ENV=production
55
+ ENV PORT=3000
56
+
57
+ EXPOSE 3000
58
+
59
+ CMD ["node", "server-camoufox.js"]
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Jo, Inc
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.
package/README.md ADDED
@@ -0,0 +1,234 @@
1
+ # camoufox-browser
2
+
3
+ A headless browser automation server designed for AI agents. Powered by [Camoufox](https://camoufox.com) - a Firefox-based browser with C++ anti-detection that bypasses bot detection including Google captcha.
4
+
5
+ This is the same browser engine that powers [askjo.ai](https://askjo.ai)'s web scraping capabilities.
6
+
7
+ **Perfect for:** [OpenClaw](https://openclaw.ai), Claude Code, LangChain agents, AutoGPT, and any AI system that needs to browse the web.
8
+
9
+ ## Motivation
10
+
11
+ AI agents need to browse the web, but current solutions have significant limitations:
12
+
13
+ - **Playwright/Puppeteer + stealth plugins** get detected and blocked by Google, Cloudflare, and most anti-bot systems. JavaScript-level evasion isn't enough.
14
+ - **Headless Chrome** is trivially fingerprinted. Sites check for hundreds of browser characteristics that reveal automation.
15
+ - **API-based scrapers** (Browserless, ScrapingBee) work but cost money per request and add latency.
16
+ - **Raw HTTP requests** can't handle JavaScript-rendered content or complex interactions.
17
+
18
+ Camoufox solves this with **C++ level anti-detection** baked into the Firefox source code itself - not a plugin that can be detected, but fundamental changes to how the browser reports its fingerprint. This is the same approach used by commercial anti-detect browsers.
19
+
20
+ This project wraps Camoufox in a simple REST API optimized for AI agents: accessibility snapshots instead of bloated HTML, stable element refs for reliable clicking, and search macros for common sites.
21
+
22
+ ## Features
23
+
24
+ - **Anti-Detection** - Camoufox engine (Firefox-based) with C++ fingerprint spoofing, bypasses Google captcha
25
+ - **Element Refs** - Stable `e1`, `e2`, `e3` references for clicking/typing
26
+ - **Session Isolation** - Separate cookies/storage per user, tabs grouped by conversation
27
+ - **Search Macros** - 13 built-in URL macros (`@google_search`, `@youtube_search`, etc.)
28
+ - **Token-Efficient** - Accessibility snapshots instead of full HTML (90% smaller)
29
+ - **Docker Ready** - Production Dockerfile with pre-baked Camoufox binary
30
+
31
+ ## Quick Start
32
+
33
+ ### OpenClaw Plugin
34
+
35
+ Install as an OpenClaw plugin for agent tool access:
36
+
37
+ ```bash
38
+ openclaw plugins install @jo-inc/camoufox-browser
39
+ ```
40
+
41
+ Then start the server and configure:
42
+
43
+ ```yaml
44
+ # ~/.openclaw/openclaw.json
45
+ plugins:
46
+ entries:
47
+ camoufox-browser:
48
+ enabled: true
49
+ config:
50
+ url: "http://localhost:9377"
51
+ ```
52
+
53
+ The plugin provides these agent tools:
54
+ - `camoufox_create_tab` - Create a browser tab
55
+ - `camoufox_snapshot` - Get page snapshot with element refs
56
+ - `camoufox_click` - Click elements by ref
57
+ - `camoufox_type` - Type into elements
58
+ - `camoufox_navigate` - Navigate to URLs or use search macros
59
+ - `camoufox_scroll` - Scroll the page
60
+ - `camoufox_screenshot` - Take screenshots
61
+ - `camoufox_close_tab` - Close tabs
62
+ - `camoufox_list_tabs` - List open tabs
63
+
64
+ ### Standalone Server
65
+
66
+ ```bash
67
+ # Clone and install
68
+ git clone https://github.com/jo-inc/camoufox-browser
69
+ cd camoufox-browser
70
+ npm install
71
+
72
+ # Start server (downloads Camoufox browser on first run)
73
+ npm start # Default port 3000
74
+ ./run-camoufox.sh -p 3001 # Custom port
75
+
76
+ # Server runs on http://localhost:3000
77
+ ```
78
+
79
+ ## API Overview
80
+
81
+ ### Create a Tab
82
+ ```bash
83
+ curl -X POST http://localhost:3000/tabs \
84
+ -H "Content-Type: application/json" \
85
+ -d '{"userId": "user1", "listItemId": "conv1", "url": "https://example.com"}'
86
+ ```
87
+
88
+ ### Get Page Snapshot (with element refs)
89
+ ```bash
90
+ curl "http://localhost:3000/tabs/TAB_ID/snapshot?userId=user1"
91
+ ```
92
+
93
+ Response includes refs for interaction:
94
+ ```json
95
+ {
96
+ "snapshot": "[button e1] Submit [link e2] Learn more",
97
+ "refs": {
98
+ "e1": { "role": "button", "name": "Submit" },
99
+ "e2": { "role": "link", "name": "Learn more" }
100
+ },
101
+ "url": "https://example.com"
102
+ }
103
+ ```
104
+
105
+ ### Click an Element
106
+ ```bash
107
+ curl -X POST http://localhost:3000/tabs/TAB_ID/click \
108
+ -H "Content-Type: application/json" \
109
+ -d '{"userId": "user1", "ref": "e1"}'
110
+ ```
111
+
112
+ ### Search with Macros
113
+ ```bash
114
+ curl -X POST http://localhost:3000/tabs/TAB_ID/navigate \
115
+ -H "Content-Type: application/json" \
116
+ -d '{"userId": "user1", "macro": "@google_search", "query": "best coffee beans"}'
117
+ ```
118
+
119
+ ## All Endpoints
120
+
121
+ | Method | Path | Description |
122
+ |--------|------|-------------|
123
+ | GET | `/health` | Health check |
124
+ | GET | `/tabs?userId=X` | List all tab groups for user |
125
+ | POST | `/tabs` | Create new tab |
126
+ | DELETE | `/tabs/:tabId` | Close tab |
127
+ | POST | `/tabs/:tabId/navigate` | Navigate to URL or macro |
128
+ | GET | `/tabs/:tabId/snapshot` | Get accessibility snapshot with refs |
129
+ | POST | `/tabs/:tabId/click` | Click element by ref or selector |
130
+ | POST | `/tabs/:tabId/type` | Type into element |
131
+ | POST | `/tabs/:tabId/scroll` | Scroll page |
132
+ | POST | `/tabs/:tabId/back` | Go back |
133
+ | POST | `/tabs/:tabId/forward` | Go forward |
134
+ | POST | `/tabs/:tabId/refresh` | Refresh page |
135
+ | GET | `/tabs/:tabId/links` | Get all links |
136
+ | GET | `/tabs/:tabId/screenshot` | Get screenshot |
137
+ | DELETE | `/sessions/:userId` | Close all tabs for user |
138
+
139
+ ## Search Macros
140
+
141
+ Navigate supports these macros for common sites:
142
+
143
+ - `@google_search` - Google
144
+ - `@youtube_search` - YouTube
145
+ - `@amazon_search` - Amazon
146
+ - `@reddit_search` - Reddit
147
+ - `@wikipedia_search` - Wikipedia
148
+ - `@twitter_search` - Twitter/X
149
+ - `@yelp_search` - Yelp
150
+ - `@spotify_search` - Spotify
151
+ - `@netflix_search` - Netflix
152
+ - `@linkedin_search` - LinkedIn
153
+ - `@instagram_search` - Instagram
154
+ - `@tiktok_search` - TikTok
155
+ - `@twitch_search` - Twitch
156
+
157
+ ## Architecture
158
+
159
+ ```
160
+ Browser Instance
161
+ └── User Session (BrowserContext) - isolated cookies/storage
162
+ ├── Tab Group (listItemId: "conv1") - conversation A
163
+ │ ├── Tab (google.com)
164
+ │ └── Tab (github.com)
165
+ └── Tab Group (listItemId: "conv2") - conversation B
166
+ └── Tab (amazon.com)
167
+ ```
168
+
169
+ - One browser instance shared across users
170
+ - Separate BrowserContext per user (isolated cookies/storage)
171
+ - Tabs grouped by `listItemId` (conversation/task)
172
+ - 30-minute session timeout with automatic cleanup
173
+
174
+ ## Running Locally
175
+
176
+ ```bash
177
+ # Start with default port (3000)
178
+ ./run-camoufox.sh
179
+ # Or: npm start
180
+
181
+ # Start with custom port
182
+ ./run-camoufox.sh -p 3001
183
+ ```
184
+
185
+ First run downloads the Camoufox browser (~300MB).
186
+
187
+ ### Experimental
188
+
189
+ See [`experimental/`](experimental/) for alternative browser engines.
190
+
191
+ ## Docker Deployment
192
+
193
+ ```bash
194
+ # Build with Camoufox (recommended)
195
+ docker build -f Dockerfile.camoufox -t camoufox-browser .
196
+
197
+ # Run
198
+ docker run -p 3000:3000 camoufox-browser
199
+ ```
200
+
201
+ ## Fly.io Deployment
202
+
203
+ ```bash
204
+ fly launch --no-deploy
205
+ fly deploy
206
+ ```
207
+
208
+ ## Testing
209
+
210
+ ```bash
211
+ npm test # Run all e2e tests
212
+ npm run test:live # Run live Google tests (may hit captcha)
213
+ npm run test:debug # Show server output for debugging
214
+ ```
215
+
216
+ ## Environment Variables
217
+
218
+ | Variable | Description | Default |
219
+ |----------|-------------|---------|
220
+ | `PORT` | Server port | 3000 |
221
+ | `NODE_ENV` | Environment | development |
222
+
223
+ ## Contributing
224
+
225
+ Contributions are welcome! Please open an issue or submit a PR.
226
+
227
+ ## Credits
228
+
229
+ - [Camoufox](https://camoufox.com) - Firefox-based browser with C++ anti-detection
230
+ - [Amp](https://ampcode.com) - AI coding agent
231
+
232
+ ## License
233
+
234
+ MIT
package/SKILL.md ADDED
@@ -0,0 +1,165 @@
1
+ ---
2
+ name: camoufox-browser
3
+ description: Control a headless Camoufox browser with anti-detection. Browse websites, search Google/YouTube/Amazon, click elements, fill forms, and extract content.
4
+ globs:
5
+ requirements:
6
+ bins:
7
+ - node
8
+ - npm
9
+ ---
10
+
11
+ # camoufox-browser Skill
12
+
13
+ You can control a headless Camoufox browser running at `http://localhost:9377`. Camoufox is a Firefox-based browser with C++ anti-detection that bypasses bot detection including Google captcha.
14
+
15
+ This is the same browser engine that powers [askjo.ai](https://askjo.ai)'s web scraping.
16
+
17
+ ## Install as OpenClaw Plugin
18
+
19
+ ```bash
20
+ # Clone and install
21
+ git clone https://github.com/jo-inc/camoufox-browser ~/.openclaw/extensions/camoufox-browser
22
+ cd ~/.openclaw/extensions/camoufox-browser
23
+ npm install
24
+
25
+ # Start the server (port 9377)
26
+ ./run-camoufox.sh -p 9377 &
27
+
28
+ # Enable the plugin
29
+ openclaw plugins enable camoufox-browser
30
+ ```
31
+
32
+ Then add the tools to your agent allowlist:
33
+
34
+ ```bash
35
+ openclaw configure --section agents
36
+ # Add camoufox-browser to tools.allow
37
+ ```
38
+
39
+ ## Quick Start (Standalone)
40
+
41
+ ```bash
42
+ cd {baseDir}
43
+ npm install
44
+ npm start
45
+ ```
46
+
47
+ The server runs on port 3000 by default. Use `./run-camoufox.sh -p 9377` for custom port.
48
+
49
+ Check health: `curl http://localhost:9377/health`
50
+
51
+ ## How to Use
52
+
53
+ ### 1. Create a Tab
54
+
55
+ ```bash
56
+ curl -X POST http://localhost:9377/tabs \
57
+ -H "Content-Type: application/json" \
58
+ -d '{"userId": "openclaw", "listItemId": "task1", "url": "https://example.com"}'
59
+ ```
60
+
61
+ Save the `tabId` from the response for subsequent requests.
62
+
63
+ ### 2. Get Page Content
64
+
65
+ ```bash
66
+ curl "http://localhost:9377/tabs/TAB_ID/snapshot?userId=openclaw"
67
+ ```
68
+
69
+ This returns an accessibility snapshot with element refs like `e1`, `e2`, `e3`. These refs are stable identifiers you use to click or type into elements.
70
+
71
+ ### 3. Click Elements
72
+
73
+ Use the ref from the snapshot:
74
+
75
+ ```bash
76
+ curl -X POST http://localhost:9377/tabs/TAB_ID/click \
77
+ -H "Content-Type: application/json" \
78
+ -d '{"userId": "openclaw", "ref": "e1"}'
79
+ ```
80
+
81
+ ### 4. Type Text
82
+
83
+ ```bash
84
+ curl -X POST http://localhost:9377/tabs/TAB_ID/type \
85
+ -H "Content-Type: application/json" \
86
+ -d '{"userId": "openclaw", "ref": "e2", "text": "hello world", "pressEnter": true}'
87
+ ```
88
+
89
+ ### 5. Search with Macros
90
+
91
+ Instead of navigating to search URLs, use macros:
92
+
93
+ ```bash
94
+ curl -X POST http://localhost:9377/tabs/TAB_ID/navigate \
95
+ -H "Content-Type: application/json" \
96
+ -d '{"userId": "openclaw", "macro": "@google_search", "query": "weather in New York"}'
97
+ ```
98
+
99
+ Available macros:
100
+ - `@google_search` - Search Google
101
+ - `@youtube_search` - Search YouTube
102
+ - `@amazon_search` - Search Amazon
103
+ - `@reddit_search` - Search Reddit
104
+ - `@wikipedia_search` - Search Wikipedia
105
+ - `@twitter_search` - Search Twitter/X
106
+
107
+ ### 6. Scroll the Page
108
+
109
+ ```bash
110
+ curl -X POST http://localhost:9377/tabs/TAB_ID/scroll \
111
+ -H "Content-Type: application/json" \
112
+ -d '{"userId": "openclaw", "direction": "down", "amount": 500}'
113
+ ```
114
+
115
+ ### 7. Navigate Back/Forward
116
+
117
+ ```bash
118
+ curl -X POST http://localhost:9377/tabs/TAB_ID/back \
119
+ -H "Content-Type: application/json" \
120
+ -d '{"userId": "openclaw"}'
121
+ ```
122
+
123
+ ### 8. Get All Links
124
+
125
+ ```bash
126
+ curl "http://localhost:9377/tabs/TAB_ID/links?userId=openclaw&limit=50"
127
+ ```
128
+
129
+ ### 9. Close Tab When Done
130
+
131
+ ```bash
132
+ curl -X DELETE "http://localhost:9377/tabs/TAB_ID?userId=openclaw"
133
+ ```
134
+
135
+ ## Workflow Pattern
136
+
137
+ 1. Create tab with initial URL
138
+ 2. Get snapshot to see page content and element refs
139
+ 3. Click/type using refs from snapshot
140
+ 4. Get new snapshot after each navigation (refs reset)
141
+ 5. Repeat until task complete
142
+ 6. Close tab
143
+
144
+ ## Tips
145
+
146
+ - Always get a fresh snapshot after clicking links or submitting forms
147
+ - Use `pressEnter: true` when typing in search boxes
148
+ - Element refs (`e1`, `e2`) reset after navigation - always get new snapshot
149
+ - Use macros for searching instead of constructing URLs manually
150
+ - The browser has anti-detection so it works with Google, Amazon, etc.
151
+
152
+ ## All Endpoints
153
+
154
+ | Method | Path | Description |
155
+ |--------|------|-------------|
156
+ | POST | `/tabs` | Create tab |
157
+ | GET | `/tabs/:id/snapshot` | Get page content with refs |
158
+ | POST | `/tabs/:id/navigate` | Go to URL or macro |
159
+ | POST | `/tabs/:id/click` | Click element |
160
+ | POST | `/tabs/:id/type` | Type text |
161
+ | POST | `/tabs/:id/scroll` | Scroll page |
162
+ | POST | `/tabs/:id/back` | Go back |
163
+ | POST | `/tabs/:id/forward` | Go forward |
164
+ | GET | `/tabs/:id/links` | Get all links |
165
+ | DELETE | `/tabs/:id` | Close tab |
@@ -0,0 +1,35 @@
1
+ FROM debian:bookworm-slim
2
+
3
+ # Install Chromium and dependencies
4
+ RUN apt-get update && apt-get install -y \
5
+ chromium \
6
+ fonts-liberation \
7
+ fonts-noto-color-emoji \
8
+ libnss3 \
9
+ libatk-bridge2.0-0 \
10
+ libdrm2 \
11
+ libxkbcommon0 \
12
+ libgbm1 \
13
+ libasound2 \
14
+ libxshmfence1 \
15
+ && rm -rf /var/lib/apt/lists/*
16
+
17
+ # Install Node.js
18
+ RUN apt-get update && apt-get install -y \
19
+ nodejs \
20
+ npm \
21
+ && rm -rf /var/lib/apt/lists/*
22
+
23
+ WORKDIR /app
24
+
25
+ COPY package.json ./
26
+ RUN npm install --production
27
+
28
+ COPY server.js ./
29
+
30
+ ENV NODE_ENV=production
31
+ ENV PORT=3000
32
+
33
+ EXPOSE 3000
34
+
35
+ CMD ["node", "server.js"]