---
title: Session Replay React Native Standalone SDK
description: Use the standalone SDK if you want to instrument Session Replay without using the Amplitude Analytics SDK.
product: session-replay
last_updated: 2024-07-01
token_estimate: 3394
---
# Session Replay React Native Standalone SDK

> For AI agents: a documentation index is available at [/docs/llms.txt](/docs/llms.txt). Append `.md` to any page URL for markdown, or send `Accept: text/markdown`.

- **Package:** `@amplitude/session-replay-react-native` ([npm](https://www.npmjs.com/package/@amplitude/session-replay-react-native))
- **Latest version:** 1.0.1

The Session Replay React Native standalone SDK records mobile sessions and uploads them to Amplitude without the Amplitude Analytics SDK. Use it when another analytics provider already instruments your app, or when you manage Amplitude `deviceId` and `sessionId` yourself. If your app already uses the Amplitude React Native Analytics SDK, install the [Session Replay React Native SDK Plugin](https://amplitude.com/docs/sdks/session-replay/session-replay-react-native-sdk-plugin) instead.

You need an Amplitude API key. After you install the package, rebuild the native app. Expo Go doesn't include this native module, so use a development build or a prebuild client.

For changelog details, go to the [package change log](https://github.com/amplitude/Amplitude-TypeScript/blob/main/packages/session-replay-react-native/CHANGELOG.md) on GitHub.

## Install the SDK

#### npm

```bash
npm install @amplitude/session-replay-react-native --save
```

#### yarn

```bash
yarn add @amplitude/session-replay-react-native
```

## Quickstart

`init()` configures the SDK and doesn't start capture. Call `start()` after you pass matching `deviceId` and `sessionId` values.

```js
import { init, start } from "@amplitude/session-replay-react-native";

await init({
  apiKey: "YOUR_API_KEY",
  deviceId: "YOUR_DEVICE_ID",
  sessionId: Date.now(),
  sampleRate: 0.1,
  privacyConfig: {
    maskLevel: "medium",
  },
});

await start();
```

## Correlate replays with analytics events

Session Replay matches a replay to analytics events when the standalone SDK and your analytics SDK send the same `deviceId` and `sessionId`. Pass those values into `init()`, then call `setDeviceId()` and `setSessionId()` whenever either identifier changes.

```js
import {
  setDeviceId,
  setSessionId,
} from "@amplitude/session-replay-react-native";

await setDeviceId("new-device-id");
await setSessionId(Date.now());
```

The standalone SDK doesn't manage sessions for you. Your app or third-party analytics integration must keep both identifiers in sync.

## Configuration

Pass this configuration to `init()`.

| Name | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `apiKey` | `string` | Yes | - | Your Amplitude API key. |
| `deviceId` | `string | null` | No | `null` | Device identifier that matches the device ID on your analytics events. |
| `sessionId` | `number` | No | `-1` | Session identifier that matches the session ID on your analytics events. Use milliseconds since epoch. |
| `sampleRate` | `number` | No | `0` | Fraction of sessions to capture, as a decimal between `0` and `1`. For example, `0.4` selects 40% of sessions over a large sample. |
| `enableRemoteConfig` | `boolean` | No | `true` | Enables [remote configuration](https://amplitude.com/docs/admin/account-management/account-settings#session-replay-settings). |
| `logLevel` | `LogLevel` | No | `LogLevel.Warn` | Sets the log level for the Session Replay SDK. Import `LogLevel` from `@amplitude/session-replay-react-native`, then pass `LogLevel.None`, `LogLevel.Error`, `LogLevel.Warn`, `LogLevel.Verbose`, or `LogLevel.Debug`. |
| `privacyConfig` | `{ maskLevel?: 'light' | 'medium' | 'conservative' }` | No | `{ maskLevel: 'medium' }` | Privacy options. Set `maskLevel` to `'light'`, `'medium'`, or `'conservative'`. |
| `optOut` | `boolean` | No | `false` | Set to `true` to skip session replay collection at initialization. |
| `serverZone` | `'US' | 'EU'` | No | `'US'` | Amplitude server zone. Set to `'EU'` for EU data residency. |

## Methods

### init

Configures the Session Replay SDK. Call this before any other Session Replay method. `init()` doesn't start capture.

```js
import { init } from "@amplitude/session-replay-react-native";

await init({
  apiKey: "YOUR_API_KEY",
  deviceId: "YOUR_DEVICE_ID",
  sessionId: Date.now(),
});
```

### start

Starts recording session replay. Call this after `init()`, and after a previous `stop()` when you want capture to resume.

```js
import { start } from "@amplitude/session-replay-react-native";

await start();
```

### stop

Stops recording session replay.

```js
import { stop } from "@amplitude/session-replay-react-native";

await stop();
```

### setSessionId

Updates the session identifier. Call this whenever the session ID on your analytics events changes.

```js
import { setSessionId } from "@amplitude/session-replay-react-native";

await setSessionId(Date.now());
```

### setDeviceId

Updates the device identifier. Call this whenever the device ID on your analytics events changes. Pass `null` to clear the device ID.

```js
import { setDeviceId } from "@amplitude/session-replay-react-native";

await setDeviceId("new-device-id");
await setDeviceId(null);
```

### getSessionId

Returns the current session identifier from the Session Replay SDK, or `null` if you haven't initialized the SDK.

```js
import { getSessionId } from "@amplitude/session-replay-react-native";

const sessionId = await getSessionId();
```

### setOptOut

Updates opt-out at runtime. Pass `true` to disable replay collection. Pass `false` to allow collection again, subject to sampling and whether you already called `start()`.

```js
import { setOptOut } from "@amplitude/session-replay-react-native";

await setOptOut(true);
await setOptOut(false);
```

### flush

Uploads pending session replay data immediately.

```js
import { flush } from "@amplitude/session-replay-react-native";

await flush();
```

### teardown

Shuts down native Session Replay and clears JavaScript lifecycle state. Call `init()` again before any other Session Replay method.

```js
import { init, start, teardown } from "@amplitude/session-replay-react-native";

await teardown();

await init({
  apiKey: "YOUR_API_KEY",
  deviceId: "YOUR_DEVICE_ID",
  sessionId: Date.now(),
});
await start();
```

## Mask onscreen data

Session Replay masks or obfuscates views that contain sensitive data or PII. Wrap the region with `AmpMaskView` and set `mask` to `amp-mask`, `amp-unmask`, or `amp-block`. `AmpMaskView` lays out like a normal `View`, so apply the same layout styles you use on a `View`.

```js
import { AmpMaskView } from "@amplitude/session-replay-react-native";

<AmpMaskView mask="amp-mask">
  <Text>{title}</Text>
</AmpMaskView>;
```

`AmpMaskView` is a regular React Native layout node, so it takes part in layout exactly like a `View` and doesn't make itself transparent to layout. When you wrap existing content, apply the sizing and flex styles that the content relies on to the `AmpMaskView` itself, such as `flex: 1`, an explicit `width` and `height`, or `alignItems`. Without those styles, the wrapper can collapse or resize the region you wrapped.

### Unmask views

To unmask a view that the global mask level otherwise masks, set `mask` to `amp-unmask`.

```js
import { AmpMaskView } from "@amplitude/session-replay-react-native";

<AmpMaskView mask="amp-unmask">
  <Text>{title}</Text>
</AmpMaskView>;
```

### Block views

To replace a view with an empty placeholder of the same dimensions, set `mask` to `amp-block`.

```js
import { AmpMaskView } from "@amplitude/session-replay-react-native";

<AmpMaskView mask="amp-block">
  <Text>Session Replay doesn't capture this content</Text>
</AmpMaskView>;
```

### Platform differences in masking

Android and iOS resolve `AmpMaskView` with different native Session Replay libraries, so identical markup can behave differently on each platform. Test your masking on both platforms before you release.

| Behavior | Android | iOS |
| --- | --- | --- |
| Marker resolution | The nearest explicit mask marker wins. | A masked parent wins over any marker nested inside it. |
| `amp-unmask` nested inside a masked region | The nested subtree becomes visible again in the replay. | The nested subtree stays masked. iOS doesn't support nested unmasking. |
| Where `amp-unmask` takes effect | Anywhere, including inside a region that `amp-mask` covers. | Only outside masked regions, such as on content that the mask level masks. |
| Masked text in the replay | Asterisks that preserve the length of the original text. | No image and no text. The region renders as a flat gray fill. |
| `amp-block` in the replay | Session Replay sends no bitmap for the view, and the player renders a placeholder. | The region renders as a flat gray fill, the same as `amp-mask`. |

Session Replay applies these representations on the device when it captures each frame, so the uploaded replay data holds the masked representation instead of the original text or pixels. The player can't restore masked content later.

To keep a region visible on both platforms, place its `amp-unmask` wrapper outside every `amp-mask` and `amp-block` region rather than nesting it inside one.

### Choose a masking level

Set `privacyConfig.maskLevel` in `init()`.

| Mask level | Description |
| --- | --- |
| `light` | Masks sensitive native text inputs, such as passwords. |
| `medium` (default) | Masks all React Native `TextInput` fields. |
| `conservative` | Masks all `TextInput` fields and standard React Native `Text` content. |

> **Note:** React Native masking limitations
>
> Session Replay doesn't automatically mask text that React Native renders outside standard native text views, including `react-native-svg`, Shopify Skia, and canvas-based renderers. Wrap those regions in `AmpMaskView`.
>
> On Android, `light` doesn't reliably identify credit-card fields. Use `medium` or `conservative`, or wrap the field in `AmpMaskView`, for cross-platform coverage.

Remote configuration on the Session Replay settings page takes precedence over the SDK. This SDK forwards `enableRemoteConfig` to the native iOS and Android Session Replay libraries. Amplitude's Session Replay privacy settings state that if you enable remote configuration and it fails to load, Session Replay doesn't capture sessions.

## Track web views (beta)

By default, Session Replay blocks web views and doesn't track them. To track a web view, wrap it in `AmpMaskView` and set `mask` to `amp-unmask`.

```js
import { AmpMaskView } from "@amplitude/session-replay-react-native";
import { WebView } from "react-native-webview";

<AmpMaskView mask="amp-unmask" style={{ flex: 1 }}>
  <WebView source={{ uri: "https://reactnative.dev/" }} style={{ flex: 1 }} />
</AmpMaskView>;
```

## EU data residency

Session Replay supports Amplitude projects that use the EU data center. Set `serverZone` to `'EU'` during initialization.

```js
import { init, start } from "@amplitude/session-replay-react-native";

await init({
  apiKey: "YOUR_API_KEY",
  deviceId: "YOUR_DEVICE_ID",
  sessionId: Date.now(),
  serverZone: "EU",
});
await start();
```

## Sampling rate

By default, Session Replay captures 0% of sessions. Set `sampleRate` to the percentage of sessions you want to record.

```js
import { init, start } from "@amplitude/session-replay-react-native";

await init({
  apiKey: "YOUR_API_KEY",
  deviceId: "YOUR_DEVICE_ID",
  sessionId: Date.now(),
  sampleRate: 0.1,
});
await start();
```

When you set `sampleRate`, consider the monthly quota on your Session Replay plan. For example, if your monthly quota is 2,500,000 sessions and you average 3,000,000 monthly sessions, your quota is 83% of your average sessions. To make sampling last through the month, set `sampleRate` to `.83` or lower.

Keep these quota details in mind:

- When you reach your monthly session quota, Amplitude stops capturing sessions for replay.
- Session quotas reset on the first of every month.
- Use sample rate to distribute your session quota across the month, rather than using your full quota at the beginning.
- Start with a low rate, for example `.01`. If this value doesn't capture enough replays, raise the rate over a few days. To monitor captured replay volume, go to [View the number of captured sessions](https://amplitude.com/docs/session-replay).

Session Replay supports remote sampling rate settings. Your organization can update the sampling rate of your project after implementation, without a code change. If there's a conflict, Session Replay defaults to the remote setting. For more information, go to [Account Settings](https://amplitude.com/docs/admin/account-management/account-settings#session-replay-settings).

## User opt-out

To skip collection at initialization, set `optOut` to `true`. To change this later, call `setOptOut()`. Don't re-run `init()` only to change opt-out.

```js
import { init, setOptOut, start } from "@amplitude/session-replay-react-native";

await init({
  apiKey: "YOUR_API_KEY",
  deviceId: "YOUR_DEVICE_ID",
  sessionId: Date.now(),
  optOut: true,
});

await setOptOut(false);
await start();
```

## Troubleshooting

### No replay appears

- Call `start()` after `init()`. `init()` configures the SDK and doesn't begin capture.
- Use a non-zero `sampleRate`, or confirm the remote sampling rate on the Session Replay settings page.
- Pass the same `deviceId` and `sessionId` that your analytics events use, and update both when they change.
- Rebuild the native app after you install the package. On iOS, run `pod install` before the rebuild.
- Don't run this SDK in Expo Go. Create a development build or prebuild client instead.

