Skip to main content
A computer can have an optional managed browser attached. It is a real browser operated by Vetta’s browser automation interface and driven — by the agent’s browser tool, or by you over REST, the SDK and the CLI — through a small set of high-level actions. Every action is domain-scoped. A session bills its minutes from open to close on the browser line item; the model-driven actions add their own spend on the same line. The agent never receives the underlying connect URL or the live-view URL — only the action results.

Session creation

Attaching a browser opens a session. Creation is two-phase and orphan-safe: Vetta writes a creating row before asking the browser automation interface for an upstream session, then promotes it to active on success or marks it error on failure. If the process dies mid-create, the creating row is retired as error by the timeout sweep once its timeout_minutes elapse, and the upstream session — opened with the same timeout — expires on its own; nothing is billed for it.
1

creating

A row is written first, before any upstream session exists.
2

active

The upstream session is up; the row is promoted and the agent can drive it.
3

closed

Closed by DELETE, by the agent, or by the sweep once timeout_minutes elapse — billed either way.
4

error

Creation failed, or never finished; the row records it and bills nothing.
Over REST the first action opens the session lazily; GET /v1/computers/{id}/browser reads it and DELETE closes it.

Attach a browser

Enable a browser when you create the computer. It reaches the open web unless you pass allowed_domains, which scopes every page it navigates to.

Actions

Two kinds of action drive the page. Deterministic actions take a URL or a CSS selector and do exactly that. Plain-language actions take an instruction; a model reads the live page and carries it out. Every result carries the url the page is on afterwards.

A screenshot the agent can see

A screenshot answers with two things. The file is the deliverable: the bytes go to storage and the result’s output carries { url, file_id, sha256, size_bytes }, so the PNG survives the session and is there to publish, attach or download. The picture is what the model is shown, and it travels as a ToolImage — { file_id, url, media_type }, where url is a short-lived signed read of that same file. The image is a link and never the bytes. A tool result lands in the session’s history and is replayed on every turn that follows, so an agent that browses for an hour would otherwise re-send every PNG it ever took, over and over, at full size. A link costs a couple of hundred bytes and does not grow, and only the most recent tool results send their pictures to the model — an older screenshot stays in the transcript as a link a person can click, not as an image paid for on every later turn. A link is good for fifteen minutes, so an agent that wants to look at something again takes a fresh screenshot rather than reaching back; that is also why a picture does not survive a session going to sleep and waking up. Without a file catalogue configured the action refuses rather than hand out an id that resolves to nothing. If the file was written but the link could not be minted, the screenshot still answers with its file_id — the deliverable is on disk either way, and only the looking is lost.
Plain-language actions need a model behind the browser. Where none is configured they fail with feature_not_configured; the deterministic actions keep working.

Write guard

Unless allow_writes is set, an act, click or type whose instruction, target or page looks like a write — submit, purchase, delete, send, pay, confirm, or a form submission on a non-search form — is refused with forbidden (param: allow_writes). Reading is always allowed; changing something is opt-in.

Domain re-validation on every action

Every action re-validates the current page URL against allowed_domains before it runs and again after — not just at goto, and including after act. A redirect, a link or an instruction that lands off the allow-list is blocked and the page is parked on a blank tab. Regardless of the allow-list, the browser always blocks private, loopback, and metadata hosts (link-local, internal ranges, and cloud metadata endpoints), including hostnames that resolve into them.
The allow-list is checked on the page URL — the document the browser navigates to. Subresources a page loads on its own (fetch/XHR, images, iframes) are not individually checked against allowed_domains today. Treat it as control over where the agent goes, not as an exfiltration boundary for a page that is already open.
"*" disables the allow-list check but does not disable the private/loopback/metadata block, and every action under "*" is logged. Prefer a scoped list.

Credentials & saved logins

Credentials are never entered through type or act. A guard refuses credential-shaped input — password, token and key patterns; vault values stay sealed and are never compared — with validation_failed, so the agent cannot type a password into a field via a normal action. Instead, a login runs through the dedicated login flow: it reads the identity’s vault credential login:<service> and fills the form through %username% and %password% placeholders. The agent drives the flow; the plaintext never enters the model or a result. Save the credential first with POST /v1/browser/credentials (vetta browser credential save), or let signup create the account — it generates a password, seals it into the vault, then registers.

