Skip to content

View and share recordings ​

Use the dashboard for internal investigation, or issue a short-lived presigned URL when an authorized viewer needs a hosted player or screenshot. A private API key has full read and write access. It belongs only on a trusted server. Never expose a private API key in browser code.

View a recording in the dashboard ​

Open recordings in the rrweb Cloud dashboard, select a recording, and use the built-in timeline and playback controls; this is the simplest option for teammates who already have dashboard access.

For an application-owned viewer, continue with a scoped link rather than asking the viewer to enter an API key.

On a trusted server, request the recording metadata and links with includeSignedUrls=true using the private API key, then return only the signed link the authorized viewer needs; presigned URLs are bearer credentials scoped to one resource that expire after the time encoded in expires.

The Get recording operation returns this shape when signing is available:

json
{
  "recordingId": "550e8400-e29b-41d4-a716-446655440000",
  "metadata": {},
  "links": {
    "self": "/recordings/550e8400-e29b-41d4-a716-446655440000",
    "events": "/recordings/550e8400-e29b-41d4-a716-446655440000/events",
    "player": "/recordings/550e8400-e29b-41d4-a716-446655440000/player",
    "screenshot": "/recordings/550e8400-e29b-41d4-a716-446655440000/screenshot",
    "eventsSigned": "/recordings/550e8400-e29b-41d4-a716-446655440000/events?tenantId=...&expires=...&keyId=...&signature=...",
    "playerSigned": "/recordings/550e8400-e29b-41d4-a716-446655440000/player.html?tenantId=...&expires=...&keyId=...&signature=...",
    "screenshotPngSigned": "/recordings/550e8400-e29b-41d4-a716-446655440000/screenshot.png?tenantId=...&expires=...&keyId=...&signature=..."
  }
}
bash
curl --get \
  --url 'https://api.rrweb.com/recordings/550e8400-e29b-41d4-a716-446655440000' \
  --header 'Authorization: Bearer secret_key_rr_your_key' \
  --header 'Accept: application/json' \
  --data-urlencode 'includeSignedUrls=true'

Protect the link from logs and analytics while it is valid. The currently returned playerSigned link targets /player.html, and screenshotPngSigned targets /screenshot.png.

Embed the hosted player ​

Give the embed an authorized playerSigned value from your application server, then add display options such as embed, autoplay, and time with the URL API before setting it as an iframe's src.

The Get recording player operation documents the canonical endpoint.

javascript
const playerUrl = new URL(playerSigned, 'https://api.rrweb.com');
playerUrl.searchParams.set('embed', 'controls');
playerUrl.searchParams.set('autoplay', 'false');

document.querySelector('#replay-frame').src = playerUrl.toString();
html
<iframe
  id="replay-frame"
  title="Session replay"
  allow="fullscreen"
  referrerpolicy="no-referrer"
></iframe>

The /recordings/{recordingId}/player.html endpoint accepts:

  • embed: false, true, controls, controls-hover, or controls-hidden;
  • autoplay: false (paused by default), true (play once), or loop;
  • speed: from 0.25 to 4; and
  • time: offset:0, offset:-5000, percent:50, or epoch:1702900000000.
Embed valueLayout
Omitted or falseStandard page with heading, recording ID, API-key form, and player controls
true or controlsPlayer fills its container, with controls always visible
controls-hoverPlayer fills its container, with controls revealed on hover or keyboard focus; touch devices keep them visible
controls-hiddenPlayer fills its container, with no controls, including on hover

For a looping embed without controls, set embed=controls-hidden and autoplay=loop on the signed URL. For a static frame, set embed=controls-hidden, autoplay=false, and time=percent:50.

Looping honors time on the first pass and restarts subsequent passes from the beginning. If time points to the end, looping starts from the beginning immediately. Recordings with zero duration do not repeat.

Embed layouts remove the heading, recording ID, and API-key form. The player fills the page or iframe viewport without opening browser fullscreen. The /preview alias forwards these query parameters to /player.html.

The signature protects the method, resource path, organization ID, and expiry. These player options are not integrity-protected, so constrain them in your own application if a viewer must not change them.

Capture a screenshot of a recording ​

Request /screenshot.png, /screenshot.jpeg, or /screenshot.webp from a trusted server with the private API key, choosing time, width, height, and quality to control the captured frame.

The Get recording screenshot operation supports those formats. A trusted server can request any format and proxy the resulting image to an authorized viewer:

bash
curl --get \
  --url 'https://api.rrweb.com/recordings/550e8400-e29b-41d4-a716-446655440000/screenshot.png?time=percent%3A50&width=1280&height=720' \
  --header 'Authorization: Bearer secret_key_rr_your_key' \
  --header 'Accept: image/png' \
  --output recording.png

Without an extension, send Accept: image/png, image/jpeg, or image/webp. An extension takes precedence over the header. Screenshot options are:

  • time, using the same offset, percent, or epoch forms as the player;
  • width and height, each from 1 to 4096 pixels; and
  • quality, an integer from 1 to 100 for JPEG and WebP. PNG ignores quality.

The recording-detail response generates a signed PNG link. Request JPEG or WebP through a trusted server when you need those formats.

Troubleshoot access ​

  • A 401 usually means authentication is missing or lacks recording-event read access.
  • A 403 on a signed link usually means its signature is invalid or expired.
  • A 404 means the recording or event stream was not found.
  • A 422 screenshot response means the requested time falls outside the recording.

See Authentication for the complete credential model.