Skip to content

Commit 890b599

Browse files
authored
Merge pull request #16 from browser-use/feat/v4-api-support
Add Browser Use Cloud API v4 support, CI, and tests
2 parents 308e4d0 + 6662a72 commit 890b599

15 files changed

Lines changed: 3709 additions & 212 deletions

.eslintrc.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,23 @@ module.exports = {
2828
'n8n-nodes-base/node-class-description-inputs-wrong-regular-node': 'off',
2929
'n8n-nodes-base/node-class-description-outputs-wrong': 'off',
3030
},
31+
overrides: [
32+
{
33+
// Plain CommonJS tests that drive the compiled output; they are deliberately
34+
// outside tsconfig.json, so the type-aware parser must not run on them.
35+
files: ['test/**/*.js'],
36+
parserOptions: {
37+
project: null,
38+
sourceType: 'script',
39+
ecmaVersion: 2022,
40+
},
41+
rules: {
42+
// The package is CommonJS, so require() is the correct import style here.
43+
'@typescript-eslint/no-require-imports': 'off',
44+
'@typescript-eslint/no-var-requires': 'off',
45+
},
46+
},
47+
],
3148
ignorePatterns: [
3249
'.eslintrc.js',
3350
'dist/**',

.github/workflows/ci.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
9+
# A new push supersedes in-flight runs for the same ref.
10+
concurrency:
11+
group: ci-${{ github.ref }}
12+
cancel-in-progress: true
13+
14+
permissions:
15+
contents: read
16+
17+
jobs:
18+
verify:
19+
name: Verify (Node ${{ matrix.node-version }})
20+
runs-on: ubuntu-latest
21+
22+
strategy:
23+
fail-fast: false
24+
matrix:
25+
# Floor from package.json engines, plus the version the publish
26+
# workflow releases from.
27+
node-version: ['22.22', '24']
28+
29+
steps:
30+
- uses: actions/checkout@v4
31+
32+
# Must precede setup-node so the pnpm store path can be resolved for caching.
33+
- uses: pnpm/action-setup@v4
34+
35+
- uses: actions/setup-node@v4
36+
with:
37+
node-version: ${{ matrix.node-version }}
38+
cache: pnpm
39+
40+
- name: Install dependencies
41+
run: pnpm install --frozen-lockfile
42+
43+
- name: Check formatting
44+
run: pnpm format:check
45+
46+
- name: Lint
47+
run: pnpm lint
48+
49+
- name: Build
50+
run: pnpm build
51+
52+
# Runs against dist/, so it must follow the build step.
53+
- name: Test
54+
run: pnpm test

.github/workflows/publish.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,34 @@ jobs:
2121
- uses: actions/setup-node@v4
2222
with:
2323
node-version: 24
24+
cache: pnpm
25+
26+
- name: Verify tag matches package.json version
27+
if: startsWith(github.ref, 'refs/tags/v')
28+
run: |
29+
TAG_VERSION="${GITHUB_REF_NAME#v}"
30+
PKG_VERSION="$(node -p "require('./package.json').version")"
31+
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
32+
echo "::error::Tag $GITHUB_REF_NAME does not match package.json version $PKG_VERSION"
33+
exit 1
34+
fi
35+
echo "Publishing version $PKG_VERSION"
2436
2537
- name: Install dependencies
2638
run: pnpm install --frozen-lockfile
2739

40+
- name: Check formatting
41+
run: pnpm format:check
42+
2843
- name: Lint
2944
run: pnpm lint
3045

3146
- name: Build
3247
run: pnpm build
3348

49+
- name: Test
50+
run: pnpm test
51+
3452
- name: Publish
3553
run: |
3654
unset NODE_AUTH_TOKEN

CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,34 @@
11
# Changelog
22

3+
## 1.2.0
4+
5+
### Added
6+
7+
- Added **V4 Runs, Sessions, and Browsers** to the **API Version** dropdown on the **Browser Use** node.
8+
- Added v4 **Run** operations: run and wait, create, get, get status, get many, cancel, get events, and get attachments.
9+
- Added v4 **Session** operations for conversational follow-ups: queue message (with interrupt), get queue, cancel queued message, get, get many, and purge.
10+
- Added v4 **Browser** operations: create, get, get many, stop, and get downloads.
11+
- Added v4 run options for model selection, provider-native model parameters, session continuation, workspaces and attached files, judge settings, max cost, and per-run browser settings.
12+
- Added client-side structured output for v4: the JSON Schema is appended to the task and the result is parsed into `parsedResult`, with `structuredOutputError` describing any mismatch.
13+
14+
### Changed
15+
16+
- Newly added **Browser Use** nodes now default to **v4**, which Browser Use recommends for new integrations. The node gained a second `typeVersion` to do this safely: nodes already on the canvas stay at typeVersion 1 and keep defaulting to v2, while nodes added from now on are typeVersion 2 and default to v4. Changing the default in place would have migrated saved nodes silently, because n8n resolves a missing parameter to its property default and omits default-valued parameters when saving.
17+
- Labelled **V2 Tasks** as legacy in the **API Version** dropdown.
18+
- Structured output on v4 now accepts JSON Schema union types such as `["string", "null"]`, checks `required` even when the schema omits `type`, and validates the task length after the starting URL and schema are appended rather than before.
19+
- Credential testing and the v2 and v3 request paths now also normalise a Base URL saved as `/api/v4`.
20+
- Moved the shared structured-output templates and the base URL version helper into modules shared by all three API versions, replacing three copies of the same code.
21+
22+
- Raised the minimum Node version from 20.19 to 22.22, matching n8n's own requirement. The development toolchain cannot install on Node 20 at all: `isolated-vm`, a transitive dependency of `n8n-workflow`, fails to compile against Node 20's V8 headers. Node 20 is also past end of life.
23+
- Added CI running formatting, lint, build, and tests on every pull request and push to main, across Node 22.22 and 24. The repository previously had no CI; lint and build only ran during a tagged publish.
24+
- Added a test suite covering all three API versions, run with Node's built-in test runner via `pnpm test` and added to `prepublishOnly`. It drives the compiled node against a stubbed HTTP layer, so no API key or network access is needed.
25+
- Hardened the publish workflow: a `v*` tag whose version does not match `package.json` now fails before publishing, formatting is checked alongside lint and build, and the pnpm store is cached.
26+
27+
### Compatibility
28+
29+
- Existing v2 and v3 workflows are unaffected; their request bodies and endpoints are unchanged, and existing nodes keep their current API version rather than moving to v4.
30+
- API v4 is not available on Zero Data Retention projects. Those workflows should stay on the v3 API Version; the node returns an explanatory error if v4 is used.
31+
332
## 1.1.2
433

534
### Changed

README.md

Lines changed: 160 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# n8n-nodes-browser-use
22

3-
An n8n community node package for Browser Use Cloud. The single **Browser Use** node supports both API v2 task workflows and API v3 session-based agent workflows.
3+
An n8n community node package for Browser Use Cloud. The single **Browser Use** node supports API v4 run workflows, API v3 session-based agent workflows, and the legacy API v2 task workflows.
44

55
<p>
66
<img src="https://raw.githubusercontent.com/browser-use/browser-use/main/static/browser-use.png" alt="Browser Use" width="360">
@@ -12,7 +12,9 @@ Browser Use Cloud lets AI agents control managed browsers for web research, data
1212

1313
This package includes one n8n node:
1414

15-
- **Browser Use**: choose **API Version** in the node UI to use v2 Tasks or v3 Sessions and Browsers
15+
- **Browser Use**: choose **API Version** in the node UI to use v4 Runs, v3 Sessions and Browsers, or v2 Tasks
16+
17+
New nodes default to **v4**, which Browser Use recommends for new integrations. Existing workflows keep whichever API version they were saved with.
1618

1719
## Installation
1820

@@ -43,10 +45,70 @@ The default Base URL remains:
4345
https://api.browser-use.com/api/v2
4446
```
4547

46-
Leave the credential Base URL at the default. In the **Browser Use** node, use the **API Version** dropdown to switch between **v2 Tasks** and **v3 Sessions and Browsers**. The node switches the API path internally, so existing credentials continue to work. The node authenticates with the `X-Browser-Use-API-Key` header.
48+
Leave the credential Base URL at the default. In the **Browser Use** node, use the **API Version** dropdown to switch between **v4 Runs**, **v3 Sessions and Browsers**, and **v2 Tasks**. The node rewrites the trailing `/api/vN` segment internally, so existing credentials continue to work. The node authenticates with the `X-Browser-Use-API-Key` header.
49+
50+
## Choosing an API version
51+
52+
| Version | Use it for | Notes |
53+
| --- | --- | --- |
54+
| **v4** (default) | New integrations, hard or long multi-step workflows | Highest accuracy. Not available on Zero Data Retention projects. |
55+
| **v3** | Cost- and speed-sensitive work | Session-based agents plus standalone cloud browsers. |
56+
| **v2** | Existing workflows only | Legacy; no longer actively maintained upstream. |
4757

4858
## Nodes
4959

60+
### API Version: v4 Runs, Sessions, and Browsers
61+
62+
In v4 the unit of work is a **run**. Every run belongs to a **session**, and a session is a conversation: follow-up messages queued onto a session reuse its context and browser state.
63+
64+
#### Run
65+
66+
Operations:
67+
68+
- **Run and Wait**: Dispatch a run, poll `GET /runs/{id}/status` until it reaches `completed`, `failed`, or `cancelled`, then return the full run summary
69+
- **Create**: Dispatch a run and return immediately with its ID, status, session ID, and events URL
70+
- **Get**: Retrieve the full run summary including `result`, `error`, token counts, and `totalCostUsd`
71+
- **Get Status**: Retrieve only the status, which is the cheapest way to poll from your own loop
72+
- **Get Many**: List runs, optionally filtered to a single session
73+
- **Cancel**: Cancel a run that is still in flight
74+
- **Get Events**: Retrieve the step-by-step event stream for a run
75+
- **Get Attachments**: List files the agent attached to a run
76+
77+
Run options:
78+
79+
- **Model**: `gpt-5.6-luna` (default), the rest of the GPT-5.5/5.6 family, Claude Opus 4.7/4.8/5, Claude Sonnet 5, Claude Fable 5, Gemini 3/3.1/3.5/3.6, GLM 5.2, Grok 4.5, Kimi K3, or MiniMax M3
80+
- **Model Parameters**: Provider-native parameters forwarded unchanged, e.g. `{"reasoning": {"effort": "high"}}`
81+
- **Session ID**: Continue an existing conversation instead of starting a new one
82+
- **Workspace ID** and **Attached File IDs**: Persist and attach files across runs
83+
- **Judge** and **Judge Context**: Have an LLM judge the finished run; the verdict lands in `judgement`
84+
- **Max Cost USD**: Cap the total spend of a run
85+
- **Profile ID**, **Proxy Country Code**, **Disable Proxy**, **Custom Proxy**, **Screen Width/Height**, **Enable Recording**: Browser settings applied when a new browser is provisioned
86+
87+
#### Session
88+
89+
Operations:
90+
91+
- **Queue Message**: Send a follow-up instruction; it runs immediately when the session is idle, or waits its turn. **Interrupt** cancels the active run so the message takes effect now
92+
- **Get Queue** / **Cancel Queued Message**: Inspect and manage pending messages
93+
- **Get** / **Get Many**: Session metadata, one entry per conversation
94+
- **Purge**: Permanently delete a session on a Zero Data Retention project
95+
96+
#### Browser
97+
98+
Standalone cloud browsers, the same computer-use style as v3, plus:
99+
100+
- **Get Downloads**: List files the browser downloaded, with optional presigned URLs
101+
102+
#### Structured output on v4
103+
104+
API v4 has **no server-side output schema**`run.result` is always a string. When **Extract Structured Data** is enabled, this node appends the JSON Schema to the task as an instruction and parses the returned text into a `parsedResult` field. This is best-effort:
105+
106+
- The raw text always stays in `result`
107+
- If the text is not JSON, or does not match the schema's type or required properties, `parsedResult` is `null` or partial and `structuredOutputError` explains what happened
108+
- The run itself is never failed by a parsing problem
109+
110+
Use **v3** if you need the API to enforce the schema server-side.
111+
50112
### API Version: v2 Tasks
51113

52114
The v2 mode remains available for backward compatibility. It uses the v2 `/tasks` API and keeps the same operations:
@@ -100,6 +162,95 @@ Operations:
100162

101163
Browser options include profile ID, proxy country code, timeout, screen size, resizing, custom proxy, and recording.
102164

165+
## Browser Use v4 Examples
166+
167+
### Run an agent task and wait
168+
169+
```json
170+
{
171+
"apiVersion": "v4",
172+
"resource": "run",
173+
"operation": "runAndWait",
174+
"task": "Find the top 3 trending repositories on GitHub today and summarize why they are trending",
175+
"waitTimeout": 900,
176+
"runOptions": {
177+
"model": "gpt-5.6-luna",
178+
"maxCostUsd": 1.5
179+
}
180+
}
181+
```
182+
183+
The response is the full run summary: `status`, `result`, `error`, `sessionId`, `totalInputTokens`, `totalOutputTokens`, `totalCostUsd`, plus the `eventsUrl` returned when the run was created.
184+
185+
### Continue the same conversation
186+
187+
Pass the `sessionId` from the previous run to start a follow-up run with the same context and browser state.
188+
189+
```json
190+
{
191+
"apiVersion": "v4",
192+
"resource": "run",
193+
"operation": "runAndWait",
194+
"task": "Open the first repository and extract its license and star count",
195+
"runOptions": {
196+
"sessionId": "SESSION_ID"
197+
}
198+
}
199+
```
200+
201+
To send a follow-up while a run may still be active, queue it on the session instead:
202+
203+
```json
204+
{
205+
"apiVersion": "v4",
206+
"resource": "session",
207+
"operation": "queueMessage",
208+
"sessionId": "SESSION_ID",
209+
"message": "Actually, sort by stars gained this week instead",
210+
"queueOptions": {
211+
"interrupt": true
212+
}
213+
}
214+
```
215+
216+
### Request structured output
217+
218+
```json
219+
{
220+
"apiVersion": "v4",
221+
"resource": "run",
222+
"operation": "runAndWait",
223+
"task": "Extract company details from this website",
224+
"startUrl": "https://example.com/about",
225+
"enableStructuredOutput": true,
226+
"schemaTemplate": "custom",
227+
"outputSchema": {
228+
"type": "object",
229+
"properties": {
230+
"companyName": { "type": "string" },
231+
"industry": { "type": "string" },
232+
"summary": { "type": "string" }
233+
},
234+
"required": ["companyName"]
235+
}
236+
}
237+
```
238+
239+
The parsed object arrives as `parsedResult`; the agent's raw text stays in `result`.
240+
241+
### Poll a run from your own loop
242+
243+
```json
244+
{
245+
"apiVersion": "v4",
246+
"resource": "run",
247+
"operation": "getStatus",
248+
"runId": "RUN_ID"
249+
}
250+
```
251+
252+
`Get Status` returns only `{ id, status }`, so it is cheap to call on a schedule. Fetch the full summary with `Get` once the status is terminal.
253+
103254
## Browser Use v3 Examples
104255

105256
### Run an agent task and wait
@@ -180,8 +331,14 @@ The response includes:
180331

181332
The node returns clear n8n errors for authentication failures, validation errors, missing resources, rate limits, and Browser Use API server errors. With n8n's "Continue On Fail" enabled, the error message is returned as item JSON.
182333

334+
On v4 two statuses carry extra context:
335+
336+
- **403**: the API key may lack project access, or the project has Zero Data Retention enabled, which v4 does not support — switch that workflow to the v3 API Version
337+
- **409**: a session runs one run at a time, so wait for the active run or cancel it first
338+
183339
## Documentation
184340

341+
- [Browser Use API v4 Reference](https://docs.browser-use.com/cloud/openapi/v4.json)
185342
- [Browser Use API v3 Reference](https://docs.browser-use.com/cloud/api-reference)
186343
- [Browser Use API v2 Reference](https://docs.browser-use.com/cloud/api-v2-overview)
187344
- [Browser Use Dashboard](https://cloud.browser-use.com)

credentials/BrowserUseApi.credentials.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export class BrowserUseApi implements ICredentialType {
2525
type: 'string',
2626
default: 'https://api.browser-use.com/api/v2',
2727
description:
28-
'The base URL for the Browser Use API. Leave this as the default; the node switches between v2 and v3 based on the API Version field.',
28+
'The base URL for the Browser Use API. Leave this as the default; the node switches between v2, v3, and v4 based on the API Version field.',
2929
required: true,
3030
},
3131
];
@@ -42,7 +42,7 @@ export class BrowserUseApi implements ICredentialType {
4242
test: ICredentialTestRequest = {
4343
request: {
4444
baseURL:
45-
'={{$credentials.baseUrl.replace(/\\/api\\/v3\\/?$/, "/api/v2").replace(/\\/$/, "")}}',
45+
'={{$credentials.baseUrl.replace(/\\/api\\/v[34]\\/?$/, "/api/v2").replace(/\\/$/, "")}}',
4646
url: '/tasks',
4747
method: 'GET',
4848
},

nodes/BrowserUse/ApiVersion.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* eslint-disable n8n-nodes-base/node-filename-against-convention -- Shared helper module, not an n8n node file. */
2+
3+
export type BrowserUseApiVersion = 'v2' | 'v3' | 'v4';
4+
5+
/**
6+
* Credentials hold a single Base URL (default `/api/v2`), while each node mode talks to its
7+
* own API version. Rewrite a trailing `/api/vN` to the requested version and leave any other
8+
* base URL untouched so custom gateways keep working.
9+
*/
10+
export function getVersionedBaseUrl(baseUrl: string, version: BrowserUseApiVersion): string {
11+
return baseUrl.replace(/\/api\/v[234]\/?$/, `/api/${version}`);
12+
}

0 commit comments

Comments
 (0)