@aluvia/sdk 1.1.0 → 1.4.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/README.md +410 -285
- package/dist/cjs/api/account.js +10 -74
- package/dist/cjs/api/apiUtils.js +80 -0
- package/dist/cjs/api/geos.js +2 -63
- package/dist/cjs/api/request.js +8 -2
- package/dist/cjs/bin/account.js +31 -0
- package/dist/cjs/bin/api-helpers.js +58 -0
- package/dist/cjs/bin/cli-adapter.js +16 -0
- package/dist/cjs/bin/cli.js +245 -0
- package/dist/cjs/bin/close.js +120 -0
- package/dist/cjs/bin/geos.js +10 -0
- package/dist/cjs/bin/mcp-helpers.js +57 -0
- package/dist/cjs/bin/mcp-server.js +220 -0
- package/dist/cjs/bin/mcp-tools.js +90 -0
- package/dist/cjs/bin/open.js +293 -0
- package/dist/cjs/bin/session.js +259 -0
- package/dist/cjs/client/AluviaClient.js +365 -189
- package/dist/cjs/client/BlockDetection.js +486 -0
- package/dist/cjs/client/ConfigManager.js +26 -23
- package/dist/cjs/client/PageLoadDetection.js +175 -0
- package/dist/cjs/client/ProxyServer.js +4 -2
- package/dist/cjs/client/logger.js +4 -0
- package/dist/cjs/client/rules.js +38 -49
- package/dist/cjs/connect.js +117 -0
- package/dist/cjs/errors.js +12 -1
- package/dist/cjs/index.js +5 -1
- package/dist/cjs/session/lock.js +186 -0
- package/dist/esm/api/account.js +2 -66
- package/dist/esm/api/apiUtils.js +71 -0
- package/dist/esm/api/geos.js +2 -63
- package/dist/esm/api/request.js +8 -2
- package/dist/esm/bin/account.js +28 -0
- package/dist/esm/bin/api-helpers.js +53 -0
- package/dist/esm/bin/cli-adapter.js +8 -0
- package/dist/esm/bin/cli.js +242 -0
- package/dist/esm/bin/close.js +117 -0
- package/dist/esm/bin/geos.js +7 -0
- package/dist/esm/bin/mcp-helpers.js +51 -0
- package/dist/esm/bin/mcp-server.js +185 -0
- package/dist/esm/bin/mcp-tools.js +78 -0
- package/dist/esm/bin/open.js +256 -0
- package/dist/esm/bin/session.js +252 -0
- package/dist/esm/client/AluviaClient.js +371 -195
- package/dist/esm/client/BlockDetection.js +482 -0
- package/dist/esm/client/ConfigManager.js +21 -18
- package/dist/esm/client/PageLoadDetection.js +171 -0
- package/dist/esm/client/ProxyServer.js +5 -3
- package/dist/esm/client/logger.js +4 -0
- package/dist/esm/client/rules.js +36 -49
- package/dist/esm/connect.js +81 -0
- package/dist/esm/errors.js +10 -0
- package/dist/esm/index.js +5 -3
- package/dist/esm/session/lock.js +142 -0
- package/dist/types/api/AluviaApi.d.ts +2 -7
- package/dist/types/api/account.d.ts +1 -16
- package/dist/types/api/apiUtils.d.ts +28 -0
- package/dist/types/api/geos.d.ts +1 -1
- package/dist/types/bin/account.d.ts +1 -0
- package/dist/types/bin/api-helpers.d.ts +20 -0
- package/dist/types/bin/cli-adapter.d.ts +8 -0
- package/dist/types/bin/cli.d.ts +2 -0
- package/dist/types/bin/close.d.ts +1 -0
- package/dist/types/bin/geos.d.ts +1 -0
- package/dist/types/bin/mcp-helpers.d.ts +28 -0
- package/dist/types/bin/mcp-server.d.ts +2 -0
- package/dist/types/bin/mcp-tools.d.ts +46 -0
- package/dist/types/bin/open.d.ts +21 -0
- package/dist/types/bin/session.d.ts +11 -0
- package/dist/types/client/AluviaClient.d.ts +51 -4
- package/dist/types/client/BlockDetection.d.ts +96 -0
- package/dist/types/client/ConfigManager.d.ts +6 -1
- package/dist/types/client/PageLoadDetection.d.ts +93 -0
- package/dist/types/client/logger.d.ts +2 -0
- package/dist/types/client/rules.d.ts +18 -0
- package/dist/types/client/types.d.ts +48 -47
- package/dist/types/connect.d.ts +18 -0
- package/dist/types/errors.d.ts +6 -0
- package/dist/types/index.d.ts +7 -5
- package/dist/types/session/lock.d.ts +43 -0
- package/package.json +21 -12
package/README.md
CHANGED
|
@@ -5,430 +5,507 @@
|
|
|
5
5
|
[](./LICENSE)
|
|
6
6
|
[](./package.json)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
**Stop getting blocked.** Aluvia routes your AI agent's web traffic through premium US mobile carrier IPs — the same IPs used by real people on their phones. Websites trust them, so your agent stops hitting 403s, CAPTCHAs, and rate limits.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
This SDK gives you everything you need:
|
|
11
11
|
|
|
12
|
-
**
|
|
13
|
-
|
|
14
|
-
**
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
- **CLI for browser automation** — launch headless Chromium sessions from the command line, with JSON output designed for AI agent frameworks
|
|
13
|
+
- **Automatic block detection and unblocking** — the SDK detects 403s, WAF challenges, and CAPTCHAs, then reroutes through Aluvia and reloads the page automatically
|
|
14
|
+
- **Smart routing** — proxy only the sites that block you; everything else goes direct to save cost and latency
|
|
15
|
+
- **Runtime rule updates** — add hostnames to proxy rules on the fly, no restarts or redeployments
|
|
16
|
+
- **Adapters for every tool** — Playwright, Puppeteer, Selenium, Axios, got, and Node's fetch
|
|
17
|
+
- **IP rotation and geo targeting** — rotate IPs or target specific US regions at runtime
|
|
18
|
+
- **REST API wrapper** — manage connections, check usage, and build custom tooling with `AluviaApi`
|
|
19
|
+
- **MCP server** — for Model Context Protocol (MCP) only, use the separate package: `npm install @aluvia/mcp` and run `npx aluvia-mcp`. See [mcp/README.md](mcp/README.md) and [MCP Server Guide](docs/mcp-server-guide.md).
|
|
17
20
|
|
|
18
21
|
---
|
|
19
22
|
|
|
20
|
-
##
|
|
21
|
-
|
|
22
|
-
The Aluvia client runs a local rules-based proxy server on your agent's host, handles authentication and connection management, and provides ready-to-use adapters for popular tools like Playwright, Puppeteer, and Axios.
|
|
23
|
-
|
|
24
|
-
Simply point your automation tool at the local proxy address (`127.0.0.1`) and the client handles the rest. For each request, the client checks the destination hostname against user-defined (or agent-defined) routing rules and decides whether to send it through Aluvia's mobile IPs or direct to the destination.
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
┌──────────────────┐ ┌──────────────────────────┐ ┌──────────────────────┐
|
|
28
|
-
│ │ │ │ │ │
|
|
29
|
-
│ Your Agent │─────▶ Aluvia Client ─────▶ gateway.aluvia.io │
|
|
30
|
-
│ │ │ 127.0.0.1:port │ │ (Mobile IPs) │
|
|
31
|
-
│ │ │ │ │ │
|
|
32
|
-
└──────────────────┘ │ Per-request routing: │ └──────────────────────┘
|
|
33
|
-
│ │
|
|
34
|
-
│ not-blocked.com ──────────────▶ Direct
|
|
35
|
-
│ blocked-site.com ─────────────▶ Via Aluvia
|
|
36
|
-
│ │
|
|
37
|
-
└──────────────────────────┘
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
**Benefits:**
|
|
23
|
+
## Table of contents
|
|
41
24
|
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
25
|
+
- [Quick start](#quick-start)
|
|
26
|
+
- [CLI reference](#cli-reference)
|
|
27
|
+
- [Connecting to a running browser](#connecting-to-a-running-browser)
|
|
28
|
+
- [Programmatic usage (AluviaClient)](#programmatic-usage)
|
|
29
|
+
- [Routing rules](#routing-rules)
|
|
30
|
+
- [Block detection and auto-unblocking](#block-detection-and-auto-unblocking)
|
|
31
|
+
- [Tool integration adapters](#tool-integration-adapters)
|
|
32
|
+
- [REST API (AluviaApi)](#rest-api)
|
|
33
|
+
- [Architecture](#architecture)
|
|
46
34
|
|
|
47
35
|
---
|
|
48
36
|
|
|
49
37
|
## Quick start
|
|
50
38
|
|
|
51
|
-
###
|
|
39
|
+
### 1. Get Aluvia API key
|
|
52
40
|
|
|
53
|
-
|
|
54
|
-
|
|
41
|
+
[Aluvia dashboard](https://dashboard.aluvia.io)
|
|
42
|
+
|
|
43
|
+
### 2. Install
|
|
55
44
|
|
|
56
|
-
|
|
45
|
+
```bash
|
|
46
|
+
npm install @aluvia/sdk playwright
|
|
47
|
+
export ALUVIA_API_KEY="your-api-key"
|
|
48
|
+
```
|
|
57
49
|
|
|
58
|
-
|
|
59
|
-
2. Go to **API and SDKs** and get your **API Key**
|
|
50
|
+
### 3. Run
|
|
60
51
|
|
|
61
|
-
|
|
52
|
+
Aluvia automatically detects website blocks and uses mobile IPs when necessary.
|
|
62
53
|
|
|
63
54
|
```bash
|
|
64
|
-
|
|
55
|
+
aluvia session start https://example.com --auto-unblock --run your-script.js
|
|
65
56
|
```
|
|
66
57
|
|
|
67
|
-
|
|
58
|
+
---
|
|
68
59
|
|
|
69
|
-
|
|
60
|
+
## Skills
|
|
70
61
|
|
|
71
|
-
|
|
62
|
+
- Claude code skill
|
|
63
|
+
- OpenClaw skill
|
|
72
64
|
|
|
73
|
-
|
|
74
|
-
import { chromium } from "playwright";
|
|
75
|
-
import { AluviaClient } from "@aluvia/sdk";
|
|
65
|
+
---
|
|
76
66
|
|
|
77
|
-
|
|
78
|
-
const client = new AluviaClient({ apiKey: process.env.ALUVIA_API_KEY! });
|
|
67
|
+
## CLI reference
|
|
79
68
|
|
|
80
|
-
|
|
81
|
-
const connection = await client.start();
|
|
69
|
+
The CLI outputs JSON for easy integration with AI agent frameworks. All commands are available via the `aluvia` binary. Run `aluvia help --json` for machine-readable help.
|
|
82
70
|
|
|
83
|
-
|
|
84
|
-
await client.updateTargetGeo("us_ca");
|
|
71
|
+
### `session start` — Launch a browser session
|
|
85
72
|
|
|
86
|
-
|
|
87
|
-
|
|
73
|
+
```bash
|
|
74
|
+
aluvia session start <url> [options]
|
|
75
|
+
```
|
|
88
76
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
77
|
+
| Option | Description |
|
|
78
|
+
| --------------------------- | ------------------------------------------------------------------------ |
|
|
79
|
+
| `--auto-unblock` | Auto-detect blocks and reload through Aluvia |
|
|
80
|
+
| `--run <script>` | Run a script with `page`, `browser`, `context` injected; exits when done |
|
|
81
|
+
| `--headful` | Show the browser window (default: headless) |
|
|
82
|
+
| `--browser-session <name>` | Name this session (auto-generated if omitted, e.g. `swift-falcon`) |
|
|
83
|
+
| `--connection-id <id>` | Reuse an existing Aluvia connection |
|
|
84
|
+
| `--disable-block-detection` | Disable block detection entirely |
|
|
92
85
|
|
|
93
|
-
|
|
94
|
-
const proxiedHosts = new Set<string>();
|
|
86
|
+
**Examples:**
|
|
95
87
|
|
|
96
|
-
|
|
97
|
-
|
|
88
|
+
```bash
|
|
89
|
+
# Launch with auto-unblocking
|
|
90
|
+
aluvia session start https://example.com --auto-unblock
|
|
98
91
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const hostname = new URL(url).hostname;
|
|
92
|
+
# Run a script inline
|
|
93
|
+
aluvia session start https://example.com --auto-unblock --run scrape.mjs
|
|
102
94
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const isBlocked =
|
|
106
|
-
status === 403 ||
|
|
107
|
-
status === 429 ||
|
|
108
|
-
(await page.title()).toLowerCase().includes("blocked");
|
|
95
|
+
# Debug with a visible browser window
|
|
96
|
+
aluvia session start https://example.com --headful
|
|
109
97
|
|
|
110
|
-
|
|
111
|
-
|
|
98
|
+
# Reuse an existing connection
|
|
99
|
+
aluvia session start https://example.com --connection-id 3449
|
|
100
|
+
```
|
|
112
101
|
|
|
113
|
-
|
|
114
|
-
// Rules update at runtime—no need to restart the browser
|
|
115
|
-
proxiedHosts.add(hostname);
|
|
116
|
-
await client.updateRules([...proxiedHosts]);
|
|
102
|
+
### `session close` — Stop a session
|
|
117
103
|
|
|
118
|
-
|
|
119
|
-
|
|
104
|
+
```bash
|
|
105
|
+
aluvia session close # auto-selects if only one is running
|
|
106
|
+
aluvia session close --browser-session swift-falcon # close by name
|
|
107
|
+
aluvia session close --all # close all sessions
|
|
108
|
+
```
|
|
120
109
|
|
|
121
|
-
|
|
122
|
-
return visitWithRetry(url);
|
|
123
|
-
}
|
|
110
|
+
### `session list` — List active sessions
|
|
124
111
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
}
|
|
112
|
+
```bash
|
|
113
|
+
aluvia session list
|
|
114
|
+
```
|
|
130
115
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"sessions": [
|
|
119
|
+
{
|
|
120
|
+
"browserSession": "swift-falcon",
|
|
121
|
+
"pid": 12345,
|
|
122
|
+
"startUrl": "https://example.com",
|
|
123
|
+
"cdpUrl": "http://127.0.0.1:38209",
|
|
124
|
+
"connectionId": 3449,
|
|
125
|
+
"blockDetection": true,
|
|
126
|
+
"autoUnblock": true
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
"count": 1
|
|
139
130
|
}
|
|
140
131
|
```
|
|
141
132
|
|
|
142
|
-
###
|
|
143
|
-
|
|
144
|
-
For even simpler setup, the SDK can automatically launch a Chromium browser that's already configured with the Aluvia proxy. This eliminates the need to manually import Playwright and configure proxy settings.
|
|
133
|
+
### `session get` — Full session details
|
|
145
134
|
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// Initialize with startPlaywright option to auto-launch browser
|
|
150
|
-
const client = new AluviaClient({
|
|
151
|
-
apiKey: process.env.ALUVIA_API_KEY!,
|
|
152
|
-
startPlaywright: true, // Automatically launch and configure Chromium
|
|
153
|
-
});
|
|
135
|
+
```bash
|
|
136
|
+
aluvia session get [--browser-session <name>]
|
|
137
|
+
```
|
|
154
138
|
|
|
155
|
-
|
|
156
|
-
const connection = await client.start();
|
|
139
|
+
Returns session info enriched with block detection history and the full connection object from the API.
|
|
157
140
|
|
|
158
|
-
|
|
159
|
-
const browser = connection.browser;
|
|
160
|
-
const page = await browser.newPage();
|
|
141
|
+
### `session rotate-ip` — Get a new IP
|
|
161
142
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
143
|
+
```bash
|
|
144
|
+
aluvia session rotate-ip [--browser-session <name>]
|
|
145
|
+
```
|
|
165
146
|
|
|
166
|
-
|
|
167
|
-
await page.goto("https://example.com");
|
|
168
|
-
console.log("Title:", await page.title());
|
|
147
|
+
### `session set-geo` — Target a specific region
|
|
169
148
|
|
|
170
|
-
|
|
171
|
-
|
|
149
|
+
```bash
|
|
150
|
+
aluvia session set-geo US # target US IPs
|
|
151
|
+
aluvia session set-geo us_ca # target California
|
|
152
|
+
aluvia session set-geo --clear # clear geo targeting
|
|
172
153
|
```
|
|
173
154
|
|
|
174
|
-
|
|
155
|
+
### `session set-rules` — Update routing rules
|
|
175
156
|
|
|
176
157
|
```bash
|
|
177
|
-
|
|
178
|
-
|
|
158
|
+
aluvia session set-rules "example.com,api.example.com" # add rules
|
|
159
|
+
aluvia session set-rules --remove "example.com" # remove rules
|
|
179
160
|
```
|
|
180
161
|
|
|
181
|
-
|
|
162
|
+
Rules are comma-separated. By default rules are appended; use `--remove` to remove specific rules.
|
|
182
163
|
|
|
183
|
-
|
|
164
|
+
### Account and other commands
|
|
184
165
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
-
|
|
189
|
-
|
|
190
|
-
|
|
166
|
+
```bash
|
|
167
|
+
aluvia account # account info
|
|
168
|
+
aluvia account usage # usage stats
|
|
169
|
+
aluvia account usage --start 2025-01-01T00:00:00Z --end 2025-02-01T00:00:00Z
|
|
170
|
+
|
|
171
|
+
aluvia geos # list available geo-targeting options
|
|
172
|
+
aluvia help # plain text help
|
|
173
|
+
aluvia help --json # machine-readable help
|
|
174
|
+
```
|
|
191
175
|
|
|
192
176
|
---
|
|
193
177
|
|
|
194
|
-
##
|
|
178
|
+
## Connecting to a running browser
|
|
195
179
|
|
|
196
|
-
|
|
180
|
+
There are two ways to run code against a browser session started by the CLI.
|
|
197
181
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
├─────────────────────────────┼───────────────────────────────────┤
|
|
205
|
-
│ • Fetches/creates config │ • Local HTTP proxy (proxy-chain) │
|
|
206
|
-
│ • Polls for updates (ETag) │ • Per-request routing decisions │
|
|
207
|
-
│ • PATCH updates (rules, │ • Uses rules engine to decide: │
|
|
208
|
-
│ session, geo) │ direct vs gateway │
|
|
209
|
-
└─────────────────────────────┴───────────────────────────────────┘
|
|
182
|
+
### Option A: `--run` (simplest)
|
|
183
|
+
|
|
184
|
+
Pass a script to `session start`. The globals `page`, `browser`, and `context` are available — no imports needed:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
aluvia session start https://example.com --auto-unblock --run script.mjs
|
|
210
188
|
```
|
|
211
189
|
|
|
212
|
-
|
|
190
|
+
```js
|
|
191
|
+
// script.mjs
|
|
192
|
+
console.log("URL:", page.url());
|
|
213
193
|
|
|
214
|
-
|
|
215
|
-
-
|
|
216
|
-
|
|
217
|
-
|
|
194
|
+
const newPage = await context.newPage();
|
|
195
|
+
await newPage.goto("https://another-site.com");
|
|
196
|
+
console.log("Other site title:", await newPage.title());
|
|
197
|
+
```
|
|
218
198
|
|
|
219
|
-
|
|
199
|
+
The session starts, runs your script, and exits.
|
|
220
200
|
|
|
221
|
-
|
|
222
|
-
- For each request, uses the **rules engine** to decide whether to route direct or via Aluvia.
|
|
223
|
-
- Because the proxy reads the latest config per-request, rule updates take effect immediately
|
|
201
|
+
### Option B: `connect()` (for AI agents and long-running processes)
|
|
224
202
|
|
|
225
|
-
|
|
203
|
+
Start a session as a background daemon, then connect from your application:
|
|
226
204
|
|
|
227
|
-
|
|
205
|
+
```bash
|
|
206
|
+
aluvia session start https://example.com --auto-unblock
|
|
207
|
+
```
|
|
228
208
|
|
|
229
|
-
|
|
209
|
+
```ts
|
|
210
|
+
import { connect } from "@aluvia/sdk";
|
|
230
211
|
|
|
231
|
-
|
|
212
|
+
// Auto-discovers the running session
|
|
213
|
+
const { page, browser, context, disconnect } = await connect();
|
|
214
|
+
console.log("URL:", page.url());
|
|
232
215
|
|
|
233
|
-
|
|
216
|
+
// When running multiple sessions, specify by name
|
|
217
|
+
const conn = await connect("swift-falcon");
|
|
218
|
+
console.log("URL:", conn.page.url());
|
|
234
219
|
|
|
235
|
-
|
|
220
|
+
// Disconnect when done (the session keeps running)
|
|
221
|
+
await disconnect();
|
|
222
|
+
```
|
|
236
223
|
|
|
237
|
-
|
|
238
|
-
- Credentials stay inside the SDK (nothing secret in your config)
|
|
239
|
-
- Rule changes apply immediately (no restarts)
|
|
224
|
+
Use this when your agent generates automation code dynamically at runtime or needs a persistent browser across multiple operations.
|
|
240
225
|
|
|
241
|
-
|
|
226
|
+
---
|
|
242
227
|
|
|
243
|
-
|
|
228
|
+
## Programmatic usage
|
|
244
229
|
|
|
245
|
-
|
|
230
|
+
For full control, use `AluviaClient` directly instead of the CLI.
|
|
246
231
|
|
|
247
|
-
|
|
232
|
+
### Basic example
|
|
248
233
|
|
|
249
|
-
|
|
234
|
+
```ts
|
|
235
|
+
import { AluviaClient } from "@aluvia/sdk";
|
|
236
|
+
import { chromium } from "playwright";
|
|
250
237
|
|
|
251
|
-
|
|
252
|
-
|
|
238
|
+
const client = new AluviaClient({
|
|
239
|
+
apiKey: process.env.ALUVIA_API_KEY!,
|
|
240
|
+
});
|
|
253
241
|
|
|
254
|
-
|
|
242
|
+
const connection = await client.start();
|
|
243
|
+
const browser = await chromium.launch({ proxy: connection.asPlaywright() });
|
|
244
|
+
const page = await browser.newPage();
|
|
245
|
+
await page.goto("https://example.com");
|
|
255
246
|
|
|
256
|
-
|
|
247
|
+
// ... do your work ...
|
|
257
248
|
|
|
258
|
-
|
|
249
|
+
await browser.close();
|
|
250
|
+
await connection.close();
|
|
251
|
+
```
|
|
259
252
|
|
|
260
|
-
###
|
|
253
|
+
### With auto-launched browser
|
|
261
254
|
|
|
262
255
|
```ts
|
|
263
256
|
const client = new AluviaClient({
|
|
264
257
|
apiKey: process.env.ALUVIA_API_KEY!,
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
258
|
+
startPlaywright: true,
|
|
259
|
+
blockDetection: {
|
|
260
|
+
enabled: true,
|
|
261
|
+
autoUnblock: true,
|
|
262
|
+
},
|
|
268
263
|
});
|
|
264
|
+
|
|
265
|
+
const connection = await client.start();
|
|
266
|
+
const page = await connection.browser.newPage();
|
|
267
|
+
await page.goto("https://example.com"); // auto-reloads through Aluvia if blocked
|
|
268
|
+
|
|
269
|
+
await connection.close(); // stops proxy, closes browser, releases resources
|
|
269
270
|
```
|
|
270
271
|
|
|
271
|
-
|
|
272
|
+
### Runtime updates
|
|
272
273
|
|
|
273
|
-
|
|
274
|
+
While your agent is running, update routing, rotate IPs, or change geo — no restarts needed:
|
|
274
275
|
|
|
275
276
|
```ts
|
|
276
|
-
|
|
277
|
+
await client.updateRules(["blocked-site.com"]); // proxy this hostname
|
|
278
|
+
await client.updateSessionId("new-session-id"); // rotate to a new IP
|
|
279
|
+
await client.updateTargetGeo("us_ca"); // target California IPs
|
|
277
280
|
```
|
|
278
281
|
|
|
279
|
-
|
|
280
|
-
[Understanding the connection object](https://docs.aluvia.io/fundamentals/connections)
|
|
281
|
-
|
|
282
|
-
### 3. Use the connection with your tools
|
|
283
|
-
|
|
284
|
-
Pass the connection to your automation tool using the appropriate adapter:
|
|
282
|
+
### Constructor options
|
|
285
283
|
|
|
286
284
|
```ts
|
|
287
|
-
|
|
285
|
+
new AluviaClient({
|
|
286
|
+
apiKey: string; // Required
|
|
287
|
+
connectionId?: number; // Reuse an existing connection
|
|
288
|
+
startPlaywright?: boolean; // Auto-launch Chromium browser
|
|
289
|
+
headless?: boolean; // Default: true (only with startPlaywright)
|
|
290
|
+
blockDetection?: BlockDetectionConfig; // See "Block detection" section
|
|
291
|
+
localPort?: number; // Local proxy port (auto-assigned if omitted)
|
|
292
|
+
gatewayProtocol?: "http" | "https"; // Default: "http"
|
|
293
|
+
gatewayPort?: number; // Default: 8080 (http) or 8443 (https)
|
|
294
|
+
pollIntervalMs?: number; // Config poll interval (default: 5000ms)
|
|
295
|
+
timeoutMs?: number; // API request timeout
|
|
296
|
+
logLevel?: "silent" | "info" | "debug";
|
|
297
|
+
strict?: boolean; // Throw if config fails to load (default: true)
|
|
298
|
+
apiBaseUrl?: string; // Default: "https://api.aluvia.io/v1"
|
|
299
|
+
});
|
|
288
300
|
```
|
|
289
301
|
|
|
290
|
-
|
|
302
|
+
For all options in detail, see the [Client Technical Guide](docs/client-technical-guide.md#constructor-options).
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Routing rules
|
|
307
|
+
|
|
308
|
+
The local proxy routes each request based on hostname rules. Only hostnames matching a rule go through Aluvia; everything else goes direct.
|
|
309
|
+
|
|
310
|
+
### Why this matters
|
|
311
|
+
|
|
312
|
+
- **Save money** — proxy only the sites that block you
|
|
313
|
+
- **Lower latency** — non-blocked sites skip the proxy entirely
|
|
314
|
+
- **Adapt on the fly** — rules update at runtime, no restarts needed
|
|
315
|
+
|
|
316
|
+
### Rule patterns
|
|
317
|
+
|
|
318
|
+
| Pattern | Matches |
|
|
319
|
+
| --------------- | ------------------------------ |
|
|
320
|
+
| `*` | All hostnames |
|
|
321
|
+
| `example.com` | Exact match |
|
|
322
|
+
| `*.example.com` | Subdomains of example.com |
|
|
323
|
+
| `google.*` | google.com, google.co.uk, etc. |
|
|
324
|
+
| `-example.com` | Exclude from proxying |
|
|
291
325
|
|
|
292
|
-
|
|
326
|
+
### Examples
|
|
293
327
|
|
|
294
328
|
```ts
|
|
295
|
-
|
|
296
|
-
await client.
|
|
297
|
-
|
|
329
|
+
// Proxy all traffic
|
|
330
|
+
await client.updateRules(["*"]);
|
|
331
|
+
|
|
332
|
+
// Proxy specific hosts only
|
|
333
|
+
await client.updateRules(["target-site.com", "*.google.com"]);
|
|
334
|
+
|
|
335
|
+
// Proxy everything except Stripe
|
|
336
|
+
await client.updateRules(["*", "-api.stripe.com"]);
|
|
337
|
+
|
|
338
|
+
// Route all traffic direct (no proxy)
|
|
339
|
+
await client.updateRules([]);
|
|
298
340
|
```
|
|
299
341
|
|
|
300
|
-
|
|
342
|
+
Or from the CLI:
|
|
301
343
|
|
|
302
|
-
```
|
|
303
|
-
|
|
344
|
+
```bash
|
|
345
|
+
aluvia session set-rules "target-site.com,*.google.com"
|
|
346
|
+
aluvia session set-rules --remove "target-site.com"
|
|
304
347
|
```
|
|
305
348
|
|
|
306
349
|
---
|
|
307
350
|
|
|
308
|
-
##
|
|
351
|
+
## Block detection and auto-unblocking
|
|
309
352
|
|
|
310
|
-
|
|
353
|
+
Most proxy solutions require you to decide upfront which sites to proxy. If a site blocks you later, you're stuck.
|
|
311
354
|
|
|
312
|
-
|
|
355
|
+
Aluvia detects blocks automatically and can unblock your agent on the fly. The SDK analyzes every page load using a weighted scoring system across multiple signals — HTTP status codes, WAF headers, CAPTCHA selectors, page content, redirect chains, and more.
|
|
313
356
|
|
|
314
|
-
|
|
315
|
-
- through Aluvia's mobile proxy IPs,
|
|
357
|
+
### Automatic unblocking (recommended)
|
|
316
358
|
|
|
317
|
-
|
|
359
|
+
When a block is detected, the SDK adds the hostname to proxy rules and reloads the page through Aluvia:
|
|
318
360
|
|
|
319
|
-
|
|
320
|
-
|
|
361
|
+
```ts
|
|
362
|
+
const client = new AluviaClient({
|
|
363
|
+
apiKey: process.env.ALUVIA_API_KEY!,
|
|
364
|
+
startPlaywright: true,
|
|
365
|
+
blockDetection: {
|
|
366
|
+
enabled: true,
|
|
367
|
+
autoUnblock: true,
|
|
368
|
+
onDetection: (result, page) => {
|
|
369
|
+
console.log(
|
|
370
|
+
`${result.blockStatus} on ${result.hostname} (score: ${result.score})`,
|
|
371
|
+
);
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Or from the CLI:
|
|
321
378
|
|
|
322
|
-
|
|
379
|
+
```bash
|
|
380
|
+
aluvia session start https://example.com --auto-unblock
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Detection-only mode
|
|
384
|
+
|
|
385
|
+
Run detection without automatic remediation. Your agent inspects the results and decides what to do:
|
|
323
386
|
|
|
324
387
|
```ts
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
388
|
+
blockDetection: {
|
|
389
|
+
enabled: true,
|
|
390
|
+
onDetection: (result, page) => {
|
|
391
|
+
if (result.blockStatus === "blocked") {
|
|
392
|
+
// Agent decides: retry, rotate IP, update rules, etc.
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
}
|
|
329
396
|
```
|
|
330
397
|
|
|
331
|
-
###
|
|
398
|
+
### Block status scores
|
|
332
399
|
|
|
333
|
-
|
|
334
|
-
| --------------- | ------------------------------------- |
|
|
335
|
-
| `*` | All hostnames |
|
|
336
|
-
| `example.com` | Exact match |
|
|
337
|
-
| `*.example.com` | Subdomains of example.com |
|
|
338
|
-
| `google.*` | google.com, google.co.uk, and similar |
|
|
339
|
-
| `-example.com` | Exclude from proxying |
|
|
400
|
+
Each page analysis produces a score from 0.0 to 1.0:
|
|
340
401
|
|
|
341
|
-
|
|
402
|
+
| Score | Status | Meaning |
|
|
403
|
+
| ------ | ------------- | --------------------------------------------------------------- |
|
|
404
|
+
| >= 0.7 | `"blocked"` | High confidence block. Auto-reloads when `autoUnblock: true`. |
|
|
405
|
+
| >= 0.4 | `"suspected"` | Possible block. Reloads only if `autoUnblockOnSuspected: true`. |
|
|
406
|
+
| < 0.4 | `"clear"` | No block detected. |
|
|
407
|
+
|
|
408
|
+
Scores use probabilistic combination (`1 - product(1 - weight)`) so weak signals don't stack into false positives.
|
|
409
|
+
|
|
410
|
+
### How detection works
|
|
342
411
|
|
|
343
|
-
|
|
412
|
+
Detection runs in two passes:
|
|
344
413
|
|
|
345
|
-
|
|
414
|
+
1. **Fast pass** (at `domcontentloaded`) — checks HTTP status codes and WAF response headers. High-confidence blocks (score >= 0.9) trigger immediate remediation.
|
|
415
|
+
2. **Full pass** (after `networkidle`) — analyzes page title, visible text, challenge selectors, meta refreshes, and redirect chains.
|
|
346
416
|
|
|
347
|
-
|
|
417
|
+
The SDK also detects SPA navigations and tracks persistent blocks per hostname to prevent infinite retry loops.
|
|
348
418
|
|
|
349
|
-
|
|
419
|
+
### Detection config options
|
|
420
|
+
|
|
421
|
+
```ts
|
|
422
|
+
blockDetection: {
|
|
423
|
+
enabled?: boolean; // Default: true
|
|
424
|
+
autoUnblock?: boolean; // Auto-remediate blocked pages
|
|
425
|
+
autoUnblockOnSuspected?: boolean; // Also remediate "suspected" pages
|
|
426
|
+
challengeSelectors?: string[]; // Custom CSS selectors for challenge detection
|
|
427
|
+
extraKeywords?: string[]; // Additional keywords for text analysis
|
|
428
|
+
extraStatusCodes?: number[]; // Additional HTTP status codes to flag
|
|
429
|
+
networkIdleTimeoutMs?: number; // Default: 3000ms
|
|
430
|
+
onDetection?: (result, page) => void | Promise<void>;
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Manual detection
|
|
435
|
+
|
|
436
|
+
You can also check responses yourself and update rules on the fly:
|
|
350
437
|
|
|
351
438
|
```ts
|
|
352
439
|
const response = await page.goto(url);
|
|
353
440
|
|
|
354
441
|
if (response?.status() === 403) {
|
|
355
|
-
// Blocked! Add this hostname to proxy rules and retry
|
|
356
442
|
await client.updateRules([...currentRules, new URL(url).hostname]);
|
|
357
|
-
await page.goto(url); //
|
|
443
|
+
await page.goto(url); // retried through Aluvia
|
|
358
444
|
}
|
|
359
445
|
```
|
|
360
446
|
|
|
361
|
-
|
|
447
|
+
For the full list of signal detectors and weights, see the [Client Technical Guide](docs/client-technical-guide.md#signal-detectors).
|
|
362
448
|
|
|
363
449
|
---
|
|
364
450
|
|
|
365
451
|
## Tool integration adapters
|
|
366
452
|
|
|
367
|
-
|
|
453
|
+
The SDK handles proxy configuration for every major tool:
|
|
454
|
+
|
|
455
|
+
| Tool | Method | Returns |
|
|
456
|
+
| ------------ | ---------------------------- | ----------------------------------------------------- |
|
|
457
|
+
| Playwright | `connection.asPlaywright()` | `{ server, username?, password? }` |
|
|
458
|
+
| Playwright | `connection.browser` | Auto-launched Chromium (with `startPlaywright: true`) |
|
|
459
|
+
| Playwright | `connection.cdpUrl` | CDP endpoint for `connectOverCDP()` |
|
|
460
|
+
| Puppeteer | `connection.asPuppeteer()` | `['--proxy-server=...']` |
|
|
461
|
+
| Selenium | `connection.asSelenium()` | `'--proxy-server=...'` |
|
|
462
|
+
| Axios | `connection.asAxiosConfig()` | `{ proxy: false, httpAgent, httpsAgent }` |
|
|
463
|
+
| got | `connection.asGotOptions()` | `{ agent: { http, https } }` |
|
|
464
|
+
| fetch | `connection.asUndiciFetch()` | Proxy-enabled `fetch` function |
|
|
465
|
+
| Node.js http | `connection.asNodeAgents()` | `{ http: Agent, https: Agent }` |
|
|
466
|
+
|
|
467
|
+
### Examples
|
|
368
468
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
| Axios | `connection.asAxiosConfig()` | `{ proxy: false, httpAgent, httpsAgent }` |
|
|
376
|
-
| got | `connection.asGotOptions()` | `{ agent: { http, https } }` |
|
|
377
|
-
| fetch | `connection.asUndiciFetch()` | Proxy-enabled `fetch` function |
|
|
378
|
-
| Node.js http | `connection.asNodeAgents()` | `{ http: Agent, https: Agent }` |
|
|
469
|
+
```ts
|
|
470
|
+
// Playwright
|
|
471
|
+
const browser = await chromium.launch({ proxy: connection.asPlaywright() });
|
|
472
|
+
|
|
473
|
+
// Puppeteer
|
|
474
|
+
const browser = await puppeteer.launch({ args: connection.asPuppeteer() });
|
|
379
475
|
|
|
380
|
-
|
|
476
|
+
// Axios
|
|
477
|
+
const axiosClient = axios.create(connection.asAxiosConfig());
|
|
478
|
+
await axiosClient.get("https://example.com");
|
|
479
|
+
|
|
480
|
+
// got
|
|
481
|
+
const gotClient = got.extend(connection.asGotOptions());
|
|
482
|
+
await gotClient("https://example.com");
|
|
483
|
+
|
|
484
|
+
// Node's fetch (via undici)
|
|
485
|
+
const myFetch = connection.asUndiciFetch();
|
|
486
|
+
await myFetch("https://example.com");
|
|
487
|
+
```
|
|
381
488
|
|
|
382
|
-
For more details
|
|
489
|
+
For more details, see the [Client Technical Guide](docs/client-technical-guide.md#tool-adapters).
|
|
383
490
|
|
|
384
491
|
---
|
|
385
492
|
|
|
386
|
-
##
|
|
387
|
-
|
|
388
|
-
`AluviaApi` is a typed wrapper for the Aluvia REST API. Use it to manage connections,
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
403
|
-
│ │ │ │ │
|
|
404
|
-
│ ▼ ▼ ▼ │
|
|
405
|
-
│ ┌────────────────────────────────────────────────────┐ │
|
|
406
|
-
│ │ requestAndUnwrap / ctx.request │ │
|
|
407
|
-
│ │ (envelope unwrapping, error throwing) │ │
|
|
408
|
-
│ └────────────────────────────────────────────────────┘ │
|
|
409
|
-
│ │ │
|
|
410
|
-
│ ▼ │
|
|
411
|
-
│ ┌────────────────────────────────────────────────────┐ │
|
|
412
|
-
│ │ requestCore │ │
|
|
413
|
-
│ │ (URL building, headers, timeout, JSON parsing) │ │
|
|
414
|
-
│ └────────────────────────────────────────────────────┘ │
|
|
415
|
-
│ │ │
|
|
416
|
-
│ ▼ │
|
|
417
|
-
│ globalThis.fetch │
|
|
418
|
-
└───────────────────────────────────────────────────────────────┘
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
### What you can do
|
|
422
|
-
|
|
423
|
-
| Endpoint | Description |
|
|
424
|
-
| ------------------------------------ | --------------------------------------- |
|
|
425
|
-
| `api.account.get()` | Get account info (balance, usage) |
|
|
426
|
-
| `api.account.connections.list()` | List all connections |
|
|
427
|
-
| `api.account.connections.create()` | Create a new connection |
|
|
428
|
-
| `api.account.connections.get(id)` | Get connection details |
|
|
429
|
-
| `api.account.connections.patch(id)` | Update connection (rules, geo, session) |
|
|
430
|
-
| `api.account.connections.delete(id)` | Delete a connection |
|
|
431
|
-
| `api.geos.list()` | List available geo-targeting options |
|
|
493
|
+
## REST API
|
|
494
|
+
|
|
495
|
+
`AluviaApi` is a typed wrapper for the Aluvia REST API. Use it to manage connections, check account info, or build custom tooling — without starting a proxy.
|
|
496
|
+
|
|
497
|
+
### Endpoints
|
|
498
|
+
|
|
499
|
+
| Method | Description |
|
|
500
|
+
| ----------------------------------------- | --------------------------------------- |
|
|
501
|
+
| `api.account.get()` | Get account info (balance, usage) |
|
|
502
|
+
| `api.account.connections.list()` | List all connections |
|
|
503
|
+
| `api.account.connections.create(body)` | Create a new connection |
|
|
504
|
+
| `api.account.connections.get(id)` | Get connection details |
|
|
505
|
+
| `api.account.connections.patch(id, body)` | Update connection (rules, geo, session) |
|
|
506
|
+
| `api.account.connections.delete(id)` | Delete a connection |
|
|
507
|
+
| `api.account.usage.get(params?)` | Get usage stats |
|
|
508
|
+
| `api.geos.list()` | List available geo-targeting options |
|
|
432
509
|
|
|
433
510
|
### Example
|
|
434
511
|
|
|
@@ -442,12 +519,12 @@ const account = await api.account.get();
|
|
|
442
519
|
console.log("Balance:", account.balance_gb, "GB");
|
|
443
520
|
|
|
444
521
|
// Create a connection for a new agent
|
|
445
|
-
const
|
|
522
|
+
const conn = await api.account.connections.create({
|
|
446
523
|
description: "pricing-scraper",
|
|
447
524
|
rules: ["competitor-site.com"],
|
|
448
525
|
target_geo: "us_ca",
|
|
449
526
|
});
|
|
450
|
-
console.log("Created:",
|
|
527
|
+
console.log("Created connection:", conn.connection_id);
|
|
451
528
|
|
|
452
529
|
// List available geos
|
|
453
530
|
const geos = await api.geos.list();
|
|
@@ -457,12 +534,60 @@ console.log(
|
|
|
457
534
|
);
|
|
458
535
|
```
|
|
459
536
|
|
|
460
|
-
|
|
537
|
+
`AluviaApi` is also available as `client.api` when using `AluviaClient`.
|
|
461
538
|
|
|
462
|
-
For the complete API reference, see [API Technical Guide](docs/api-technical-guide.md).
|
|
539
|
+
For the complete API reference, see the [API Technical Guide](docs/api-technical-guide.md).
|
|
463
540
|
|
|
464
541
|
---
|
|
465
542
|
|
|
543
|
+
## Architecture
|
|
544
|
+
|
|
545
|
+
The client is split into two independent planes:
|
|
546
|
+
|
|
547
|
+
```
|
|
548
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
549
|
+
│ AluviaClient │
|
|
550
|
+
├─────────────────────────────┬───────────────────────────────────┤
|
|
551
|
+
│ Control Plane │ Data Plane │
|
|
552
|
+
│ (ConfigManager) │ (ProxyServer) │
|
|
553
|
+
├─────────────────────────────┼───────────────────────────────────┤
|
|
554
|
+
│ • Fetches/creates config │ • Local HTTP proxy (proxy-chain) │
|
|
555
|
+
│ • Polls for updates (ETag) │ • Per-request routing decisions │
|
|
556
|
+
│ • PATCH updates (rules, │ • Uses rules engine to decide: │
|
|
557
|
+
│ session, geo) │ direct vs gateway │
|
|
558
|
+
└─────────────────────────────┴───────────────────────────────────┘
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
**Control Plane (ConfigManager)** — communicates with the Aluvia REST API to fetch proxy credentials and routing rules, polls for configuration updates using ETags, and pushes updates (rules, session ID, geo).
|
|
562
|
+
|
|
563
|
+
**Data Plane (ProxyServer)** — runs a local HTTP proxy on `127.0.0.1` that reads the latest config per-request, so rule updates take effect immediately without restarts.
|
|
564
|
+
|
|
565
|
+
```
|
|
566
|
+
┌──────────────────┐ ┌──────────────────────────┐ ┌──────────────────────┐
|
|
567
|
+
│ │ │ │ │ │
|
|
568
|
+
│ Your Agent │─────▶│ Aluvia Client │─────▶│ gateway.aluvia.io │
|
|
569
|
+
│ │ │ 127.0.0.1:port │ │ (Mobile IPs) │
|
|
570
|
+
│ │ │ │ │ │
|
|
571
|
+
└──────────────────┘ │ Per-request routing: │ └──────────────────────┘
|
|
572
|
+
│ │
|
|
573
|
+
│ not-blocked.com ──────────────▶ Direct
|
|
574
|
+
│ blocked-site.com ─────────────▶ Via Aluvia
|
|
575
|
+
│ │
|
|
576
|
+
└──────────────────────────┘
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
## Learn more
|
|
582
|
+
|
|
583
|
+
- [What is Aluvia?](https://docs.aluvia.io/)
|
|
584
|
+
- [Understanding connections](https://docs.aluvia.io/fundamentals/connections)
|
|
585
|
+
- [Playwright integration guide](https://docs.aluvia.io/integrations/integration-playwright)
|
|
586
|
+
- [Puppeteer](https://docs.aluvia.io/integrations/integration-puppeteer), [Selenium](https://docs.aluvia.io/integrations/integration-selenium), [Axios](https://docs.aluvia.io/integrations/integration-axios), [got](https://docs.aluvia.io/integrations/integration-got), [fetch](https://docs.aluvia.io/integrations/integration-fetch)
|
|
587
|
+
- [CLI Technical Guide](docs/cli-technical-guide.md)
|
|
588
|
+
- [Client Technical Guide](docs/client-technical-guide.md)
|
|
589
|
+
- [API Technical Guide](docs/api-technical-guide.md)
|
|
590
|
+
|
|
466
591
|
## License
|
|
467
592
|
|
|
468
593
|
MIT — see [LICENSE](./LICENSE)
|