Kernel Browser Telemetry API
Stream live telemetry events from a browser session.
Stream live telemetry events from a browser session.
openapi: 3.1.0
info:
title: Kernel API Keys Browser Telemetry API
description: Developer tools and cloud infrastructure for AI agents to use web browsers
version: 0.1.0
servers:
- url: https://api.onkernel.com
description: API Server
security:
- bearerAuth: []
tags:
- name: Browser Telemetry
description: Stream live telemetry events from a browser session.
paths:
/browsers/{id}/telemetry/stream:
get:
summary: Stream telemetry events via SSE
description: 'Streams browser telemetry events as a server-sent events (SSE) stream. The stream closes when the browser session terminates. Each event frame includes an id: field containing a monotonically increasing sequence number; pass it as Last-Event-ID on reconnect to resume without gaps. The event: field is never set; all frames carry JSON in the data: field. A keepalive comment frame is sent every 15 seconds when no events arrive. Returns 404 if the browser session does not exist. If telemetry was not enabled on the session, the stream opens but no events are delivered. Fresh connections only see new events; pass replay=all to start from the oldest retained event instead.
'
operationId: streamBrowserTelemetry
tags:
- Browser Telemetry
security:
- bearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
description: Browser session ID
- name: Last-Event-ID
in: header
schema:
type: string
description: Last event sequence number for SSE reconnection (sent by SSE clients on reconnect). Takes precedence over replay when both are present, so reconnect resumes instead of re-replaying.
- name: replay
in: query
schema:
type: string
description: Pass `all` to start from the oldest retained event instead of only new events; any other value is treated as from-now. The buffer is bounded, so the first event id may be greater than 1 if older events were evicted.
responses:
'200':
description: SSE stream of telemetry events
headers:
X-SSE-Content-Type:
description: Media type of SSE data events (always application/json).
schema:
type: string
const: application/json
content:
text/event-stream:
schema:
$ref: '#/components/schemas/BrowserTelemetryEventEnvelope'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalError'
x-codeSamples:
- lang: JavaScript
source: "import Kernel from '@onkernel/sdk';\n\nconst client = new Kernel({\n apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted\n});\n\nconst response = await client.browsers.telemetry.stream('id');\n\nconsole.log(response.event);"
- lang: Python
source: "import os\nfrom kernel import Kernel\n\nclient = Kernel(\n api_key=os.environ.get(\"KERNEL_API_KEY\"), # This is the default and can be omitted\n)\nfor telemetry in client.browsers.telemetry.stream(\n id=\"id\",\n):\n print(telemetry)"
- lang: Go
source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/kernel/kernel-go-sdk\"\n\t\"github.com/kernel/kernel-go-sdk/option\"\n)\n\nfunc main() {\n\tclient := kernel.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\tstream := client.Browsers.Telemetry.StreamStreaming(\n\t\tcontext.TODO(),\n\t\t\"id\",\n\t\tkernel.BrowserTelemetryStreamParams{},\n\t)\n\tfor stream.Next() {\n\t\tfmt.Printf(\"%+v\\n\", stream.Current())\n\t}\n\terr := stream.Err()\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n"
/browsers/{id}/telemetry/events:
get:
summary: Read telemetry events for a browser session
description: 'Reads a page of telemetry events for the browser session. To page through results, pass the X-Next-Offset value from the previous response as offset and repeat while X-Has-More is true. Returns an empty list when telemetry data is unavailable.
'
operationId: readBrowserTelemetryEvents
tags:
- Browser Telemetry
security:
- bearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
description: Browser session ID
- name: offset
in: query
required: false
description: 'Opaque pagination cursor: pass the X-Next-Offset value from the previous response to fetch the next page. When set, paging continues from this cursor and since is ignored, while until still bounds the page. It is not an event''s seq field, so do not derive it from the response body.
'
schema:
type: integer
minimum: 0
- name: since
in: query
required: false
description: 'Start of the window: an RFC-3339 timestamp, or a duration like 5m meaning that long ago. Defaults to 5m. Ignored when offset is set.
'
schema:
type: string
- name: until
in: query
required: false
description: 'End of the window (exclusive): an RFC-3339 timestamp, or a duration like 5m meaning that long ago.
'
schema:
type: string
- name: limit
in: query
required: false
description: Maximum number of events per page. Defaults to 20.
schema:
type: integer
minimum: 1
maximum: 100
default: 20
- name: category
in: query
required: false
description: Restrict results to these event categories. Repeat the parameter for multiple values.
schema:
type: array
items:
type: string
enum:
- console
- network
- page
- interaction
- control
- connection
- system
- screenshot
- captcha
- monitor
- name: order
in: query
required: false
description: 'Read direction. asc (default) reads oldest first, starting from since or the offset cursor. desc reads newest first: each request returns one page of up to limit records ending at the offset cursor (or until, or the newest archived event); combining desc with since is rejected with a 400. In either direction the category filter applies within the page, so a filtered page may be empty while X-Has-More is true.
'
schema:
type: string
default: asc
responses:
'200':
description: A page of telemetry events.
headers:
X-Has-More:
description: Whether more results are available
schema:
type: boolean
X-Next-Offset:
description: The offset where the next page starts. 0 when there are no more results.
schema:
type: integer
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/BrowserTelemetryEventEnvelope'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalError'
x-codeSamples:
- lang: JavaScript
source: "import Kernel from '@onkernel/sdk';\n\nconst client = new Kernel({\n apiKey: process.env['KERNEL_API_KEY'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const telemetryEventsResponse of client.browsers.telemetry.events('id')) {\n console.log(telemetryEventsResponse.event);\n}"
- lang: Python
source: "import os\nfrom kernel import Kernel\n\nclient = Kernel(\n api_key=os.environ.get(\"KERNEL_API_KEY\"), # This is the default and can be omitted\n)\npage = client.browsers.telemetry.events(\n id=\"id\",\n)\npage = page.items[0]\nprint(page.event)"
- lang: Go
source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/kernel/kernel-go-sdk\"\n\t\"github.com/kernel/kernel-go-sdk/option\"\n)\n\nfunc main() {\n\tclient := kernel.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"),\n\t)\n\tpage, err := client.Browsers.Telemetry.Events(\n\t\tcontext.TODO(),\n\t\t\"id\",\n\t\tkernel.BrowserTelemetryEventsParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", page)\n}\n"
components:
schemas:
BrowserSystemOomKillEvent:
type: object
description: The Linux kernel OOM-killer terminated a process inside the VM. Fires for any process killed by the kernel due to memory exhaustion, including Chrome renderer subprocesses that are not supervised.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: system_oom_kill
category:
type: string
const: system
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
type: object
additionalProperties: false
required:
- process_name
- pid
- rss_kb
properties:
process_name:
type: string
description: Comm of the killed process as reported by the kernel (max 15 chars, truncated by the kernel).
pid:
type: integer
description: PID of the killed process.
rss_kb:
type: integer
description: Resident set size of the killed process in KiB (sum of anon-rss, file-rss, and shmem-rss).
trigger_process_name:
type: string
description: Comm of the process whose allocation request caused the kernel to invoke the OOM-killer. Often the same as process_name but can differ. Max 15 chars.
trigger_pid:
type: integer
description: PID of the triggering process. Absent if the kernel did not emit the standard header line.
constraint:
type: string
x-go-type: string
description: Why the kernel decided to OOM-kill. none means global memory exhaustion; memcg means a cgroup memory limit was hit; cpuset / memory_policy are NUMA/policy-driven kills. Absent on kernels older than 5.0.
enum:
- none
- memcg
- cpuset
- memory_policy
mem_total_kb:
type: integer
description: Total system memory in KiB at the time of the kill. Assumes a 4 KiB page size. Absent if the kernel did not emit a parseable Mem-Info section.
mem_free_kb:
type: integer
description: Free system memory in KiB at the time of the kill. Assumes a 4 KiB page size. Does not include reclaimable caches. Absent if the kernel did not emit a parseable Mem-Info section.
top_tasks:
type: array
maxItems: 5
description: Top processes by resident-set-size at the moment of the kill, sorted descending. Empty if the kernel did not emit the Tasks state table. Capped at 5 entries.
items:
type: object
additionalProperties: false
required:
- pid
- name
- rss_kb
properties:
pid:
type: integer
description: PID of the process.
name:
type: string
description: Comm of the process (max 15 chars, truncated by the kernel).
rss_kb:
type: integer
description: Resident set size in KiB at the moment of the kill.
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserPageNavigationSettledEvent:
type: object
title: page_navigation_settled
description: Emitted when page_dom_content_loaded and page_layout_settled have both fired for the same navigation, indicating the page is loaded and visually stable. Independent of network_idle; a single pending request does not block it.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: page_navigation_settled
category:
type: string
const: page
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
$ref: '#/components/schemas/BrowserEventContext'
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserCdpConnectEvent:
type: object
description: An external client (e.g. customer SDK, Playwright, Puppeteer) connected to the CDP WebSocket proxy on this VM.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: cdp_connect
category:
type: string
const: connection
source:
$ref: '#/components/schemas/BrowserEventSource'
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserCaptchaSolveResultEvent:
type: object
description: A captcha solve attempt reached a terminal outcome.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: captcha_solve_result
category:
type: string
const: captcha
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
type: object
additionalProperties: false
required:
- captcha_type
- status
- duration_ms
properties:
captcha_type:
type: string
x-go-type: string
description: Captcha vendor family. Provider-specific task names are normalized into this set; anything not covered is reported as other.
enum:
- hcaptcha
- recaptcha_v2
- recaptcha_v3
- turnstile
- geetest
- other
status:
type: string
x-go-type: string
description: 'Terminal outcome. success: solver returned a usable solution. failure: solver returned an error (see error_code). timeout: solver did not return within the caller''s wait budget. abandoned: caller cancelled or the page navigated away mid-solve.'
enum:
- success
- failure
- timeout
- abandoned
duration_ms:
type: number
description: Wall-clock duration from solve start to terminal outcome.
task_id:
type: string
description: Solver-assigned identifier. Opaque, useful for support cross-references.
website_host:
type: string
description: Host of the page where the captcha was solved.
website_path:
type: string
description: Path of the page where the captcha was solved. Query string excluded.
error_code:
type: string
description: Solver-specific error code on failure (e.g. ERROR_CAPTCHA_UNSOLVABLE). Absent on success.
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserPageLcpEvent:
type: object
title: page_lcp
description: A browser Largest Contentful Paint (LCP) event from the Performance Timeline API.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: page_lcp
category:
type: string
const: page
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
allOf:
- $ref: '#/components/schemas/BrowserEventContext'
- type: object
properties:
source_frame_id:
type: string
description: CDP frame identifier of the frame where the LCP element was rendered.
time:
type: number
description: Performance Timeline timestamp of the LCP entry in milliseconds.
lcp_details:
type: object
additionalProperties: false
description: LargestContentfulPaint attributes from the Performance Timeline entry.
properties:
render_time:
type: number
description: Render time of the LCP element in milliseconds; 0 for cross-origin images without Timing-Allow-Origin.
load_time:
type: number
description: Load time of the LCP element in milliseconds.
size:
type: number
description: Visible area of the LCP element in pixels squared.
element_id:
type: string
description: id attribute of the LCP element, if present.
url:
type: string
description: URL of the LCP element for image or video elements.
node_id:
type: integer
description: CDP DOM node identifier of the LCP element.
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserMonitorReconnectedEvent:
type: object
title: monitor_reconnected
description: The CDP connection to Chrome was successfully re-established after a disconnection. Events emitted during the gap are lost. Computed state is reset, so navigation and network tracking restart fresh from this point.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: monitor_reconnected
category:
type: string
const: monitor
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
type: object
additionalProperties: false
properties:
reconnect_duration_ms:
type: integer
format: int64
description: Wall-clock time in milliseconds taken to reconnect after the disconnection.
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserEventContext:
type: object
description: Browser event context stamped by the browser monitor onto all CDP-sourced events. Identifies the target, frame, and navigation epoch in which the event occurred.
properties:
session_id:
type: string
description: CDP session identifier for the target connection.
target_id:
type: string
description: Browser target identifier (stable across navigations within a tab).
target_type:
$ref: '#/components/schemas/BrowserTargetType'
frame_id:
type: string
description: CDP frame identifier within the target.
loader_id:
type: string
description: CDP document loader identifier, reset on each navigation.
url:
type: string
description: URL relevant to this event — page URL for navigation and page events, request URL for network events.
nav_seq:
type: integer
format: int64
description: Monotonically increasing navigation sequence number, incremented on each top-level navigation within the target.
BrowserApiCallEvent:
type: object
description: An agent-driven HTTP call handled by the in-VM API server.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: api_call
category:
type: string
const: control
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
type: object
additionalProperties: false
required:
- request_id
- operation_id
- status
- duration_ms
properties:
request_id:
type: string
description: Per-request identifier from the in-VM API request middleware.
operation_id:
type: string
description: OpenAPI operationId of the matched route (e.g. processExec, takeScreenshot).
status:
type: integer
description: HTTP response status code.
duration_ms:
type: number
description: Wall-clock duration of the handler in milliseconds.
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserPageNavigationEvent:
type: object
title: page_navigation
description: A browser page navigation started event (CDP Page.frameNavigated). Carries nav context fields inline but not nav_seq, as this event resets the navigation epoch.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: page_navigation
category:
type: string
const: page
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
type: object
additionalProperties: false
properties:
url:
type: string
description: URL navigated to.
frame_id:
type: string
description: CDP frame identifier of the navigated frame.
parent_frame_id:
type: string
description: Parent frame identifier for subframe navigations; absent for top-level navigations.
loader_id:
type: string
description: New CDP document loader identifier assigned for this navigation.
session_id:
type: string
description: CDP session identifier.
target_id:
type: string
description: Browser target identifier.
target_type:
$ref: '#/components/schemas/BrowserTargetType'
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserInteractionScrollSettledEvent:
type: object
title: interaction_scroll_settled
description: A browser scroll settled event emitted after scroll position stops changing, captured via injected page script.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: interaction_scroll_settled
category:
type: string
const: interaction
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
allOf:
- $ref: '#/components/schemas/BrowserEventContext'
- type: object
properties:
from_x:
type: integer
description: Scroll x-position at the start of the scroll gesture in CSS pixels.
from_y:
type: integer
description: Scroll y-position at the start of the scroll gesture in CSS pixels.
to_x:
type: integer
description: Final scroll x-position after the gesture settled in CSS pixels.
to_y:
type: integer
description: Final scroll y-position after the gesture settled in CSS pixels.
target_selector:
type: string
description: CSS selector path to the scrolled element.
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserCallStack:
type: object
description: CDP Runtime.StackTrace representing the JavaScript call stack at the time of an event. Fields use CDP naming conventions rather than snake_case to match the Chrome DevTools Protocol wire format.
required:
- callFrames
properties:
description:
type: string
description: Optional label for the stack trace (e.g. async cause).
callFrames:
type: array
description: Ordered list of call frames, outermost first.
items:
type: object
required:
- functionName
- scriptId
- url
- lineNumber
- columnNumber
properties:
functionName:
type: string
description: JavaScript function name, or empty string for anonymous functions.
scriptId:
type: string
description: CDP script identifier.
url:
type: string
description: URL or name of the script file.
lineNumber:
type: integer
description: Zero-based line number within the script.
columnNumber:
type: integer
description: Zero-based column number within the line.
parent:
$ref: '#/components/schemas/BrowserCallStack'
description: Parent stack trace for async stacks.
BrowserMonitorScreenshotEvent:
type: object
title: monitor_screenshot
description: A periodic screenshot of the browser viewport.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: monitor_screenshot
category:
type: string
const: screenshot
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
type: object
additionalProperties: false
properties:
png:
type: string
contentEncoding: base64
description: Base64-encoded PNG screenshot of the browser viewport.
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserConsoleErrorEvent:
type: object
title: console_error
description: 'A browser console error or uncaught JavaScript exception event. Emitted from two distinct CDP sources with different data shapes. Runtime.consoleAPICalled (console.error calls) produces level, text, args, and stack_trace. Runtime.exceptionThrown (uncaught exceptions) produces text, line, column, source_url, and stack_trace. Fields not applicable to the source are absent.
'
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: console_error
category:
type: string
const: console
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
allOf:
- $ref: '#/components/schemas/BrowserEventContext'
- type: object
required:
- text
properties:
text:
type: string
description: 'Human-readable error text, as the browser console would display it. For console.error() calls, the first argument coerced to a string. For uncaught exceptions, the prefix and error message, e.g. "Uncaught Error: boom" or "Uncaught (in promise) TypeError: x is not a function".
'
stack_trace:
$ref: '#/components/schemas/BrowserCallStack'
level:
type: string
description: CDP console type value, always "error". Present only when sourced from Runtime.consoleAPICalled.
args:
type: array
description: All console arguments coerced to strings. Present only when sourced from Runtime.consoleAPICalled.
items:
type: string
line:
type: integer
description: Line number in the script where the exception was thrown. Present only when sourced from Runtime.exceptionThrown.
column:
type: integer
description: Column number in the script where the exception was thrown. Present only when sourced from Runtime.exceptionThrown.
source_url:
type: string
description: URL of the script file that threw the exception. Present only when sourced from Runtime.exceptionThrown.
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserPageLayoutSettledEvent:
type: object
title: page_layout_settled
description: A browser layout settled event emitted 1 second after page load with no intervening layout shifts, indicating visual stability. Each layout shift resets the 1-second timer.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: page_layout_settled
category:
type: string
const: page
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
$ref: '#/components/schemas/BrowserEventContext'
truncated:
type: boolean
description: True if the data field was truncated due to size limits.
BrowserNetworkRequestEvent:
type: object
title: network_request
description: A browser network request sent event.
required:
- ts
- type
- category
- source
properties:
ts:
type: integer
format: int64
description: Event timestamp in Unix microseconds.
type:
type: string
const: network_request
category:
type: string
const: network
source:
$ref: '#/components/schemas/BrowserEventSource'
data:
allOf:
-
# --- truncated at 32 KB (66 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/kernel/refs/heads/main/openapi/kernel-browser-telemetry-api-openapi.yml