# What the recorders capture (https://docs.vitrinka.ai/qa/recorder/protocol)



## Recording data [#contract]

This page describes the recording flow. The browser extension is maintained in the vitrinka repository; the Expo SDK and the web recorder (`@vitrinka/web`) are maintained in the kit repository. Their capture methods differ, as shown below.

## Where data goes [#where]

Recording data is uploaded to the vitrinka server you configure. Software updates and downloads use separate distribution services; this is not a claim that the application makes no other network requests.

```http
GET    /api/v1/recorder/policy      recording and masking settings
GET    /api/v1/recorder/me          who the recorder records as, and its HUD preferences
PATCH  /api/v1/recorder/me          save the HUD preferences (size, verbose)
POST   /api/v1/sessions/:id/chunk   rrweb chunks (with a seq query parameter)
POST   /api/v1/sessions             create a recording session
POST   /api/v1/sessions/:id/events  the event stream (batched)
POST   /api/v1/sessions/:id/shot    screenshot keyframes
POST   /api/v1/sessions/:id/tags    tags on the session
PATCH  /api/v1/sessions/:id         status (recording | paused | done)
GET    /api/v1/sessions/:id         the session's own row, to reconcile
```

<Callout type="warn">
  These are the recording endpoints. Setup, pairing, listing and resuming sessions also use the server API.
</Callout>

## Credentials [#credentials]

A recorder carries a `vkr_` recorder token, and that token reaches only the endpoints above — the policy, its own record, creating a session, and, on a session that same token started, its capture leaves, tags, status and read-back. It never lists sessions, reads a session's events or replay, reads a board or touches tasks, and it never reads, closes or writes into a session another credential started — a member's, another project's, or one another recorder token started, even one linked by the same person. Such a call answers `403` with the fix: start a new session (an admin-minted key asking for another project's session gets `404`). A leaked token records into its workspace and reads back nothing but the status of the sessions it started. After a recorder is linked again, and across the upgrade that brought this rule, a session started under the old token cannot be continued; start a new one. A token is either linked from a device by approving a short code (bound to the person, expiring 30 days after its last use) or minted by an admin for one project, for unattended builds nobody can link by hand. The browser extension can also use a `vkp_` personal token. Tokens are listed and revocable under **Settings → Tokens**.

## When recording happens [#when]

Only during a session you explicitly start — and for Expo, only in a build that was allowed to carry the recorder at all.

* **Expo — compile time** — the recorder exists only in builds whose profile the config plugin allowlists and that set `EXPO_PUBLIC_VITRINKA_URL`; every other build strips it from the bundle. No token is baked in: the tester links the device, and only an unattended build carries an admin-minted recorder key.
* **Expo — run time** — inside an enabled build, capture runs only between you pressing record and stop. A machine-driven session started over the Expo devtools channel shows a visible HUD indicator.
* **Web — scoped** — the recorder mounts only when its `url` is set, and records only on a page whose host matches a project domain rule; a production rule refuses it unless the rule opts in (Settings → Projects → Routing → in-app recorder).
* **Browser — scoped** — capture runs only in tabs matching the project's configured domains, and only while a session you started is live. The popup always shows the recording state.

## What is captured, per session [#what]

| Channel      | Expo recorder                                                      | Web recorder                                                                                             | Browser extension                                                          |
| ------------ | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Screenshots  | Keyframes on navigation and touch, throttled.                      | None — the rrweb DOM stream, inputs masked, is the keyframe.                                             | Keyframes plus an rrweb DOM stream.                                        |
| Interactions | Tap coordinates, the pressed element's label, and the route.       | Clicks with the element's short selector, its rectangle and a redacted text snippet; every route change. | Clicks and navigation.                                                     |
| Network      | Method, URL, status, duration, and capped request/response bodies. | Fetch and XHR calls, headers, URLs and bodies passed through the same redaction as the Expo recorder.    | API calls including bodies, via CDP.                                       |
| Console      | Errors and warnings.                                               | Errors and unhandled rejections.                                                                         | Errors.                                                                    |
| Notes        | Notes you type in the HUD.                                         | Notes and annotations, on an element or a dragged region.                                                | Notes and ⌖ snaps typed in the on-page HUD (`Alt+Shift+N`, `Alt+Shift+A`). |

## Redaction [#redaction]

With the default policy, recorders mask sensitive network fields before upload. The server also applies its policy when it receives events. Coverage depends on the recorder and the data format; see [Recorder redaction](/security/redaction) for policy settings and exceptions.

* **What counts as secret** — `password`, `token`, `authorization`, `cookie`, `apikey`, and multi-word forms like `accessToken` or `refreshToken`.
* **Workspace policy** — the recorders fetch masking settings from `GET /api/v1/recorder/policy`. Administrators can add patterns for their application's data.

<Callout type="warn">
  **Do not rely on masking to remove every sensitive detail from screenshots or page content.** Text masking and image handling vary by recorder and settings. Use test data when recording.
</Callout>

## Retention and access [#retention]

Recorded sessions live on your vitrinka server, under its access rules. The recorders themselves keep only an undelivered upload tail on the device, which is removed once it is delivered or the session is discarded.
