Expo ScreenCapture

GitHub

npm

A library that allows you to protect screens in your app from being captured or recorded.

Android
iOS

expo-screen-capture allows you to protect screens in your app from being captured or recorded, as well as be notified if a screenshot is taken while your app is foregrounded. The two most common reasons you may want to prevent screen capture are:

  • If a screen is displaying sensitive information (password, credit card data, and so on)
  • You are displaying paid content that you don't want to be recorded and shared

This is especially important on Android since the android.media.projection API allows third-party apps to perform screen capture or screen sharing (even if the app is in the background).

On Android, the screen capture callback works without additional permissions only for Android 14+. You don't need to request or check permissions for blocking screen capture or using the callback on Android 14+.

If you want to use the screen capture callback on Android 13 or lower, you need to add the READ_MEDIA_IMAGES permission to your AndroidManifest.xml file. You can use the android.permissions key in your app config. See Android permissions for more information.

The READ_MEDIA_IMAGES permission can be added only for apps needing broad access to photos. See Details on Google Play's Photo and Video Permissions policy.
Currently, taking screenshots on iOS cannot be prevented. This is due to underlying OS limitations.

Installation

Terminal
npx expo install expo-screen-capture

If you are installing this in an existing React Native app, start by installing expo in your project. Then, follow the additional instructions as mentioned by the library's README under "Installation in bare React Native projects" section.

Usage

Example: hook

Screen Capture hook
import { usePreventScreenCapture } from 'expo-screen-capture';
import { Text, View } from 'react-native';

export default function ScreenCaptureExample() {
  usePreventScreenCapture();

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>As long as this component is mounted, this screen is unrecordable!</Text>
    </View>
  );
}

Example: Blocking screen capture imperatively

Blocking screen capture
import * as ScreenCapture from 'expo-screen-capture';
import { useEffect } from 'react';
import { Button, StyleSheet, View } from 'react-native';

