Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.6.0"
".": "0.7.0"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 26
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browser-use%2Fbrowser-use-9f5ca0cd0a64c620cebceaebf7c6f8c3a917aa6fbc2ea6b9d2a6e3b9d17aaea4.yml
openapi_spec_hash: 3d30ebd2ed6ab3a5b42b6b267a45d34f
config_hash: 9d52be5177b2ede4cb0633c04f4cc4ef
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browser-use%2Fbrowser-use-ce018db4d6891d645cfb220c86d17ac1d431e1ba2f604e8015876b17a5a11149.yml
openapi_spec_hash: e9a00924682ab214ca5d8b6b5c84430e
config_hash: dd3e22b635fa0eb9a7c741a8aaca2a7f
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## 0.7.0 (2025-08-19)

Full Changelog: [v0.6.0...v0.7.0](https://github.com/browser-use/browser-use-node/compare/v0.6.0...v0.7.0)

### Features

* **api:** manual updates ([d339b83](https://github.com/browser-use/browser-use-node/commit/d339b83355a358c7a55fa501576403cb30e0aa31))
* **api:** manual updates ([5d09807](https://github.com/browser-use/browser-use-node/commit/5d09807eb2cb8fa30555775d0a5cb21b2c7f3c7f))

## 0.6.0 (2025-08-19)

Full Changelog: [v0.5.1...v0.6.0](https://github.com/browser-use/browser-use-node/compare/v0.5.1...v0.6.0)
Expand Down
47 changes: 29 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ const client = new BrowserUse({
apiKey: process.env['BROWSER_USE_API_KEY'], // This is the default and can be omitted
});

const me = await client.users.me.retrieve();
const task = await client.tasks.create({
task: 'Search for the top 10 Hacker News posts and return the title and url.',
});

console.log(me.additionalCreditsBalanceUsd);
console.log(task.id);
```

### Request & Response types
Expand All @@ -43,7 +45,10 @@ const client = new BrowserUse({
apiKey: process.env['BROWSER_USE_API_KEY'], // This is the default and can be omitted
});

const me: BrowserUse.Users.MeRetrieveResponse = await client.users.me.retrieve();
const params: BrowserUse.TaskCreateParams = {
task: 'Search for the top 10 Hacker News posts and return the title and url.',
};
const task: BrowserUse.TaskCreateResponse = await client.tasks.create(params);
```

Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors.
Expand All @@ -56,15 +61,17 @@ a subclass of `APIError` will be thrown:

<!-- prettier-ignore -->
```ts
const me = await client.users.me.retrieve().catch(async (err) => {
if (err instanceof BrowserUse.APIError) {
console.log(err.status); // 400
console.log(err.name); // BadRequestError
console.log(err.headers); // {server: 'nginx', ...}
} else {
throw err;
}
});
const task = await client.tasks
.create({ task: 'Search for the top 10 Hacker News posts and return the title and url.' })
.catch(async (err) => {
if (err instanceof BrowserUse.APIError) {
console.log(err.status); // 400
console.log(err.name); // BadRequestError
console.log(err.headers); // {server: 'nginx', ...}
} else {
throw err;
}
});
```

Error codes are as follows:
Expand Down Expand Up @@ -96,7 +103,7 @@ const client = new BrowserUse({
});

// Or, configure per-request:
await client.users.me.retrieve({
await client.tasks.create({ task: 'Search for the top 10 Hacker News posts and return the title and url.' }, {
maxRetries: 5,
});
```
Expand All @@ -113,7 +120,7 @@ const client = new BrowserUse({
});

// Override per-request:
await client.users.me.retrieve({
await client.tasks.create({ task: 'Search for the top 10 Hacker News posts and return the title and url.' }, {
timeout: 5 * 1000,
});
```
Expand All @@ -136,13 +143,17 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse
```ts
const client = new BrowserUse();

const response = await client.users.me.retrieve().asResponse();
const response = await client.tasks
.create({ task: 'Search for the top 10 Hacker News posts and return the title and url.' })
.asResponse();
console.log(response.headers.get('X-My-Header'));
console.log(response.statusText); // access the underlying Response object

const { data: me, response: raw } = await client.users.me.retrieve().withResponse();
const { data: task, response: raw } = await client.tasks
.create({ task: 'Search for the top 10 Hacker News posts and return the title and url.' })
.withResponse();
console.log(raw.headers.get('X-My-Header'));
console.log(me.additionalCreditsBalanceUsd);
console.log(task.id);
```

### Logging
Expand Down Expand Up @@ -222,7 +233,7 @@ parameter. This library doesn't validate at runtime that the request matches the
send will be sent as-is.

```ts
client.users.me.retrieve({
client.tasks.create({
// ...
// @ts-expect-error baz is not yet public
baz: 'undocumented option',
Expand Down
45 changes: 45 additions & 0 deletions examples/run-zod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env -S npm run tsn -T

import { BrowserUse } from 'browser-use-sdk';

import z from 'zod';
import { env } from './utils';

env();

// gets API Key from environment variable BROWSER_USE_API_KEY
const browseruse = new BrowserUse();

const HackerNewsResponse = z.object({
title: z.string(),
url: z.string(),
score: z.number(),
});

const TaskOutput = z.object({
posts: z.array(HackerNewsResponse),
});

async function main() {
console.log(`Creating Task...`);

// Create Task
const rsp = await browseruse.tasks.run({
task: 'Search for the top 10 Hacker News posts and return the title, url, and score',
schema: TaskOutput,
});

const posts = rsp.doneOutput?.posts;

if (posts == null) {
throw new Error('No posts found');
}

for (const post of posts) {
console.log(`${post.title} (${post.score}) - ${post.url}`);
}

console.log(`\nFound ${posts.length} posts`);
}

main().catch(console.error);
23 changes: 23 additions & 0 deletions examples/run.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env -S npm run tsn -T

import { BrowserUse } from 'browser-use-sdk';

import { env } from './utils';

env();

// gets API Key from environment variable BROWSER_USE_API_KEY
const browseruse = new BrowserUse();

async function main() {
console.log(`Creating Task...`);

// Create Task
const rsp = await browseruse.tasks.run({
task: "What's the weather line in SF and what's the temperature?",
});

console.log(rsp.doneOutput);
}

main().catch(console.error);
2 changes: 1 addition & 1 deletion examples/stream-zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ async function main() {
// Create a task and get the stream
const task = await browseruse.tasks.create({
task: 'Extract top 10 Hacker News posts and return the title, url, and score',
structuredOutputJson: TaskOutput,
schema: TaskOutput,
});

const stream = browseruse.tasks.stream({
Expand Down
2 changes: 1 addition & 1 deletion examples/zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ async function main() {
// Create Task
const rsp = await browseruse.tasks.create({
task: 'Extract top 10 Hacker News posts and return the title, url, and score',
structuredOutputJson: TaskOutput,
schema: TaskOutput,
});

poll: do {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "browser-use-sdk",
"version": "0.6.0",
"version": "0.7.0",
"description": "The official TypeScript library for the Browser Use API",
"author": "Browser Use <[email protected]>",
"types": "dist/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion src/lib/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { TaskCreateParams, TaskView } from '../resources/tasks';
// RUN

export type TaskCreateParamsWithSchema<T extends ZodType> = Omit<TaskCreateParams, 'structuredOutputJson'> & {
structuredOutputJson: T;
schema: T;
};

export function stringifyStructuredOutput<T extends ZodType>(schema: T): string {
Expand Down
45 changes: 43 additions & 2 deletions src/resources/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ export class Tasks extends APIResource {
body: TaskCreateParams | TaskCreateParamsWithSchema<ZodType>,
options?: RequestOptions,
): APIPromise<TaskCreateResponse> {
if (body.structuredOutputJson != null && typeof body.structuredOutputJson === 'object') {
const schema = body.structuredOutputJson;
if ('schema' in body && body.schema != null && typeof body.schema === 'object') {
const schema = body.schema;

const _body: TaskCreateParams = {
...body,
Expand Down Expand Up @@ -190,6 +190,47 @@ export class Tasks extends APIResource {
}
}

/**
* Create and run an agent task.
*
* @returns The output of the task.
*/
run<T extends ZodType>(
body: TaskCreateParamsWithSchema<T>,
options?: RequestOptions,
): APIPromise<TaskViewWithSchema<T>>;
run(body: TaskCreateParams, options?: RequestOptions): APIPromise<TaskView>;
run(
body: TaskCreateParams | TaskCreateParamsWithSchema<ZodType>,
options?: RequestOptions,
): APIPromise<unknown> {
if ('schema' in body && body.schema != null && typeof body.schema === 'object') {
return this.create(body, options)._thenUnwrap(async (data) => {
const taskId = data.id;

for await (const msg of this.stream<ZodType>({ taskId, schema: body.schema }, options)) {
if (msg.data.status === 'finished') {
return msg.data;
}
}

throw new Error('Task did not finish');
});
}

return this.create(body, options)._thenUnwrap(async (data) => {
const taskId = data.id;

for await (const msg of this.stream(taskId, options)) {
if (msg.data.status === 'finished') {
return msg.data;
}
}

throw new Error('Task did not finish');
});
}

/**
* Control the execution of an AI agent task.
*
Expand Down
2 changes: 1 addition & 1 deletion src/version.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const VERSION = '0.6.0'; // x-release-please-version
export const VERSION = '0.7.0'; // x-release-please-version