Use the Session Replay API to list session replays and retrieve the event files for a specific replay.
This API uses basic authentication, using the API key and secret key for your project. Pass base64-encoded credentials in the request header like {api-key}:{secret-key}. api-key replaces username, and secret-key replaces the password.
Your authorization header should look something like this:
--header 'Authorization: Basic YWhhbWwsdG9uQGFwaWdlZS5jb206bClwYXNzdzByZAo'
For more information, see Find your API Credentials
| Region | Endpoint |
|---|---|
| Standard server | https://amplitude.com/api/1/session-replays |
project_id parameter is needed because the authenticated API key carries the project inference.next_page_token from the previous response as-is.sort_order parameter must be consistent across all pages of a paginated request. Passing a page_token from an asc request with sort_order=desc returns a 400 error.Returns a paginated list of session replays for the authenticated project.
GET https://amplitude.com/api/1/session-replays
curl --location 'https://amplitude.com/api/1/session-replays' \
-u '{api_key}:{secret_key}'
GET /api/1/session-replays HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
Example: List replays with filters and descending sort
curl --location 'https://amplitude.com/api/1/session-replays?start_time=2024-01-01T00%3A00%3A00Z&end_time=2024-01-31T23%3A59%3A59Z&page_size=25&sort_order=desc' \
-u '{api_key}:{secret_key}'
GET /api/1/session-replays?start_time=2024-01-01T00%3A00%3A00Z&end_time=2024-01-31T23%3A59%3A59Z&page_size=25&sort_order=desc HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
| Name | Description |
|---|---|
start_time |
Optional. ISO 8601 string. Lower bound on replay start_time, inclusive. For example, 2024-01-01T00:00:00Z. |
end_time |
Optional. ISO 8601 string. Upper bound on replay start_time, inclusive. For example, 2024-01-31T23:59:59Z. |
page_size |
Optional. Integer. Number of results per page. Default is 50, maximum is 200. |
page_token |
Optional. String. Opaque pagination cursor from a previous response's next_page_token. |
sort_order |
Optional. String. asc returns oldest replays first (default). desc returns newest replays first. Must be consistent across pages when using page_token. |
{
"session_replays": [
{
"replay_id": "string",
"session_id": "string",
"device_id": "string",
"amplitude_id": 123456,
"start_time": "2024-01-01T00:00:00Z",
"end_time": "2024-01-01T00:05:00Z",
"retention_in_days": 90
}
],
"next_page_token": "string | null"
}
| Property | Description |
|---|---|
session_replays |
Array of session replay objects. |
session_replays[].replay_id |
Unique identifier for the replay, in device_id/session_id format. Use this as the replay_id parameter when fetching files. |
session_replays[].session_id |
The session identifier. |
session_replays[].device_id |
The device identifier. |
session_replays[].amplitude_id |
The Amplitude user ID. |
session_replays[].start_time |
ISO 8601 timestamp of when the session started. |
session_replays[].end_time |
ISO 8601 timestamp of when the session ended. |
session_replays[].retention_in_days |
Number of days Amplitude retains the replay data. |
next_page_token |
Opaque cursor to pass as page_token to retrieve the next page. null when there are no more results. |
Returns a paginated list of presigned S3 URLs for the event files belonging to a specific replay. Each URL points to a gzip-compressed JSON array of rrweb events. Amplitude orders files by key, which encodes start time.
GET https://amplitude.com/api/1/session-replays/files
curl --location 'https://amplitude.com/api/1/session-replays/files?replay_id={device_id}%2F{session_id}' \
-u '{api_key}:{secret_key}'
GET /api/1/session-replays/files?replay_id={device_id}%2F{session_id} HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
Example: Fetch v2 files with pagination
curl --location 'https://amplitude.com/api/1/session-replays/files?replay_id={device_id}%2F{session_id}&version=2&page_size=50&page_token={page_token}' \
-u '{api_key}:{secret_key}'
GET /api/1/session-replays/files?replay_id={device_id}%2F{session_id}&version=2&page_size=50&page_token={page_token} HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
| Name | Description |
|---|---|
replay_id |
Required. String. The replay identifier, in device_id/session_id format. URL-encode the / separator as %2F. |
version |
Optional. Integer. Recording format version. 2 or 3. Default is 3. |
page_size |
Optional. Integer. Number of files per page. Default is 100, maximum is 1000. |
page_token |
Optional. String. Opaque pagination cursor from a previous response's next_page_token. |
{
"files": [
"https://s3.amazonaws.com/...presigned-url-1...",
"https://s3.amazonaws.com/...presigned-url-2..."
],
"next_page_token": "string | null"
}
| Property | Description |
|---|---|
files |
Array of presigned S3 URLs. Each URL serves a gzip-compressed JSON array of rrweb events. URLs expire after 15 minutes. |
next_page_token |
Opaque cursor to pass as page_token to retrieve the next page. null when there are no more files. |
The format of each file depends on the version you requested.
Each file is gzip-compressed. Decompress it to get a JSON array of rrweb events ready to pass to an rrweb player.
async function fetchReplayEvents(fileUrl) {
const response = await fetch(fileUrl);
// The response is gzip-compressed; fetch decompresses automatically in browsers.
// In Node.js 18+, use the DecompressionStream API or the zlib module.
const buffer = await response.arrayBuffer();
const text = new TextDecoder().decode(buffer);
return JSON.parse(text); // array of rrweb events
}
import gzip
import json
import urllib.request
def fetch_replay_events(file_url):
with urllib.request.urlopen(file_url) as response:
decompressed = gzip.decompress(response.read())
return json.loads(decompressed) # list of rrweb events
curl -s '{presigned_url}' | gunzip | python3 -m json.tool
The result is a JSON array of rrweb events:
[
{ "type": 4, "data": { "href": "https://example.com", "width": 1440, "height": 900 }, "timestamp": 1700000000000 },
{ "type": 2, "data": { ... }, "timestamp": 1700000000050 },
...
]
Version 2 files require two decompression steps:
const zlib = require('zlib');
async function fetchReplayEventsV2(fileUrl) {
const response = await fetch(fileUrl);
const buffer = Buffer.from(await response.arrayBuffer());
// Step 1: gzip decompress the file, then JSON parse → array of packed strings
const packedStrings = JSON.parse(zlib.gunzipSync(buffer).toString('utf8'));
// Step 2: unpack each string
return packedStrings.map((packed) => {
// Each packed string is itself a JSON string whose value is a latin1-encoded
// binary blob of zlib-compressed event data.
const compressedBinary = JSON.parse(packed);
const buf = Buffer.from(compressedBinary, 'latin1');
return JSON.parse(zlib.inflateSync(buf).toString('utf8')); // rrweb event
});
}
import gzip
import json
import zlib
import urllib.request
def fetch_replay_events_v2(file_url):
with urllib.request.urlopen(file_url) as response:
# Step 1: gzip decompress, then JSON parse → list of packed strings
packed_strings = json.loads(gzip.decompress(response.read()))
# Step 2: unpack each string
events = []
for packed in packed_strings:
# Each packed string is a JSON string whose value is a latin1-encoded
# binary blob of zlib-compressed event data.
compressed_binary = json.loads(packed)
buf = compressed_binary.encode('latin1')
events.append(json.loads(zlib.decompress(buf)))
return events
To replay a full session, fetch all files for a replay in order, unpack each one, concatenate the event arrays, and pass the result to Amplitude's rrweb player. Use Amplitude's fork rather than upstream rrweb, as it includes fixes that may be incompatible with the upstream version.
const events = (await Promise.all(fileUrls.map(fetchReplayEvents))).flat();
rrweb.replay({ events, root: document.getElementById('player') });
| Code | Description |
|---|---|
200 OK |
Successful request. |
400 Bad Request |
Invalid parameter value. Check the error message for details. |
401 Unauthorized |
Missing or invalid API credentials. |
404 Not Found |
No data found for the given replay_id. Amplitude only returns this error on the first page. |
March 4th, 2025
Need help? Contact Support
Visit Amplitude.com
Have a look at the Amplitude Blog
Learn more at Amplitude Academy
© 2026 Amplitude, Inc. All rights reserved. Amplitude is a registered trademark of Amplitude, Inc.