Session Replay reference
Replay is configured through the RUM application and its recording rules, not through its own object.
Activation
Section titled “Activation”Replay records only for sessions matching a Replay recording rule. While a Replay rule could still match, the SDK buffers the last 60 to 120 seconds in memory, and a match sends that buffer before streaming; see replay buffer and privacy. Once replay activates for a session it stays on for the rest of that session, in every tab and across page loads.
| Setting | Where | Default | Description |
|---|---|---|---|
capture | Recording rule | required | replay records a replay when the rule matches. |
sample_rate, auto_sample | Recording rule | 1, false | Share of matching sessions; Auto follows the replay quota. |
min_duration_ms, require_interaction | Recording rule | 3000, true for Replay | Gates before upload, bypassed by error conditions. |
enabled | Recording rule | true | Disabled rules are never applied. |
Privacy settings
Section titled “Privacy settings”Set on the RUM application under settings.privacy and delivered to the SDK with its config. Change them with PATCH /rum/{app_id}, sending only the keys you change; it needs an account admin or an API key with no scope restriction. A privacy level writes these flags for you:
| Field | Documented default | Effect |
|---|---|---|
mask_inputs | true | Masks all input values in the recording (rrweb maskAllInputs). Any privacy level masks inputs whatever this flag says. |
mask_text | false | Masks all user-visible text in the recording. Strict masks text whatever this flag says. |
settings.privacy also carries the privacy level, the personal data patterns, the per-element selectors (mask_selectors, unmask_selectors, block_selectors, ignore_input_selectors) and never_record_urls; see replay privacy. It also carries hide_action_text, which is not a replay setting.
With mask_text off and below Strict, user-visible page text is recorded (Balanced scrubs emails, card numbers and long digit runs from it). Turn it on, choose Strict, or add mask_selectors if the recorded pages render anything you would not want in a recording.
Segment mechanics
Section titled “Segment mechanics”The SDK records with rrweb, in a separate chunk loaded only for sessions a Replay rule has matched or could still match. Every tab records its own window, and each page load is its own stream of segments:
- A segment closes at 20 seconds or about 2.5 MB of JSON, and when the tab is hidden. A page’s first full snapshot is sent at once.
- Segments are numbered from 0 per page load (
q) and carry the session, window and page load IDs, the event range and, on the last one, a final marker. - Each segment is a JSON array of rrweb events, gzipped where the browser can, sent to
POST https://in-replay.siteqwality.com/v2/segmentswith the client token inAuthorizationand the index in thex-sq-replay-indexheader. - A failed upload is retried with backoff, and a
Retry-Afterholds every send. A retried upload with the same content is accepted and not stored again. See replay transport for the full contract.
Who can watch a replay
Section titled “Who can watch a replay”A replay shows what a user saw, so reading one needs more than read access to RUM.
| Caller | Needs |
|---|---|
| Team member | The account’s replay access level: Members (default) lets any member watch, Admins only admins and super admins. Viewers and auditors never can. |
| API key or M2M client | The read:rum_replay scope, plus read:rum. A key with no scope list does not get replays: add both scopes. |
| AI assistant | Never. The MCP server does not expose replay content. |
Change the access level with PUT /rum/settings (account admins only), sending only the fields you change:
{ "replay_access": "admins", "body_access": "members" }body_access sets the same rule for network bodies, headers and console arguments. GET /rum/settings returns both.
Callers without access get a 403. An application outside your account returns 404.
Retrieval
Section titled “Retrieval”The player loads a replay in two steps: a manifest that lists every piece without URLs, then short-lived URLs for the pieces it is about to play.
Manifest
Section titled “Manifest”GET /rum/{app_id}/sessions/{session_id}/replay:
| Field | Description |
|---|---|
status | ready (all compacted), live (a segment arrived in the last 2 minutes on a page still open: poll every 5 seconds), processing (some page loads are still raw segments; they play, and are compacted within about 35 minutes) or none. |
reason | With none, why nothing was recorded, when the SDK reported it: not_sampled, no_rule, consent, quota, privacy_url, too_large or opted_out. |
start_ms, end_ms | First and last recorded event, Unix milliseconds. |
active_ms, activity | Time with user input, and the [start, end] ranges it falls in, for skipping inactivity. |
windows[] | One per browser tab: window_id, index (0 for the tab that recorded first) and its page_loads[]. |
page_loads[] | One per document: page_load_id, url (minimized), start_ms, end_ms and its chunks[] in playback order. |
chunks[] | id (opaque), kind (block or segment), start_ms, end_ms, bytes, and snapshot (playback can start here). |
Chunk URLs
Section titled “Chunk URLs”POST /rum/{app_id}/sessions/{session_id}/replay/chunks with {"ids": [...]}, at most 20 ids, returns one entry per id found (unknown ids are left out):
| Field | Description |
|---|---|
id, kind | The id asked for, and block, segment or stylesheet. |
url | Presigned GET URL. |
range | For blocks: send it as the Range header. |
expires_in | 120 seconds. On a 403 from storage, ask for the URL again. |
Keep ids opaque and use the range returned with each URL. If a chunk id is missing from the response, refresh the manifest before retrying. Issued URLs stay valid through recompaction until they expire.
How to play each kind:
block: a compacted block, one gzip stream holding a JSON array of rrweb events. Gunzip it yourself; the response has noContent-Encoding. Every block starts with Meta and a full snapshot and plays on its own. When you continue from the previous block of the same page load, skip the new block’s leading Meta and full snapshot events and every event marked"sqk": 1: they only rebuild the state the player already has.stylesheet: plain CSS. A block’s_cssTextattribute or style text that readssq-css:<hash>names one: requestcss:<hash>with the block’s other ids and swap in its text before handing events to rrweb.segment: a raw segment, a JSON array of rrweb events as the SDK sent it: gzip, or plain JSON for an uncompressed tail sent at page close. Check for the gzip header before unpacking.
Compaction
Section titled “Compaction”About 30 minutes after a page load goes quiet (2 minutes once the SDK marks it ended), its segments are compacted into blocks. Compaction applies the application’s current privacy settings and selectors again on the server; changing settings later does not recompact existing blocks. It moves stylesheets of 1 KB or more into a shared store and adds a full snapshot about every megabyte, so seeking never replays the whole page load. Raw segments stay until their retention ends.
Who watched
Section titled “Who watched”Every replay view is written to the audit log as rum.replay.viewed, with target_kind rum_session and the session as target_id, at most once per viewer per 30 minutes. Whenever the manifest or the chunk URLs return something to play, the view is recorded first; if it cannot be recorded, the request fails with a 500 and returns no content.
GET /rum/{app_id}/sessions/{session_id}/viewers lists who watched over the last 90 days, most recent first: actor_type, the person or key (user_id, email, api_key_id, api_key_name, m2m_client_id), first_viewed_at, last_viewed_at and views.
Replay links
Section titled “Replay links”The dashboard player opens at a given moment from its URL, https://app.siteqwality.com/rum/{app_id}/sessions/{session_id}:
| Query | Effect |
|---|---|
?, ?, ? | Opens at that offset into the recording (seconds, m:ss or h:mm:ss), clamped to the recording. Share writes this form. |
? | Opens 5 seconds before that absolute time (never before the start) and highlights the event row with that ID. The Replay link in an error’s Affected sessions list uses the error’s error_ts_ms and event_id. |
When both are present, t wins.
See also
Section titled “See also”- Replay overview for the concept and privacy guidance.
- Recording rules for the activation mechanism.
- SDK reference for the recorder’s browser-side behavior.