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

# Browser Use

> Drive a real browser and a virtual display inside a runtime

Browser Use gives a runtime two ways to see and control what is on screen. The
**browser** is a managed Chromium instance you drive semantically — navigate,
snapshot the interactable elements, then click, fill, and type by element
reference. The **display** is a virtual screen you drive with raw pixels —
screenshots, mouse coordinates, and keystrokes.

Use them together or separately: the browser plane is precise and fast for web
work; the display plane reaches everything the browser plane cannot — native
dialogs, browser chrome, canvas and WebGL, and non-browser applications.

## The two planes

| | Browser (semantic) | Display (pixel) |
| - | - | - |
| Sees | Interactable elements with refs (`e1`, `e2`, …), URL, title | Rendered pixels |
| Acts by | Element ref, selector, role, text, XPath, or coordinates | X/Y coordinates and key names |
| Best for | Links, buttons, forms, text — anything the DOM describes | Native dialogs, canvas/WebGL, OS windows, non-browser apps |
| Requires display | No — runs headless | Yes — `display.enable` first |

Enable the display **before** opening a browser and the browser opens headed —
its window lives on the display, so both planes act on the same session:
snapshot to find an element's box, then fall back to pixel input for whatever
the DOM cannot describe.

## Requirements

Browser Use needs a runtime template that ships the browser and display stack
— use `browser-small`. On a template without Chromium, `browser.open` returns
`501`; without the display server, `display.enable` returns `400`.

```python Python theme={"dark"}
from gravixlayer import GravixLayer

client = GravixLayer()  # reads GRAVIXLAYER_API_KEY
sandbox = client.runtime.create(template="browser-small")

# Open a browser and load a page (headless — the display is not enabled).
browser = sandbox.browser.open(url="https://example.com")
bid = browser["browser_id"]  # "b1" for the runtime's first browser

# Snapshot the page, then clean up.
snap = sandbox.browser.snapshot(bid)
print(snap["title"], len(snap["elements"]), "elements")

sandbox.browser.close(bid)
sandbox.kill()
```

```typescript TypeScript theme={"dark"}
import { GravixLayer } from 'gravixlayer';

const client = new GravixLayer(); // reads GRAVIXLAYER_API_KEY
const sandbox = await client.runtime.create({ template: 'browser-small' });

// Open a browser and load a page (headless — the display is not enabled).
const browser = await sandbox.browser.open({ url: 'https://example.com' });
const bid = browser.browserId; // "b1" for the runtime's first browser

// Snapshot the page, then clean up.
const snap = await sandbox.browser.snapshot(bid);
console.log(snap.title, snap.elements.length, 'elements');

await sandbox.browser.close(bid);
await sandbox.kill();
```

```bash CLI theme={"dark"}
export GRAVIXLAYER_API_KEY=gl_sk_...
RT=$(gravixlayer runtime create -t browser-small --wait --output json | jq -r '.runtime_id')

gravixlayer runtime browser open "$RT" --url https://example.com   # opens b1
gravixlayer runtime browser snapshot "$RT" --browser b1
gravixlayer runtime browser close "$RT" --browser b1
gravixlayer runtime kill "$RT" -y
```

```bash cURL theme={"dark"}
export GRAVIXLAYER_API_KEY=gl_sk_...
API="https://api.gravixlayer.ai/v1"

# Create a runtime on browser-small, then use $RT for its id.
# (REST create sends cloud and region explicitly; SDKs default them.)
RT=$(curl -sS -X POST "$API/agents/runtime" \
  -H "Authorization: Bearer $GRAVIXLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template":"browser-small","cloud":"aws","region":"us-east-1"}' \
  | jq -r .runtime_id)

curl -sS -X POST "$API/agents/runtime/$RT/browser/open" \
  -H "Authorization: Bearer $GRAVIXLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com"}'

curl -sS -X POST "$API/agents/runtime/$RT/browser/b1/snapshot" \
  -H "Authorization: Bearer $GRAVIXLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"viewport_only":true}'

curl -sS -X POST "$API/agents/runtime/$RT/browser/b1/close" \
  -H "Authorization: Bearer $GRAVIXLAYER_API_KEY"

curl -sS -X DELETE "$API/agents/runtime/$RT" \
  -H "Authorization: Bearer $GRAVIXLAYER_API_KEY"
```

On the other Browser Use pages, Python and TypeScript examples are
self-contained. CLI and cURL examples expect `$RT` to hold a live runtime —
create one as above and skip the final `kill` until you are done.

## Lifecycle

1. **Create a runtime** on `browser-small`.
2. **Enable the display** if you want a headed window, pixel input, or a live
   view of the screen.
