Privacy

Learn how to mask parts of your app's data in Session Replay.

By default, our Session Replay SDK masks all text content, images, webviews and user input. This helps ensure that no sensitive data will be exposed. You can also manually choose which parts of your app's data you want to mask by using the different options listed below.

To disable the default masking behavior (not to be used on applications with sensitive data):

Copied
options.experimental.sessionReplay.maskAllText = false
options.experimental.sessionReplay.maskAllImages = false

You can choose which type of view you want to mask or unmask by using the addMaskViewClass or addUnmaskViewClass options.

Let's say you have:

  • A custom view that you want to mask
  • A TextView subclass (which normally would be masked) that you don't want to mask.

You can set the options like this:

Copied
  options.experimental.sessionReplay.addMaskViewClass("com.example.MyCustomView")
  options.experimental.sessionReplay.addUnmaskViewClass("com.example.MyCustomTextView")

If you're using a code obfuscation tool (R8/ProGuard), adjust your proguard rules accordingly so your custom view class names are not minified.

The masking behavior applies to classes and their subclasses. This means if you add a view via addMaskViewClass (for example, TextView, which is the default behavior), its respective subclasses (RadioButton, CheckBox, EditText, etc.) will also be masked. For example, you can do the following:

Copied
  options.experimental.sessionReplay.addMaskViewClass("android.widget.TextView") // mask TextView and all its subclasses
  options.experimental.sessionReplay.addUnmaskViewClass("android.widget.RadioButton") // but unmask RadioButton and all its subclasses

You can also choose to mask or unmask a specific view instance by using tags like this:

Copied
<View
  android:id="@+id/my_view"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:tag="sentry-mask|sentry-unmask"
/>

If your view already has a tag assigned, you can set the masking tag by a sentry-specific id:

Copied
<View
  android:id="@+id/my_view"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
>
    <tag android:id="@id/sentry_privacy" android:value="mask|unmask" />
  </View>

We also provide convenient extension functions for Kotlin:

Copied
  view.sentryReplayMask()
  // or
  view.sentryReplayUnmask()

We only support masking specific composables in Jetpack Compose. Since composables don't have a concept of classes (they are all composable functions), masking by view class is not supported.

In this example, we want the "Hello" message to be captured in the replay (by default, all text composables are masked), but not the custom composable:

Copied
import io.sentry.android.replay.sentryReplayMask
import io.sentry.android.replay.sentryReplayUnmask

Column(
  verticalArrangement = Arrangement.Center,
  horizontalAlignment = Alignment.CenterHorizontally,
  modifier = Modifier.fillMaxSize()
) {
  MyCustomComposable(
    modifier = Modifier.fillMaxWidth().sentryReplayMask()
    ...
  )
  Text("Hello", modifier = Modifier.sentryReplayUnmask())
}

Currently, we don't support masking anything within embedded android views (AndroidView), but you can still mask the entire view as follows:

Copied
import io.sentry.android.replay.sentryReplayMask

AndroidView(
  modifier = Modifier.sentryReplayMask(),
  factory = { context -> ... }
)
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").