Skip to content
Open
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
62 changes: 62 additions & 0 deletions browsers/telemetry/categories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: "Telemetry Categories"
description: "The categories a browser session can capture, what each contains, and their cost"
---

A category groups related telemetry events and is the unit you enable or disable. Selection is opt-in: a session captures a category only when you turn it on.

For the full payload schema of any event type, see the [Stream telemetry events](https://kernel.sh/docs/api-reference/browser-telemetry/stream-telemetry-events-via-sse) endpoint in the API reference.

## Operational

These categories report on the session itself rather than page content.

| Category | Captures | Event types |
| --- | --- | --- |
| `control` | Computer-control API calls against the session | `api_call` |
| `connection` | CDP and live view connect/disconnect activity | `cdp_connect`, `cdp_disconnect`, `live_view_connect`, `live_view_disconnect` |
| `system` | VM-level failures | `system_oom_kill`, `service_crashed` |
| `captcha` | Results of automated captcha solves | `captcha_solve_result` |

## Browser activity

These categories report what's happening in the page. Capturing any of them attaches a Chrome DevTools Protocol (CDP) collector to the session and produces highly granular page-level events. Capturing them adds overhead, so enable only the ones you need.

| Category | Captures | Event types |
| --- | --- | --- |
| `console` | Console output from the page | `console_log`, `console_error` |
| `network` | Network requests, responses, and failures | `network_request`, `network_response`, `network_loading_failed`, `network_idle` |
| `page` | Navigation and page lifecycle, including performance signals | `page_navigation`, `page_dom_content_loaded`, `page_load`, `page_tab_opened`, `page_layout_shift`, `page_lcp`, `page_layout_settled`, `page_navigation_settled` |
| `interaction` | Browser-native input in the page (clicks, keys, scroll) | `interaction_click`, `interaction_key`, `interaction_scroll_settled` |
| `screenshot` | Periodic screenshots of the session | `monitor_screenshot` |

<Note>
`interaction` events are browser-native DOM events observed in the page, not calls to the [computer-control](/browsers/computer-controls) API (those are reported by the `control` category).
</Note>

### The monitor category

`monitor` reports the health of the CDP collector itself: `monitor_disconnected`, `monitor_reconnected`, `monitor_reconnect_failed`, and `monitor_init_failed`.

It isn't directly settable. It flows automatically whenever any of the browser-activity categories are captured. You can still [filter the stream](/browsers/telemetry/streaming) by `monitor` to isolate these events.

## Data sensitivity

Telemetry is off by default and the default set carries operational metadata only. The browser-activity categories are different: they capture what actually flows through the session, which is your own browser's data and can include credentials and personal information.

| Category | Can contain sensitive data |
| --- | --- |
| `network` | Request and response headers (including `Authorization` and `Cookie`), request bodies, and truncated response bodies, plus full URLs. A common place for session tokens, credentials, and personal data. |
| `console` | Anything the page logs. Applications often log access tokens, request or response bodies, and personal data through `console.log`. |
| `page` | Page URLs and titles, which can embed tokens or identifiers in query strings or fragments. |
| `interaction` | Text of clicked elements and typed keys, which can include personal data entered into forms. |
| `screenshot` | A full rendered image of the page - the broadest exposure, capturing anything visible on screen. |
| `control`, `connection`, `system`, `captcha`, `monitor` | Session metadata only (control calls, connection and health events). No page content. |

Captured events are persisted and can be replayed by [resuming the stream](/browsers/telemetry/streaming#resuming-after-a-disconnect), so this sensitivity applies to the data at rest, not just the live stream. Treat captured telemetry - and anywhere you forward or store it - with the same care as the underlying content. For how Kernel encrypts, retains, and processes data overall, see [Security](/security) and the [Data Processing Addendum](/dpa).

Some exposure is reduced for you automatically: input into sensitive fields such as passwords is suppressed (`interaction_key` isn't emitted for them, and `interaction_click` omits the element text). Beyond that, because selection is opt-in, the most effective control is to capture only the categories you need - enable `network`, `console`, `page`, `interaction`, or `screenshot` deliberately, and prefer the operational categories when you only need session health.

<Warning>
If you operate under HIPAA, GDPR, or similar obligations, be deliberate about the browser-activity categories: pointing them at a site that handles regulated data captures that data into storage. If you have compliance requirements around what Kernel may process, [contact us](mailto:security@kernel.sh) before enabling them.
</Warning>
111 changes: 111 additions & 0 deletions browsers/telemetry/overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
title: "Telemetry Overview"
description: "Capture what happens inside a browser session"
---

Telemetry captures events from inside a browser session - console output, network activity, page lifecycle, user interactions, captcha solves, and operational signals like crashes or connection changes. Once enabled, you can [stream them](/browsers/telemetry/streaming) live or pull them later for analysis.

Events are grouped into categories (`console`, `network`, `page`, and so on), and categories are the unit of control. Selection is opt-in: a session captures only the categories you turn on, and anything you don't stays off. See [Categories](/browsers/telemetry/categories) for the full list and what each one captures.

## Enabling telemetry

You configure telemetry when you [create a browser](/introduction/create) (and can change it later on update). There are three ways to configure it.

### Enable the default set

Set `enabled: true` with no per-category settings to capture the default set - a lightweight bundle of operational signals (`control`, `connection`, `system`, `captcha`) that's cheap to leave on:

<CodeGroup>
```typescript Typescript/Javascript
import Kernel from '@onkernel/sdk';

const kernel = new Kernel();

const browser = await kernel.browsers.create({
telemetry: { enabled: true },
});
```

```python Python
from kernel import Kernel

kernel = Kernel()

browser = kernel.browsers.create(
telemetry={"enabled": True},
)
```

```bash CLI
kernel browsers create --telemetry=all
```
</CodeGroup>

### Capture specific categories

List the categories you want under `telemetry.browser`. For example, this session captures `console` and `network` only:

<CodeGroup>
```typescript Typescript/Javascript
const browser = await kernel.browsers.create({
telemetry: {
browser: {
console: { enabled: true },
network: { enabled: true },
},
},
});
```

```python Python
browser = kernel.browsers.create(
telemetry={
"browser": {
"console": {"enabled": True},
"network": {"enabled": True},
},
},
)
```

```bash CLI
kernel browsers create --telemetry=console,network
```
</CodeGroup>

### Disable telemetry

<Info>
Telemetry is disabled by default. Use this only when updating a session to turn previously enabled telemetry back off.
</Info>

Set `enabled: false` on an existing session to turn telemetry off:

<CodeGroup>
```typescript Typescript/Javascript
await kernel.browsers.update(browser.session_id, {
telemetry: { enabled: false },
});
```

```python Python
kernel.browsers.update(
browser.session_id,
telemetry={"enabled": False},
)
```

```bash CLI
kernel browsers update <session-id> --telemetry=off
```
</CodeGroup>

<Info>
On update, a category list patches the current selection - categories you don't include keep their current state. To reset the selection instead, send `enabled: true` (it replaces the selection with the categories you provide, or the default set if you provide none); send `enabled: false` to turn telemetry off.
</Info>

## What's next

- [Categories](/browsers/telemetry/categories) - every category, what it captures, the default set, and cost characteristics.
- [Stream telemetry](/browsers/telemetry/streaming) - consume the live stream from the SDK, CLI, or raw SSE, with filtering and reconnection.
- For event payload schemas, see the [Stream telemetry events](https://kernel.sh/docs/api-reference/browser-telemetry/stream-telemetry-events-via-sse) endpoint in the API reference.
69 changes: 69 additions & 0 deletions browsers/telemetry/streaming.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: "Stream Telemetry"
description: "Consume a session's live telemetry stream from the SDK or CLI"
---

Once a session has telemetry [enabled](/browsers/telemetry/overview), you can stream its events in real time. The stream stays open until the session terminates.

## Via SDK

Open the stream and iterate over the envelopes:

<CodeGroup>
```typescript Typescript/Javascript
import Kernel from '@onkernel/sdk';

const kernel = new Kernel();

const stream = await kernel.browsers.telemetry.stream(sessionId);

for await (const { seq, event } of stream) {
console.log(`#${seq} [${event.category}] ${event.type}`);
}
```

```python Python
from kernel import Kernel

kernel = Kernel()

with kernel.browsers.telemetry.stream(session_id) as stream:
for envelope in stream:
event = envelope.event
print(f"#{envelope.seq} [{event.category}] {event.type}")
```
</CodeGroup>

To filter, check `event.category` and `event.type` in your loop. If the stream drops, re-open it with the last `seq` you processed as `last_event_id` to resume without gaps.

## Via CLI

Stream events to your terminal. The command runs until the session ends or you interrupt it:

```bash
kernel browsers telemetry stream <session-id>
```

### Filtering by category or event type

```bash
# Only network and console events
kernel browsers telemetry stream <session-id> --categories=network,console

# Only specific event types
kernel browsers telemetry stream <session-id> --types=network_response,console_error

# Machine-readable output
# -o json emits newline-delimited JSON envelopes for piping:
kernel browsers telemetry stream <session-id> -o json
```

### Resuming after a disconnect

The stream is a single connection; it does not reconnect on its own. Each event carries a monotonic `seq`, so to resume without gaps you re-open the stream and pass the last `seq` you processed.

```bash
kernel browsers telemetry stream <session-id> --seq 1024
```

The server then replays events after that sequence number.
8 changes: 8 additions & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@
]
},
"browsers/extensions",
{
"group": "Telemetry",
"pages": [
"browsers/telemetry/overview",
"browsers/telemetry/categories",
"browsers/telemetry/streaming"
]
},
{
"group": "Reserved Browsers",
"pages": [
Expand Down
52 changes: 49 additions & 3 deletions introduction/observe.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: "Observe"
description: "Watch your agent work, debug what went wrong"
---

Browser agents fail in ways that don't show up in logs. Kernel gives you four ways to see what's actually happeninglive, after the fact, frame by frame, and line by line.
Browser agents fail in ways that don't show up in logs. Kernel gives you several ways to see what's actually happening: live, after the fact, frame by frame, line by line, and event by event.

## Live view

Expand Down Expand Up @@ -60,7 +60,7 @@ Add `?readOnly=true` for a non-interactive view, or enable [kiosk mode](/browser

## Replays

Replays are MP4 recordings you start and stop on demand capture as many clips per session as you need. They're the right tool for post-hoc debugging: a failed run gives you one or more videos to scrub through, share, or attach to a bug report.
Replays are MP4 recordings you start and stop on demand - capture as many clips per session as you need. They're the right tool for post-hoc debugging: a failed run gives you one or more videos to scrub through, share, or attach to a bug report.

Replays can also be enabled on managed auth sessions, so you can [debug failed logins](https://www.kernel.sh/docs/auth/configuration#record-sessions-for-debugging) the same way.

Expand Down Expand Up @@ -119,7 +119,7 @@ Full reference: [Replays](/browsers/replays).

## Screenshots

Pull a frame at any moment with computer controls useful for snapshotting state at decision points, attaching to traces, or feeding back into a vision model.
Pull a frame at any moment with computer controls - useful for snapshotting state at decision points, attaching to traces, or feeding back into a vision model.

<CodeGroup>
```typescript Typescript/Javascript
Expand Down Expand Up @@ -192,9 +192,55 @@ if err := stream.Err(); err != nil {

Full reference: [Logs](/apps/logs).

## Telemetry

Telemetry is a real-time, structured stream of what happens inside a session: console output, network activity, page lifecycle, interactions, and operational signals like crashes. Unlike a video or screenshot, it's machine-readable, so it's the right tool for feeding session activity into your own observability pipeline or reacting to events programmatically. Enable it at creation, then stream the events:

<CodeGroup>
```typescript Typescript/Javascript
const browser = await kernel.browsers.create({ telemetry: { enabled: true } });

const stream = await kernel.browsers.telemetry.stream(browser.session_id);
for await (const { seq, event } of stream) {
console.log(`#${seq} [${event.category}] ${event.type}`);
}
```

```python Python
browser = kernel.browsers.create(telemetry={"enabled": True})

with kernel.browsers.telemetry.stream(browser.session_id) as stream:
for envelope in stream:
print(f"#{envelope.seq} [{envelope.event.category}] {envelope.event.type}")
```

```go Go
stream := client.Browsers.Telemetry.StreamStreaming(
ctx,
kernelBrowser.SessionID,
kernel.BrowserTelemetryStreamParams{},
)
defer stream.Close()

for stream.Next() {
fmt.Println(stream.Current())
}
if err := stream.Err(); err != nil {
panic(err)
}
```

```bash CLI
kernel browsers telemetry stream <session-id>
```
</CodeGroup>

Full reference: [Telemetry](/browsers/telemetry/overview).

## Picking the right tool

- **Building the agent?** Keep a [live view](/browsers/live-view) tab open while you iterate.
- **Debugging a failure?** Capture a [replay](/browsers/replays) for the run, then watch the video.
- **Instrumenting the agent itself?** Drop [screenshots](/browsers/computer-controls#take-screenshots) and [logs](/apps/logs) into your traces at the points that matter.
- **Feeding an observability pipeline?** Stream [telemetry](/browsers/telemetry/overview) events and route them wherever you collect signals.
- **Putting a human in the loop?** Embed the [live view](/browsers/live-view#embedding-in-an-iframe) in your own UI.
7 changes: 4 additions & 3 deletions reference/cli/browsers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Create a new browser session.
| `--headless` | Launch without GUI/VNC access. |
| `--kiosk` | Launch in Chrome kiosk mode. |
| `--start-url <url>` | Initial page to open on launch. |
| `--telemetry <spec>` | Configure [telemetry](/browsers/telemetry/overview) (opt-in): `all` for the default set, `off` to disable, or a comma-separated category list like `console,network`. |
| `--output json`, `-o json` | Output raw JSON object. |

### `kernel browsers delete <session-id>`
Expand Down Expand Up @@ -57,7 +58,7 @@ Update a running browser session — change or remove its proxy, load a profile,
| `--save-changes` | Save changes back to the profile when the session ends. |
| `--viewport <WxH@fps>` | Set viewport size (e.g. `1920x1080@25`). |
| `--force` | Force a viewport resize even during an active live view or recording. |
| `--telemetry <spec>` | Toggle telemetry: `all` to enable, `off` to disable, or per-category like `network=on,page=off`. |
| `--telemetry <spec>` | Update [telemetry](/browsers/telemetry/overview): `all` resets to the default set, `off` disables, or a comma-separated list like `console,network` to merge those categories into the current selection. |
| `--output json`, `-o json` | Output raw API response as JSON. |

### `kernel browsers curl <session-id> <url>`
Expand Down Expand Up @@ -105,11 +106,11 @@ Stream browser logs from the supervisor or a file path.
## Telemetry

### `kernel browsers telemetry stream <session-id>`
Stream live telemetry events (network, console, interaction, page, and system) from a browser session.
Stream live [telemetry](/browsers/telemetry/overview) events from a browser session. Filters are applied client-side and don't change what the session captures.

| Flag | Description |
|------|-------------|
| `--categories <list>` | Filter by category: `api`, `console`, `interaction`, `network`, `page`, `system`. |
| `--categories <list>` | Filter by category: `console`, `network`, `page`, `interaction`, `control`, `connection`, `system`, `screenshot`, `captcha`, `monitor`. |
| `--types <list>` | Filter by event type (e.g. `network_response,console_error`). |
| `--seq <n>` | Resume after sequence number N; replays events with `seq > N` (default: `-1`, stream from now). |
| `--output json`, `-o json` | Output newline-delimited JSON envelopes. |
Expand Down
Loading