export default function ScreenCaptureExample() {
  const activate = async () => {
    await ScreenCapture.preventScreenCaptureAsync();
  };

  const deactivate = async () => {
    await ScreenCapture.allowScreenCaptureAsync();
  };

  return (
    <View style={styles.container}>
      <Button title="Activate" onPress={activate} />
      <Button title="Deactivate" onPress={deactivate} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

Example: Callback for screen capture

Callback for screen capture
import * as ScreenCapture from 'expo-screen-capture';
import { useEffect } from 'react';
import { Button, StyleSheet, View } from 'react-native';

export default function useScreenCaptureCallback() {
  // Only use this if you add the READ_MEDIA_IMAGES permission to your AndroidManifest.xml
  const hasPermissions = async () => {
    const { status } = await ScreenCapture.requestPermissionsAsync();
    return status === 'granted';
  };

  useEffect(() => {
    let subscription;

    const addListenerAsync = async () => {
      if (await hasPermissions()) {
        subscription = ScreenCapture.addScreenshotListener(() => {
          alert('Thanks for screenshotting my beautiful app 😊');
        });
      } else {
        console.error('Permissions needed to subscribe to screenshot events are missing!');
      }
    };
    addListenerAsync();

    return () => {
      subscription?.remove();
    };
  }, []);
}

API

import * as ScreenCapture from 'expo-screen-capture';

Hooks

Android
iOS

usePermissions(options)

ParameterType
options
(optional)
PermissionHookOptions<object>

Returns:

[null | PermissionResponse, RequestPermissionMethod<PermissionResponse>, GetPermissionMethod<PermissionResponse>]

Android
iOS

usePreventScreenCapture(key)

ParameterTypeDescription
key
(optional)
string

If provided, this will prevent multiple instances of this hook or the preventScreenCaptureAsync and allowScreenCaptureAsync methods from conflicting with each other. This argument is useful if you have multiple active components using the allowScreenCaptureAsync hook.

Default:'default'

A React hook to prevent screen capturing for as long as the owner component is mounted.

Returns:

void

Methods

Android
iOS

ScreenCapture.allowScreenCaptureAsync(key)

ParameterTypeDescription
key
(optional)
string

This will prevent multiple instances of the preventScreenCaptureAsync and allowScreenCaptureAsync methods from conflicting with each other. If provided, the value must be the same as the key passed to preventScreenCaptureAsync in order to re-enable screen capturing.

Default:'default'

Re-allows the user to screen record or screenshot your app. If you haven't called preventScreenCapture() yet, this method does nothing.

Returns:

Promise<void>

Android
iOS

ScreenCapture.getPermissionsAsync()

Checks user's permissions for detecting when a screenshot is taken.

Only Android requires additional permissions to detect screenshots. On iOS devices, this method will always resolve to a granted permission response.

A promise that resolves to a PermissionResponse object.

Android
iOS

ScreenCapture.isAvailableAsync()

Returns whether the Screen Capture API is available on the current device.

Returns:

Promise<boolean>

A promise that resolves to a boolean indicating whether the Screen Capture API is available on the current device.

Android
iOS 11+

ScreenCapture.preventScreenCaptureAsync(key)

ParameterTypeDescription
key
(optional)
string

Optional. If provided, this will help prevent multiple instances of the preventScreenCaptureAsync and allowScreenCaptureAsync methods (and usePreventScreenCapture hook) from conflicting with each other. When using multiple keys, you'll have to re-allow each one in order to re-enable screen capturing.

Default:'default'

Prevents screenshots and screen recordings until allowScreenCaptureAsync is called or the app is restarted. If you are already preventing screen capture, this method does nothing (unless you pass a new and unique key).

Please note that on iOS, this will only prevent screen recordings, and is only available on iOS 11 and newer. On older iOS versions, this method does nothing.

Returns:

Promise<void>

Android
iOS

ScreenCapture.requestPermissionsAsync()

Asks the user to grant permissions necessary for detecting when a screenshot is taken.

Only Android requires additional permissions to detect screenshots. On iOS devices, this method will always resolve to a granted permission response.

A promise that resolves to a PermissionResponse object.

Event Subscriptions

Android
iOS

ScreenCapture.addScreenshotListener(listener)

ParameterTypeDescription
listener() => void

The function that will be executed when the user takes a screenshot. This function accepts no arguments.


Adds a listener that will fire whenever the user takes a screenshot while the app is foregrounded. On Android, this method requires the READ_EXTERNAL_STORAGE permission. You can request this with MediaLibrary.requestPermissionsAsync().

Returns:

EventSubscription

A Subscription object that you can use to unregister the listener, either by calling remove() or passing it to removeScreenshotListener.

Android
iOS

ScreenCapture.removeScreenshotListener(subscription)

ParameterTypeDescription
subscriptionEventSubscription

Subscription returned by addScreenshotListener.


Removes the subscription you provide, so that you are no longer listening for screenshots. You can also call remove() on that Subscription object.

Returns:

void

Example

let mySubscription = addScreenshotListener(() => {
  console.log("You took a screenshot!");
});
...
mySubscription.remove();
// OR
removeScreenshotListener(mySubscription);

Interfaces

Android
iOS

PermissionResponse

An object obtained by permissions get and request functions.

PermissionResponse Properties

NameTypeDescription
canAskAgainboolean

Indicates if user can be asked again for specific permission. If not, one should be directed to the Settings app in order to enable/disable the permission.

expiresPermissionExpiration

Determines time when the permission expires.

grantedboolean

A convenience boolean that indicates if the permission is granted.

statusPermissionStatus

Determines the status of the permission.


Types

Android
iOS

PermissionHookOptions

Literal Type: multiple types

Acceptable values are: PermissionHookBehavior | Options

Android
iOS

Subscription

A subscription object that allows to conveniently remove an event listener from the emitter.

NameTypeDescription
remove() => void

Removes an event listener for which the subscription has been created. After calling this function, the listener will no longer receive any events from the emitter.

Enums

Android
iOS

PermissionStatus

PermissionStatus Values

DENIED

PermissionStatus.DENIED = "denied"

User has denied the permission.

GRANTED

PermissionStatus.GRANTED = "granted"

User has granted the permission.

UNDETERMINED

PermissionStatus.UNDETERMINED = "undetermined"

User hasn't granted or denied the permission yet.