Saved logins are default-deny

A saved login (“context”) is identity-scoped and default-deny. It is bound when a browser opens: the engine attaches the context at session start and writes cookies and storage into it when the session closes. So a login is filled in two steps — save_context with no browser open creates the empty saved login under a name owned by the session’s identity; a browser opened with that context_name and persist_context (or human_login) fills it at close. save_context from a browser open on another or no context is refused with validation_failed — nothing that browser holds can reach the saved login. An agent cannot reopen a saved login just by naming it in context_name — it needs an explicit grant, by agent id or by role, made from the dashboard. Without a grant, context_name is refused with forbidden. On a session that reopened a saved login, extract, observe, links and screenshot also need allow_extract, and what they return is redacted of email, phone and card patterns.

Human-first login

Set human_login to run a human-first flow: save_context the name first, open with that context_name and human_login, a person completes the login once in the live view, then save_context again marks it saved and the close persists it for later reuse. During the flow a 15-minute lock is held on the context until the second save_context completes; a second open of the same context while locked is 409 context_locked.

Session lifetime & what’s withheld

  • Each session runs under timeout_minutes — default 15 minutes, maximum 360 (6 hours). See Limits & billing.
  • The agent’s own browser opens on its first browser action and closes when the agent session ends or pauses for input — it never idles on the clock while a question waits for you. The next turn opens a fresh one on demand; a saved login (context_name) carries the signed-in state across.
  • Minutes are billed open to close on the browser line item, settled when the session closes; act, extract and observe add their model spend on the same line.
  • Withheld from the agent and from API keys: the raw connect URL and the live-view URL. The live view answers a signed-in dashboard session only; an API key gets forbidden.

Configuration reference

string[]
default:"[\"*\"]"
The domains the browser may reach. Omit it for the open web — unrestricted browsing is logged. Private, loopback and metadata hosts stay blocked either way (see above), so this list narrows public reach rather than granting it. An explicit [] is validation_failed. Using a proxy requires a scoped list — "*", including the default, is not allowed with a proxy.
integer
default:"15"
Per-session timeout. Range 1–360 minutes (up to 6 hours).
string
default:"us-west"
Geographic region the browser runs in: us-west, us-east, eu-central, or ap-southeast. Pick the one closest to the target site.
boolean
default:"false"
Keep the session alive across brief disconnects instead of closing it. Useful for long, resumable flows.
boolean
default:"false"
Write cookies and local storage back to the named context_name when the session closes, so a later session can resume the same logged-in state. Implied by human_login.
object
{ width, height } in pixels for the browser viewport.
string
Emulated platform fingerprint: windows, mac, linux, mobile, or tablet.
boolean
default:"false"
Block ad and tracker requests.
boolean
default:"true"
Attempt automated CAPTCHA solving on supported challenges.
boolean
default:"false"
Enable advanced anti-bot evasion (stealth / verified fingerprint).
boolean
default:"false"
When false, the write guard refuses write-looking act, click and type. Set true to permit them.
boolean
default:"false"
Gates extract, observe, links and screenshot on saved-login sessions. Off by default so a reused login can’t silently exfiltrate page content. When on, credential-shaped values, e-mail addresses and phone numbers are redacted from what those actions return.
string
Reopen a saved login (“context”) by name, 1–64 characters. Subject to the default-deny grant model above.
boolean
default:"false"
Start a human-first login flow on an existing context_name. Takes a 15-minute lock on the context until save_context completes, and persists the login at close.
boolean
default:"false"
Route egress through a residential path. Requires a scoped allowed_domains list — true with "*" is validation_failed.
string[]
default:"[\"signup\"]"
Read by the agent browser tool only: the actions that pause for the operator’s approval while the tool is allow. Any of goto, click, type, act, extract, observe, links, screenshot, login, signup, save_context; an unknown name is validation_failed. Has no effect on a browser opened over REST.

Next: snapshots & volumes

Checkpoint a running VM, fork from it, and keep state on a persistent volume.