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

# Advanced browser control

> Run deterministic browser code against managed browsers and understand when to use it around browser-agent workflows.

Webcompute can run exact browser code against a managed browser. Use it when your app or coding-agent host should decide a specific browser step.

There are two control modes on the same runtime:

* Agent control, where `web agent`, SDK `web.agent()`, or MCP `run_web_agent` handles the live browser task.
* Deterministic control, where your app or coding-agent host runs focused browser-code snippets.

Use agent control when you want the browsing goal completed. Use deterministic control when you need exact setup, validation, file handling, retries, or recovery steps.

## Agent control

```bash theme={null}
web agent \
  --url https://www.sec.gov/edgar/search/ \
  --allow-domain sec.gov \
  "Find Apple's latest 10-Q filing and return filing metadata."
```

Agent control is model-backed. Configure a model profile with `web model setup`, or pass a route, model, and provider credential flags for a single run.

## Deterministic control

```ts theme={null}
import { Web } from "@webcompute/sdk";

const web = new Web();
const browser = await web.browser.create({
  policy: { allowedDomains: ["sec.gov"] },
  recording: true,
});

try {
  const result = await browser.playwright.execute({
    code: `
      await page.goto("https://www.sec.gov/edgar/search/");
      return {
        title: await page.title(),
        url: page.url(),
      };
    `,
  });

  console.log(result.result);
} finally {
  await browser.close();
}
```

The code body runs with `page` already in scope. Return values explicitly when another step needs the result.

## Execution result anatomy

Ask for capture when the next step needs browser status, page observation, or artifacts.

```ts theme={null}
const result = await browser.playwright.execute({
  code: `
    await page.goto("https://example.com");
    const heading = await page.getByRole("heading").first().textContent();
    return { heading, url: page.url() };
  `,
  capture: {
    status: true,
    observation: { kind: "aria", includeOn: "always" },
  },
});

console.log(result.result);
console.log(result.page);
console.log(result.status);
console.log(result.observation?.truncated);
```

Use `result.result` for your returned value. Use `result.page`, `result.status`, and `result.observation` to decide the next step or to preserve evidence.

## Write browser code for agents

When a coding agent or app writes snippets, keep them small and inspectable:

* Use the provided `page` instead of redeclaring it.
* Prefer `page.getByRole`, `page.getByLabel`, and `page.getByText` over coordinates.
* Return structured values from each snippet.
* Use bounded waits and explicit checks.
* Avoid infinite polling loops.
* Clean up browsers your application creates.

Playwright locator APIs automatically wait for many actions to be actionable. Lean on that behavior instead of adding arbitrary sleeps.

## Handle missing page state

```ts theme={null}
const result = await browser.playwright.execute({
  code: `
    await page.goto("https://example.com");
    const button = page.getByRole("button", { name: "Download report" });
    if (!(await button.count())) {
      return { available: false, reason: "Download report button not found", url: page.url() };
    }
    await button.first().click();
    return { available: true };
  `,
  capture: { status: true, observation: { kind: "aria", includeOn: "always" } },
});
```

Return a structured "not found" result when absent page state is a business outcome. Throw an error when the workflow cannot continue.

## MCP control

MCP hosts use `manage_browsers` for lifecycle and `execute_playwright_code` for deterministic page work. The runtime surface returns the code result plus bounded observation, status, logs, and artifacts so the host can decide the next snippet.

```text theme={null}
manage_browsers({ action: "create", recording: true })
execute_playwright_code({ code: "await page.goto('https://example.com'); return await page.title();" })
execute_playwright_code({ code: "return await page.getByRole('heading').first().textContent();" })
manage_browsers({ action: "close" })
```

Reference: [observations](/runtime-concepts/observations), [resources](/runtime-concepts/browser-resources), [SDK browser reference](/reference/sdk-browser-reference), [MCP tool reference](/reference/mcp-tool-reference), and [choose your path](/get-started/choose-your-path).
