> ## Documentation Index
> Fetch the complete documentation index at: https://vetta.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# browser

> The managed browser on a computer — client.computers.browser(id), client.browser.credentials and client.browser.contexts.

`client.computers.browser(id)` binds one [computer](/docs/sdk/computers) and exposes its browser; `client.browser` holds the saved logins that outlive a session. Sixteen methods; results parse with the core `BrowserActionResultSchema`, `BrowserSessionSchema`, `BrowserContextSchema` and `BrowserGrantSchema`. API detail: [Browser](/docs/api/browser); options and guards: the [Browser](/docs/computer/browser) guide.

## Attach a browser

The `browser` field of `computers.create` is the full option object, typed `BrowserOptionsInput` — every field has a default, `allowed_domains` included (`["*"]`, the open web).

```ts theme={"system"}
const box = await client.computers.create({
  name: "box",
  browser: { allowed_domains: ["app.example.com"], timeout_minutes: 20, allow_writes: true },
});
const browser = client.computers.browser(box.id);
```

## Actions

Each is one `POST /v1/computers/{id}/browser/actions` with one body, and answers a `BrowserActionResult`. The transport adds the `Idempotency-Key` the route requires on `goto` and `act`.

```ts theme={"system"}
browser.goto(url: string): Promise<BrowserActionResult>
browser.click(selector: string): Promise<BrowserActionResult>
browser.type(selector: string, text: string): Promise<BrowserActionResult>
browser.act(instruction: string, variables?: Record<string, string>): Promise<BrowserActionResult>
browser.extract(body?: { instruction?: string; selector?: string; schema?: Record<string, unknown> }): Promise<BrowserActionResult>
browser.observe(instruction: string): Promise<BrowserActionResult>
browser.links(query?: { contains?: string; limit?: number }): Promise<BrowserActionResult>
browser.screenshot(): Promise<BrowserActionResult>
```

`act` fills `%name%` placeholders in the instruction from `variables`; the values are sent once and never come back in a result. `extract` with no argument reads the page's text; with a `selector`, that element's; with an `instruction` or `schema`, the model reads it and `data` takes the schema's shape.

```ts theme={"system"}
const prices = await browser.extract({
  instruction: "every product and its price",
  schema: { type: "object", properties: { items: { type: "array" } } },
});
prices.data; // shaped to the schema
const shot = await browser.screenshot();
shot.file_id; // a fil_ — the bytes are a file, never in the result
```

<ResponseField name="object" type="string">Always `browser_action`.</ResponseField>
<ResponseField name="action" type="string">The action that ran.</ResponseField>
<ResponseField name="url" type="string">The page URL afterwards.</ResponseField>
<ResponseField name="text" type="string | null">`extract` without a schema.</ResponseField>
<ResponseField name="data" type="unknown | null">`extract` with a schema.</ResponseField>
<ResponseField name="links" type="{ href, text }[] | null">`links`.</ResponseField>
<ResponseField name="elements" type="{ selector, description }[] | null">`observe`.</ResponseField>
<ResponseField name="file_id" type="string | null">`screenshot`.</ResponseField>
<ResponseField name="performed" type="boolean">Always `true` on success; an `act` that did nothing rejects with `provider_error`.</ResponseField>

## status / close

```ts theme={"system"}
browser.status(): Promise<BrowserSession>
browser.close(): Promise<BrowserSession | null>
```

`GET` and `DELETE /v1/computers/{id}/browser`. `status` rejects with `not_found` when nothing is open; `close` resolves the closed session (`status: "closed"`, `closed_at` set) and is idempotent — it resolves `null` on the `204` that means nothing was open.

## saveContext

```ts theme={"system"}
browser.saveContext(body: SaveBrowserContext): Promise<BrowserContext>
```

`POST /v1/computers/{id}/browser/context`. `SaveBrowserContext` is `{ name, identity_id, service? }`. A saved login is bound when a browser opens, so this call has two moments: with no browser open on the computer it creates the empty saved login owned by the identity; on a browser opened with that `context_name` it marks the login saved and releases a `human_login` lock, and the close writes the cookies and storage into it. On a browser open without that context it rejects with `validation_failed` (`context_name`).

## login / signup

```ts theme={"system"}
browser.login(body: BrowserLogin): Promise<BrowserActionResult>
browser.signup(body: BrowserSignup): Promise<BrowserActionResult>
```

`POST /v1/computers/{id}/browser/login` with `{ service, url, identity_id }` fills the sign-in form from the identity's vault credential `login:<service>`; the plaintext never enters the model or the result. `signup` takes the same plus `email`, generates a password, seals it into the vault, then registers.

## browser.credentials.save

```ts theme={"system"}
client.browser.credentials.save(body: BrowserCredential): Promise<VaultCredential>
```

`POST /v1/browser/credentials`. `BrowserCredential` is `{ identity_id, service, email, password, username? }`. The reply is the [vault credential](/docs/sdk/vaults)'s metadata — there is no method that returns the value.

## browser.contexts.grant / revoke

```ts theme={"system"}
client.browser.contexts.grant(name: string, body: CreateBrowserGrant): Promise<BrowserGrant>
client.browser.contexts.revoke(name: string, identityId: string): Promise<Deleted>
```

`POST /v1/browser/contexts/{name}/grants` with `{ identity_id, grantee_type: "agent" | "role", grantee_id }`, and `DELETE /v1/browser/contexts/{name}?identity_id=`. A saved login is default-deny until an agent or role is granted; the same grantee twice replays the existing grant. Both are **dashboard-session only** — with an API key they reject with `forbidden`.

There is no `liveView` method. The live-view URL is a bearer credential; the dashboard serves it same-origin and nothing in the SDK returns it.
