Skip to content

Bundle format

This page documents the capture bundle format for contributors and advanced users who want to understand or manipulate bundles directly.

A capture bundle contains network traces, WebSocket data, UI context events, and a timeline that ties everything together. The Chrome extension exports bundles as ZIP files; internally, managed storage stores them as flat directories with the same layout. The format was designed specifically for Spectral because existing formats like HAR have significant limitations:

  • HAR is JSON/UTF-8 only — no native binary support (would need base64 encoding, adding 33% overhead)
  • HAR has no standard WebSocket support (Chrome uses non-standard _webSocketMessages)
  • HAR has no concept of UI context or unique trace IDs for cross-referencing
  • HAR’s request/response pair model doesn’t fit WebSocket’s async full-duplex messaging
PathContents
manifest.jsonSession metadata: capture ID, timestamps, app info, browser info, statistics
traces/t_NNNN.jsonHTTP trace metadata: method, URL, headers, status, timing, initiator, context refs
traces/t_NNNN_request.binRaw request body (binary-safe, may be empty)
traces/t_NNNN_response.binRaw response body (binary-safe, may be empty)
ws/ws_NNNN.jsonWebSocket connection metadata: URL, handshake ref, protocols, message count
ws/ws_NNNN_mNNN.binWebSocket message payload (binary-safe)
ws/ws_NNNN_mNNN.jsonWebSocket message metadata: direction, opcode, timestamp, connection ref
contexts/c_NNNN.jsonUI context event: action type, element info, page URL, page content snapshot
timeline.jsonOrdered list of all events with timestamps and cross-references

The manifest contains session-level metadata:

FieldTypeDescription
format_versionstringBundle format version (currently 1.0.0)
capture_idstringUnique session identifier (UUID)
created_atstringISO 8601 timestamp
app.namestringApplication name
app.base_urlstringApplication base URL
app.titlestringPage title at capture start
browser.namestringBrowser name
browser.versionstringBrowser version
extension_versionstringExtension version
capture_methodstringHow the capture was produced: chrome_extension, proxy, or merged
duration_msintegerCapture duration in milliseconds
statsobjectCounts: trace_count, ws_connection_count, ws_message_count, context_count

Each trace has a stable string ID (t_NNNN) used for cross-referencing from contexts, timeline, and analysis output.

FieldDescription
idTrace identifier
timestampEpoch milliseconds
typeAlways http
request.methodHTTP method
request.urlFull URL
request.headersArray of {name, value} objects (arrays, not objects, because HTTP allows duplicate header names)
request.body_filePath to the companion .bin file
request.body_sizeBody size in bytes
request.body_encodingBody encoding if applicable (e.g., base64), or null
response.statusHTTP status code
response.status_textHTTP status text (e.g., OK, Not Found)
response.headersArray of {name, value} objects
response.body_filePath to the companion .bin file
response.body_sizeBody size in bytes
response.body_encodingBody encoding if applicable, or null
timingBreakdown: dns_ms, connect_ms, tls_ms, send_ms, wait_ms, receive_ms, total_ms
initiatorWhat triggered the request: type (script, parser, etc.), URL, line number
context_refsArray of context IDs active when this trace was captured

Bodies are stored as separate binary files rather than inline JSON to avoid encoding overhead and preserve binary fidelity.

WebSocket connections have a metadata file with the connection URL, handshake trace reference, negotiated protocols, message count, and context refs. Each message has its own metadata file (direction, opcode, timestamp, context refs) and a binary payload file.

Opcode valuesMeaning
textText frame (UTF-8)
binaryBinary frame
pingPing control frame
pongPong control frame
closeConnection close frame

Direction is send (client to server) or receive (server to client).

Each context event captures what the user did and the state of the page at that moment.

ActionWhat is recorded
clickElement details (tag, text, attributes, CSS selector, XPath), page URL, page content
inputField identity only (not the typed value, for privacy)
submitForm target element
scrollScroll position change
navigateNew URL (SPA navigation via pushState/replaceState/popstate)

Each context event also includes viewport information (width, height, scroll position).

The page content snapshot includes visible headings (up to 10), navigation links (up to 15), main text content (up to 500 characters), forms with field identifiers (up to 5), table headers (up to 5), and alerts/notifications (up to 5).

The timeline is a flat ordered list of all events across traces, WebSocket activity, and context events. Each entry has a timestamp, an event type, and a reference to the corresponding item.

Event typeReference
contextContext ID (e.g., c_0001)
traceTrace ID (e.g., t_0001)
ws_openWebSocket connection ID (e.g., ws_0001)
ws_messageWebSocket message ID (e.g., ws_0001_m001)

The flat timeline makes correlation straightforward: to find which API calls relate to a UI action, scan forward from the context event within a time window.

The Chrome extension converts Chrome DevTools Protocol timestamps (monotonic seconds since browser start) to epoch milliseconds. An offset is computed from the first event (Date.now() - chromeTimestamp * 1000) and applied consistently to all subsequent events. The MITM proxy uses wall-clock timestamps directly.