
## Authentication and request requirements

- All endpoints use HTTP Basic auth. Use your project's API key as the username and secret key as the password.
- The `project_id` parameter isn't needed. The authenticated API key identifies the project.
- Presigned file URLs expire after 15 minutes.
- Pagination cursors are opaque strings. Don't construct or modify them. Pass `next_page_token` from the previous response as-is.
- The `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.
- `amplitude_id` and `replay_id` are mutually exclusive. Passing both returns a 400 error.
- `replay_id` and `page_token` are mutually exclusive. Passing both returns a 400 error.
- Each `replay_id` value must use `device_id/session_id` format. A leading or trailing slash returns a 400 error.
- You can pass up to 100 `replay_id` values per request. Passing 101 or more returns a 400 error.
- `amplitude_id` must be a valid integer. A non-numeric value returns a 400 error.
- When you use `replay_id`, the API ignores `page_size` and always returns `next_page_token` as `null`.

## EU data residency

For EU data residency, use `https://analytics.eu.amplitude.com` as the base URL instead of `https://amplitude.com`. For example:

- List session replays: `GET https://analytics.eu.amplitude.com/api/1/session-replays`
- Get session replay files: `GET https://analytics.eu.amplitude.com/api/1/session-replays/files`

## List session replays

Returns a paginated list of session replays for the authenticated project.

`GET https://amplitude.com/api/1/session-replays`

{% code-group %}
```curl cURL
curl --location 'https://amplitude.com/api/1/session-replays' \
-u '{api_key}:{secret_key}'
```

```bash HTTP
GET /api/1/session-replays HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
```
{% /code-group %}

{% accordion title="Example: List replays with filters and descending sort" %}
{% code-group %}
```curl cURL
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}'
```

```bash HTTP
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
```
{% /code-group %}
{% /accordion %}

{% accordion title="Example: Filter replays by Amplitude user ID" %}
{% code-group %}
```curl cURL
curl --location 'https://amplitude.com/api/1/session-replays?amplitude_id=123456' \
-u '{api_key}:{secret_key}'
```

```bash HTTP
GET /api/1/session-replays?amplitude_id=123456 HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
```
{% /code-group %}
{% /accordion %}

{% accordion title="Example: Fetch specific replays by replay ID" %}
{% code-group %}
```curl cURL
curl --location 'https://amplitude.com/api/1/session-replays?replay_id=abc123%2F1700000000000&replay_id=def456%2F1700000001000' \
-u '{api_key}:{secret_key}'
```

```bash HTTP
GET /api/1/session-replays?replay_id=abc123%2F1700000000000&replay_id=def456%2F1700000001000 HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
```
{% /code-group %}
{% /accordion %}

### Query parameters

| 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`.                                                                                                                                                                                                                                 |
| `amplitude_id` | Optional. Integer. Filters results to replays belonging to a specific Amplitude user ID. Mutually exclusive with `replay_id`.                                                                                                                                                                                                                  |
| `replay_id`    | Optional. String. Filters results to specific replays by ID, in `device_id/session_id` format. URL-encode the `/` separator as `%2F`. Repeat this parameter to request up to 100 replays. Mutually exclusive with `amplitude_id` and `page_token`. When you use this parameter, `page_size` is ignored and `next_page_token` is always `null`. |
| `page_size`    | Optional. Integer. Number of results per page. Default is `50`, maximum is `200`. Ignored when `replay_id` is specified.                                                                                                                                                                                                                       |
| `page_token`   | Optional. String. Opaque pagination cursor from a previous response's `next_page_token`. Mutually exclusive with `replay_id`.                                                                                                                                                                                                                  |
| `sort_order`   | Optional. String. `asc` returns oldest replays first (default). `desc` returns newest replays first. Must be consistent across pages when using `page_token`.                                                                                                                                                                                  |

### Response

```json
{
  "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.                        |

---

## Get session replay files

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`

{% code-group %}
```curl cURL
curl --location 'https://amplitude.com/api/1/session-replays/files?replay_id={device_id}%2F{session_id}' \
-u '{api_key}:{secret_key}'
```

```bash HTTP
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
```
{% /code-group %}

{% accordion title="Example: Fetch v2 files with pagination" %}
{% code-group %}
```curl cURL
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}'
```

```bash HTTP
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
```
{% /code-group %}
{% /accordion %}

### Query parameters

| 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`.                          |

### Response

```json
{
  "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.                   |

## Decompress and parse replay files

The format of each file depends on the `version` you requested.

### Version 3

Each file uses gzip compression. Decompress the file to get a JSON array of [rrweb](https://github.com/amplitude/rrweb) events ready to pass to an rrweb player.

{% code-group %}
```javascript JavaScript
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
}
```

```python Python
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
```

```bash cURL
curl -s '{presigned_url}' | gunzip | python3 -m json.tool
```
{% /code-group %}

The result is a JSON array of rrweb events:

```json
[
  { "type": 4, "data": { "href": "https://example.com", "width": 1440, "height": 900 }, "timestamp": 1700000000000 },
  { "type": 2, "data": { ... }, "timestamp": 1700000000050 },
  ...
]
```

### Version 2

Version 2 files require two decompression steps:

1. **gzip decompress** the file, then JSON parse → array of packed strings.
2. **zlib decompress** each string: each element is a JSON-encoded, zlib-compressed (DEFLATE) binary payload → rrweb event object.

{% code-group %}
```javascript JavaScript
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
  });
}
```

```python Python
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
```
{% /code-group %}

### Play back events

To replay a full session, fetch all files for a replay in order, unpack each file, concatenate the event arrays, and pass the result to Amplitude's [rrweb player](https://github.com/amplitude/rrweb). Use Amplitude's fork rather than upstream rrweb, because the fork includes fixes that may be incompatible with the upstream version.

```javascript
const events = (await Promise.all(fileUrls.map(fetchReplayEvents))).flat();
rrweb.replay({ events, root: document.getElementById("player") });
```

## Status and error codes

| 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. |
