Realtime protocol v1 used by the dashboard for live feeds, the screencast and takeover input. Generated from @browserhive/contracts/ws. Available when --admin is on.
URL: ws://<host>:<port>/api/v1/ws (same port as everything else).
Subprotocol: Sec-WebSocket-Protocol: browserhive.v1.
Authentication: the dashboard session cookie or Authorization: Bearer <token>, checked at upgrade. A failed check completes the upgrade and closes immediately with 4401, so browsers see the code.
The first server frame is a reply with payload type: "hello", carrying epoch and the current cursor. epoch changes on every server start; a cursor from another epoch cannot be replayed.
Every server text frame is JSON:
{ v : 1 , kind : "event" | "reply" | "error" | "stream" , seq : number, ts : number, topic ?: string, corr ?: string, payload : unknown }
kind
Meaning
event
ordered, replayable feed event on a topic (has topic and seq)
reply
answer to a client command (echoes corr); also the first hello frame
error
command failure or protocol violation; the socket stays open
stream
screencast control message on screencast:<id>; latest-wins, never replayed
Client frames are JSON objects discriminated on type (see client commands ); any command may carry corr (1–64 characters), which is echoed on its reply or error.
Limit
Value
maxInboundFrameBytes
16KiB
maxProtocolViolations
5
feedBufferCount
10000
feedBufferBytes
8MiB
feedBufferMs
5m
heartbeatMs
20s
staleMs
1m
tickMs
30s
overloadBytes
4MiB
overloadGraceMs
10s
screencastDropBytes
1MiB
Code
Name
Meaning
4401
UNAUTHORIZED
not authenticated or the session expired; log in again
4403
PASSWORD_CHANGE_REQUIRED
the operator must change the password first
4400
PROTOCOL_ERROR
too many malformed frames
4406
BAD_SUBPROTOCOL
missing or unknown Sec-WebSocket-Protocol (expected browserhive.v1)
1013
OVERLOADED
the client did not read fast enough (backpressure limit exceeded)
1001
GOING_AWAY
server shutting down, or the socket was silent too long
type
Fields
Scope
ping
—
any authenticated caller
subscribe
topic: string, cursor?: integer
any authenticated caller
unsubscribe
topic: string
any authenticated caller
screencast.start
session_id: string, max_width?: integer, max_height?: integer, quality?: integer
sessions:read
screencast.stop
session_id: string
sessions:read
screencast.set_size
session_id: string, max_width: integer, max_height: integer
sessions:read
input
session_id: string, input: object
sessions:takeover
session.set_viewport
session_id: string, width: integer, height: integer
sessions:write
logs.tail
level?: one of error, warn, info, debug, trace, module?: string
logs:read
input is accepted only while an attention request is open for the session and is re-checked on every message (INPUT_NOT_PERMITTED otherwise). session.set_viewport is an observability control and is not attention-gated.
Field names follow the Chrome DevTools Protocol (camelCase). modifiers is a bitmask: Alt=1, Ctrl=2, Meta=4, Shift=8.
Field
Type
Required
Constraints
type
"mouse"
yes
—
action
one of mouseMoved, mousePressed, mouseReleased, mouseWheel
yes
—
x
number
yes
≥ 0; ≤ 100000
y
number
yes
≥ 0; ≤ 100000
button
one of none, left, middle, right
no
—
clickCount
integer
no
≥ 0; ≤ 8
deltaX
number
no
≥ -10000; ≤ 10000
deltaY
number
no
≥ -10000; ≤ 10000
modifiers
integer
no
≥ 0; ≤ 15
Field
Type
Required
Constraints
type
"key"
yes
—
action
one of keyDown, keyUp, char, rawKeyDown
yes
—
key
string
no
max length 32
code
string
no
max length 64
text
string
no
max length 16
windowsVirtualKeyCode
integer
no
≥ 0; ≤ 255
modifiers
integer
no
≥ 0; ≤ 15
Field
Type
Required
Constraints
type
"touch"
yes
—
action
one of touchStart, touchEnd, touchMove, touchCancel
yes
—
points
object[]
yes
at most 10 items; each item: keys x, y, radiusX, radiusY, force, id
modifiers
integer
no
≥ 0; ≤ 15
payload type
Fields
hello
protocol: "browserhive.v1", protocol_version: 1, epoch: string, cursor: integer, server_version: string, now: integer
subscribed
topic: string, from: integer, to: integer, complete: boolean
unsubscribed
topic: string, ok: boolean
pong
ts: integer
screencast.started
topic: string, ordinal: integer
ok
result?: any
resync_required
topic?: string, reason: one of cursor_expired, epoch_changed, buffer_overflow
Subscribe with { "type": "subscribe", "topic": "<topic>", "cursor"?: <last seq> }. The reply subscribed { from, to, complete } says whether the replay was complete; complete: false (or resync_required) means reload from REST.
Topic
Scope
Events
sessions
sessions:read
session.opened , session.updated , session.closed , session.removed
attention
attention:read
attention.created , attention.resolved
vault.confirm
vault:read
vault.confirm.created , vault.confirm.resolved
vault.config
vault:read
vault.binding.changed , vault.policy.changed , vault.lock_state
vault.access
vault:read
vault.access
pages
sessions:read
page.visited
blocklist
blocklist:read
blocklist.hit , blocklist.reloaded
system
system:read
system.degraded , system.recovered , system.tick , system.capacity , retention.completed
logs
logs:read
log.record
notifications
notifications:read
notification.created , notification.updated
session:<id>
sessions:read
session.opened , session.updated , session.closed , session.removed , session.warning , tool.called , page.visited , screenshot.captured , vault.access , blocklist.hit , attention.created , attention.resolved , vault.confirm.created , vault.confirm.resolved
screencast:<id>
sessions:read
stream messages meta, started, stopped, failed and binary frames
Payloads of kind: "event" frames, discriminated on type. DTO fields (session, row, request, …) are the same shapes the REST API returns.
Field
Type
Required
Constraints
session
object
yes
keys session_id, slug, owner, tenant_id, channel, engine, headless, incognito, persistence_mode, current_url, created_at, last_activity_at, closed_at, closed_reason, archived_at, lease_expires_at, lease_paused_at, lease_remaining_ms, state, live, disable_evaluate, vault_enabled, stealth, fingerprint, humanize, stealth_recorded, identity, proxy_label, counts, has_live_viewers, client
Field
Type
Required
Constraints
session
object
yes
keys session_id, slug, owner, tenant_id, channel, engine, headless, incognito, persistence_mode, current_url, created_at, last_activity_at, closed_at, closed_reason, archived_at, lease_expires_at, lease_paused_at, lease_remaining_ms, state, live, disable_evaluate, vault_enabled, stealth, fingerprint, humanize, stealth_recorded, identity, proxy_label, counts, has_live_viewers, client
Field
Type
Required
Constraints
session_id
string
yes
pattern ^([a-z][a-z0-9-]{1,31})-([0-9a-z]{8})$
closed_at
integer
yes
≥ 0
reason
one of user, operator, lease_expired, crash, shutdown, interrupted, launch_failed
yes
—
Field
Type
Required
Constraints
session_id
string
yes
pattern ^([a-z][a-z0-9-]{1,31})-([0-9a-z]{8})$
action
one of archived, unarchived, deleted
yes
—
at
integer
yes
≥ 0
Field
Type
Required
Constraints
session_id
string
yes
pattern ^([a-z][a-z0-9-]{1,31})-([0-9a-z]{8})$
code
string
yes
—
message
string
yes
—
details
any
no
—
Field
Type
Required
Constraints
row
object
yes
keys event_id, session_id, tool, tab_id, ok, error_code, error_message, duration_ms, result_size_bytes, ts, trace_id, has_screenshot, args_json, result_text
has_detail
boolean
yes
—
Field
Type
Required
Constraints
row
object
yes
keys event_id, session_id, tab_id, url, title, domain, category, ts
Field
Type
Required
Constraints
row
object
yes
keys event_id, session_id, tool, kind, content_type, width, height, size_bytes, ts, url
Field
Type
Required
Constraints
row
object
yes
keys event_id, session_id, session_slug, tool_event_id, entry_name, handle, result, reason, evaluate_enabled, page_url, origin_check, principal_id, details, ts
Field
Type
Required
Constraints
row
object
yes
keys event_id, session_id, session_slug, tool_event_id, url, domain, pattern, source, tool, ts
Field
Type
Required
Constraints
request
object
yes
keys request_id, kind, session_id, session_slug, owner, reason, mode, options, status, message, resolved_by, resolution_reason, created_at, resolved_at, deadline_at, waited_ms, page_url, tool, event_id, entry_name
Field
Type
Required
Constraints
request
object
yes
keys request_id, kind, session_id, session_slug, owner, reason, mode, options, status, message, resolved_by, resolution_reason, created_at, resolved_at, deadline_at, waited_ms, page_url, tool, event_id, entry_name
Field
Type
Required
Constraints
request
object
yes
keys request_id, kind, session_id, session_slug, owner, reason, mode, options, status, message, resolved_by, resolution_reason, created_at, resolved_at, deadline_at, waited_ms, page_url, tool, event_id, entry_name
Field
Type
Required
Constraints
request
object
yes
keys request_id, kind, session_id, session_slug, owner, reason, mode, options, status, message, resolved_by, resolution_reason, created_at, resolved_at, deadline_at, waited_ms, page_url, tool, event_id, entry_name
Field
Type
Required
Constraints
handle
string
yes
pattern ^[a-z0-9][a-z0-9._-]{0,127}$
action
one of created, updated, removed
yes
—
Field
Type
Required
Constraints
group_id
string or null
yes
—
Field
Type
Required
Constraints
unlocked
boolean
yes
—
Field
Type
Required
Constraints
patterns
integer
yes
≥ 0
skipped
integer
yes
≥ 0
loaded_at
integer
yes
≥ 0
Field
Type
Required
Constraints
event
object
yes
keys event_id, code, severity, message, details, first_seen_at, last_seen_at, count, resolved_at
Field
Type
Required
Constraints
event
object
yes
keys event_id, code, severity, message, details, first_seen_at, last_seen_at, count, resolved_at
Field
Type
Required
Constraints
now
integer
yes
≥ 0
Field
Type
Required
Constraints
live
integer
yes
≥ 0
max
integer or null
yes
—
Field
Type
Required
Constraints
at
integer
yes
≥ 0
pruned_rows
integer
yes
≥ 0
result
one of ok, partial, failed
yes
—
severity
one of info, warn, error
no
—
Field
Type
Required
Constraints
notification
object
yes
keys notification_id, principal_id, type, title, body, session_id, session_slug, target, source_event_id, created_at, updated_at, count, read_at, dismissed_at
Field
Type
Required
Constraints
notification
object
yes
keys notification_id, principal_id, type, title, body, session_id, session_slug, target, source_event_id, created_at, updated_at, count, read_at, dismissed_at
Field
Type
Required
Constraints
record
object
yes
keys seq, ts, level, msg, module, trace_id, span_id, request_id, session_id, principal, transport, err; additional keys allowed
Start with screencast.start { session_id, max_width?, max_height?, quality? }; the reply screencast.started carries the ordinal that tags this screencast’s binary frames. Frames are latest-wins and dropped under backpressure; each viewer may request its own size with screencast.set_size.
type
Fields
meta
session_id: string, ordinal: integer, device_width: integer, device_height: integer, page_scale: number, offset_top: number
started
session_id: string, ordinal: integer
stopped
session_id: string, reason: one of stopped, session_closed, session_crashed, connection_closed
failed
session_id: string, code: string, message?: string
Each binary frame is a 16-byte big-endian header followed by the JPEG bytes.
Offset
Field
Encoding
0
magic
4 ASCII bytes BHSC
4
ordinal
u32
8
seq
u32 (monotonic per screencast; a lower seq after a higher one is dropped)
12
width
u16 (JPEG width)
14
height
u16 (JPEG height)