Understanding the Vibium Trace Format
The Vibium trace format is a zip of newline-delimited JSON — a timeline, a network HAR stream, and SHA1-named resources — viewable at trace.vibium.dev.
The Vibium trace format is a single zip file that captures a complete timeline of a browser session — screenshots, actions, DOM snapshots, and network traffic — packaged as newline-delimited JSON plus deduplicated binary resources. Inside the zip are three kinds of entries: a .trace file holding the main event timeline, a .network file holding HAR 1.2 entries for every request, and a resources/ folder of screenshots and snapshot images named by their SHA1 hash. Every Vibium command you run — navigate, click, fill, even read-only queries like text — is automatically recorded as a paired before/after marker. You drop the zip onto trace.vibium.dev to scrub through the session frame by frame, and the same format also opens in the standard Playwright trace viewer.
What's inside a trace zip?
A trace zip has a simple, predictable layout. The number prefix is a chunk index — a single start() → stop() run produces chunk 0.
trace.zip
├── 0-trace.trace # main event timeline (newline-delimited JSON)
├── 0-trace.network # network events as HAR entries (NDJSON)
└── resources/
├── a1b2c3d4... # screenshot frames (named by SHA1, no extension)
└── f6a7b8c9... # DOM snapshot images (named by SHA1, no extension)
Resource files have no extension — each is stored under its full lowercase SHA1 hash. That gives you free deduplication: two pixel-identical screenshots share one file, so a long session with a static page stays small.
What events appear in the timeline?
The .trace file is newline-delimited JSON, one self-contained event per line, in chronological order. A handful of event types do all the work.
| Event type | What it captures |
|---|---|
context-options | Always first; session metadata (platform, version, title) |
screencast-frame | A screenshot, referencing an image in resources/ by SHA1 |
frame-snapshot | A structured DOM snapshot for inspecting the page state |
before / after | Paired markers bracketing an action, group, or BiDi command |
event | A raw BiDi browser event (dialogs, log entries, context creation) |
The before/after pairs are the backbone of the timeline. Every Vibium command emits one automatically:
{"type":"before","callId":"call@2","title":"Element.click","class":"Element","method":"vibium:click","params":{"selector":"#login"},"startTime":1708000000500}
{"type":"after","callId":"call@2","endTime":1708000000600}The shared call@N id links the start and end, and N is a monotonic counter across actions, groups, and protocol commands — so the viewer can reconstruct exactly what ran and how long it took.
How is network traffic stored?
Network data lives in its own .network file, separate from the action timeline. Each line is a resource-snapshot wrapping a HAR 1.2 entry — the same structure browsers export from DevTools. Vibium correlates the raw BiDi network events (network.beforeRequestSent, network.responseCompleted, network.fetchError) by request id and transforms them into clean request/response pairs during recording.
{"type":"resource-snapshot","snapshot":{"request":{"method":"GET","url":"https://example.com/"},"response":{"status":200,"content":{"size":1234,"mimeType":"text/html"}},"timings":{"send":-1,"wait":45,"receive":-1}}}Failed requests get status: 0 and a _failureText field. Because the file is standard HAR, it renders as a waterfall in both the Vibium and Playwright viewers.
How do I record a trace?
Tracing lives on the browser context, and the quickest path is page.context.tracing. Enable screenshots for a visual filmstrip and snapshots to capture the DOM on stop. Here is the JavaScript flow:
const { browser } = require('vibium')
async function main() {
const bro = await browser.launch()
const vibe = await bro.page()
await vibe.context.tracing.start({ screenshots: true, snapshots: true })
await vibe.go('https://example.com')
await vibe.find('a').click()
await vibe.context.tracing.stop({ path: 'trace.zip' })
await bro.close()
}
main()stop() writes the zip to path, or returns the bytes if you omit it. You can also drive tracing from the CLI in daemon mode:
vibium trace start --screenshots --snapshots --name my-session
vibium go https://example.com
vibium trace stop -o trace.zipWhat are action groups, chunks, and bidi mode?
Three options shape what ends up in the trace, and each maps to a real field in the format. Action groups (startGroup() / stopGroup()) wrap several actions under one labeled span — they appear as nestable before/after markers, and child actions carry a parentId. Chunks (stopChunk() / startChunk()) split a long session into multiple zips without stopping recording; each chunk gets its own context-options header and index. BiDi mode (start({ bidi: true })) additionally records every raw WebDriver BiDi command sent to the browser, nested inside the parent action — invaluable for debugging low-level protocol issues, at the cost of a larger trace.
How do I view and debug a trace?
Open trace.vibium.dev and drag your trace.zip onto the page. The viewer gives you four synchronized panels: a timeline to scrub the screenshot filmstrip, an actions list (with group spans and, in bidi mode, nested protocol calls), a network waterfall, and DOM snapshots you can inspect at any point. Click an action and the filmstrip jumps to that moment — the fastest way to see exactly why a click missed or a fill landed in the wrong field. This pairs naturally with Vibium's auto-wait: if an action timed out, the trace shows you the page state it was waiting on.
Next steps
Frequently asked questions
What is the Vibium trace format?
A Vibium trace is a single zip file containing a timeline of newline-delimited JSON events (screenshots, actions, DOM snapshots), a separate network file of HAR entries, and a resources folder of binary assets named by SHA1 hash. You open it at trace.vibium.dev to scrub through a session.
What's inside a Vibium trace zip?
A trace zip has three parts: a .trace file with the main event timeline, a .network file with HAR 1.2 entries for every request, and a resources/ folder holding screenshots and snapshot images named by their SHA1 hash. Identical frames are deduplicated, so the zip stays compact.
How do I view a Vibium trace?
Go to trace.vibium.dev and drop your trace.zip onto the page. The viewer renders a timeline with a screenshot filmstrip, an action list, a network waterfall, and DOM snapshots. The format is also compatible with the standard Playwright trace viewer.
Vibium is created by Jason Huggins. This is an independent tutorial — see the official Vibium site and GitHub repo for canonical docs.
Related guides
WebDriver BiDi vs CDP: What's the Difference?
WebDriver BiDi vs CDP: both are bidirectional protocols, but BiDi is a cross-browser W3C standard while CDP is Chrome-specific and vendor-controlled.
4 min read→Concepts & InternalsEvent-Driven Browser Automation with Vibium
Event-driven browser automation with Vibium uses WebDriver BiDi's pushed events for auto-waiting, console capture, and reliable scripts without sleeps.
4 min read→Concepts & InternalsHow Vibium's Actionability (Auto-Wait) Works
Vibium's actionability auto-wait runs checks (visible, stable, receives events, enabled, editable) server-side in Go before each action — skip sleeps.
4 min read→Concepts & InternalsSelf-Healing Locators in Vibium, Explained
Vibium has no bolt-on self-healing locator engine — it earns resilience via semantic selectors, accessibility-tree finding, pickBest, and auto-wait.
4 min read→