3. **Open a browser** — headed when the display is enabled, headless
   otherwise. `sandbox.browser.goto(url)` opens one on first use.
4. **Act** — navigate, snapshot, click, fill, screenshot, download, print.
5. **Close the browser** when done. Killing the runtime stops its browsers;
   each `open` starts a new instance.

## IDs

| ID | Example | Scope |
| - | - | - |
| `runtime_id` | `b7f3…` (UUID) | The sandbox; every URL carries it |
| `browser_id` | `b1`, `b2`, … | A browser inside the runtime — numbered in open order |
| `target_id` | hex string | A tab inside a browser — from `open`, `status`, or `targets` |
| `ref` | `e3` | An element from the tab's latest snapshot |
| `download_id` | GUID | A download — from `downloads` |

Read `target_id` and `download_id` from responses; they are generated per
session, so never hard-code them.

## Objects

**BrowserInfo** — returned by `open` and `list` (`status` returns the
`{browser_id, state, targets}` subset):

| Field | Type | Description |
| - | - | - |
| `browser_id` | string | Browser handle (`b1`, …) |
| `engine` | string | `chromium` |
| `version` | string | Engine version |
| `headless` | bool | `true` when no window is on the display |
| `pid` | int | Browser process id in the guest |
| `state` | string | `running` or `exited` |
| `targets` | array | `BrowserTargetInfo` list (below) |

**BrowserTargetInfo** — a tab:

| Field | Type | Description |
| - | - | - |
| `target_id` | string | Tab handle |
| `url` | string | Current URL |
| `title` | string | Current title |
| `type` | string | Always `page` |
| `active` | bool | The tab is attached and not loading |
| `loading` | bool | A navigation is in flight |

`active` and `loading` are populated in `open`, `list`, and `status`; the
`targets` endpoint reports both as `false`.

**BrowserSnapshot** — the interactable digest, described in
[Snapshots & Actions](/documentation/agentruntime/browser-use/actions).

**ActionResult** — every action returns it:

| Field | Type | Description |
| - | - | - |
| `ok` | bool | The action was dispatched |
| `navigated` | bool | The action caused a navigation |
| `settled` | bool | The page reached quiescence afterward |
| `url` | string | URL after the action |
| `reason` | string | Why `ok` is `false`, when it is |

**DisplayStatus** — returned by `display.enable` and `display.status`:

| Field | Type | Description |
| - | - | - |
| `enabled` | bool | The display server is running |
| `width` / `height` / `depth` | int | Framebuffer geometry |
| `display` | string | X11 display name (`:0`) |
| `wm` | string | Window manager, if one is running |

## Errors

| Status | Meaning |
| - | - |
| `400` | Invalid request or state — bad `by`, a malformed body, a browser whose process exited (`open` again), a display server that failed to start, or a `secret_ref` that is not attached. Non-action calls on an unactionable element return `400 element is not actionable: <reason>` |
| `404` | Stale element ref (snapshot again), no pending dialog, or no such browser, tab, or download |
| `408` | The operation timed out |
| `500` | Internal — the operation failed inside the guest (for example the browser failed to start); retry or `open` again |
| `501` | Not implemented — `engine: "firefox"`, or a template without Chromium (recreate on `browser-small`) |
| `503` | The browser/display channel is temporarily unavailable — retry |

## Limits and notes

* One runtime can host several browsers; each browser hosts several tabs.
  Tabs share the browser's profile and cookies.
* A snapshot returns at most 500 elements. Refs are re-issued by every
  snapshot of a tab — act on refs from the latest one.
* `evaluate` runs JavaScript with page privileges — treat the expression as
  code you ship, not as user input.
* `fill` accepts `secret_ref` — the key of a secret in an
  [Identity provider](/documentation/agentruntime/getting-started/identity-providers)
  attached to the runtime — and types its value without it ever reaching your
  client.
* Browser and display time is ordinary runtime time — it bills at the
  runtime's rate while the sandbox runs.
* The browser honors the runtime's network policy — pages can only reach what
  the sandbox can reach.

## Next

> **[Display](/documentation/agentruntime/browser-use/display)**
>
> Enable the virtual screen, screenshot it, and drive raw mouse and keyboard input.

> **[Browser Sessions](/documentation/agentruntime/browser-use/browser)**
>
> Open, navigate, and manage browsers and tabs.

> **[Snapshots & Actions](/documentation/agentruntime/browser-use/actions)**
>
> The element digest and ref-based interactions — the model loop.

> **[Capture & Downloads](/documentation/agentruntime/browser-use/capture)**
>
> Screenshots, PDFs, downloads, and live watch URLs.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.