Skip to content

File Format (.pro)

A .pro file is a JSON-encoded snapshot of captured traffic. Probe writes one when you export: a saved session from View → Sessions → Export, or requests from a row's or a selection's Export menu. Saving a session stores it in Probe's local database (~/.probe/probe.db), not as a file. Earlier versions of Probe saved the same file shape as .gmp; both extensions are still accepted on import.

Probe also writes two related shapes — collection exports for a multi-entry export and request exports for a single entry. The importer routes by the JSON format field, not the file extension.

The first key tells the importer what's inside:

{
"format": "guide-session" | "guide-collection" | "guide-request",
"version": 1,
...
}

Probe trusts the format value over the extension — you can rename a file from .json to .pro (or vice-versa) and import will still work.

The full snapshot a saved tab produces. Saved sessions themselves live in Probe's local database (~/.probe/probe.db); this JSON is the interchange shape that Export writes to a path you choose and Import reads back.

{
"format": "guide-session",
"version": 1,
"id": "1731081900123",
"name": "Auth flow — staging",
"createdAt": 1731081900123,
"entries": [
{ /* LogEntry */ },
{ /* LogEntry */ }
]
}
FieldTypeDescription
formatstringMust be "guide-session".
versioninteger1 today. Bumped on a breaking format change.
idstringSession id: the save time in milliseconds, as a string. Two sessions saved in the same millisecond get a _1-style suffix.
namestringDisplay name. Editable via the Sessions manager.
createdAtintegerMilliseconds since epoch, UTC.
entriesarrayOne LogEntry per captured request.

The export format for a multi-entry export (right-click on selected rows → Export).

{
"format": "guide-collection",
"version": 1,
"exportedAt": 1731082000000,
"entries": [ /* LogEntry, ... */ ]
}

Same entries shape as a session, without the session-level id and name. On import, the entries are added to the session tab you have open — or, when that's a saved (read-only) tab, to the recording tab — and Probe switches to that tab, even from a Composer or Files tab. The tab gets the unsaved marker, so save it to keep the import.

A single-entry export. Useful for sharing one request without surrounding noise. It imports like a one-entry collection.

{
"format": "guide-request",
"version": 1,
"entry": { /* LogEntry */ }
}

The same LogEntry JSON appears inside every format above:

{
"id": 142,
"method": "POST",
"url": "https://api.example.com/v1/users",
"statusCode": 201,
"timestamp": 1731081900123,
"clientAddr": "Chrome",
"reqHeaders": {
"content-type": "application/json",
"authorization": "Bearer ..."
},
"reqBody": "{\"name\":\"Ada\"}",
"resHeaders": {
"content-type": "application/json",
"content-length": "21"
},
"resBody": "{\"id\":1,\"name\":\"Ada\"}",
"contentType": "application/json",
"durationMs": 184,
"reqSize": 124,
"resSize": 21,
"requestEndTs": 1731081900140,
"responseStartTs": 1731081900290,
"httpVersion": "HTTP/1.1"
}
FieldTypeNotes
idintegerUnique per session. Imported request and collection entries get new ids (negative numbers, shown as #-1, #-2, …) so they never collide with traffic captured live.
methodstringHTTP method.
urlstringFull URL the client sent. MITM-intercepted entries carry the explicit :443/:80 port.
statusCodeinteger0 if no response was received (request errored mid-flight or was aborted).
timestampintegerMilliseconds since epoch, UTC.
clientAddrstringProcess name for loopback traffic, IP address for remote phones. May be empty.
reqHeadersobjectLower-cased keys, single value per key.
reqBodystring | nullRaw body as text. A non-text or oversized body is replaced by a short placeholder in square brackets, such as [binary 2048 bytes] or [body too large: 12582912 bytes, not shown].
resHeadersobjectSame conventions as reqHeaders.
resBodystring | nullSame conventions as reqBody.
contentTypestring | nullSniffed from the response.
durationMsinteger | nullTotal request → response time.
reqSizeintegerBytes-on-the-wire estimate of the request.
resSizeintegerBytes-on-the-wire estimate of the response.
requestEndTsinteger | nullMilliseconds since epoch, UTC, when Probe had the whole request body. Missing in files from older versions.
responseStartTsinteger | nullMilliseconds since epoch, UTC, when the first response byte arrived. Missing in files from older versions.
httpVersionstringProtocol version, such as HTTP/1.1 or HTTP/2.0. Empty when unknown.

Only id, method, url and timestamp are required. Other fields may be missing — LogEntry.fromJson fills in defaults (statusCode 0, no headers, sizes 0) — and fields it doesn't know are ignored, so a file from a newer version of Probe still loads in an older one.

  • .gmp files — same JSON shape, accepted by every importer. Probe writes .pro for new exports.
  • .json files — accepted; the importer sniffs format.
  • Renamed extensions — fine. Content-sniffing wins over the extension.
  • No request/response that was already discarded for size — bodies stripped at capture time stay stripped. Sessions are wire-level, not browser-level.
  • No HAR support today. Probe doesn't read or write HAR.
  • No environment data, scripts, breakpoints, or rules. A .pro only carries traffic. Compose collections (with environments and scripts) live separately under ~/.probe/compose/<collection-id>.json.
  • Sessions — the user-facing feature this format underpins.
  • Internal REST API — fetch saved sessions via /api/v1/session-tabs/saved/{id}.