This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

Expo AgeRange

A library that provides access to age range information using Play Age Signals API on Android and Declared Age Range framework on iOS.

Android
iOS
Included in Expo Go

expo-age-range provides access to user age range information. It uses Google's Play Age Signals API on Android and Apple's Declared Age Range framework on iOS.

This library allows you to request age range information from your app users to help you comply with age-appropriate content regulations (such as in Texas, USA) and provide age-appropriate experiences in your app.

Limitations

We recommend testing the functionality on a real device, as simulator runtimes may not work as expected.

Installation

Terminal
- npx expo install expo-age-range
- yarn expo install expo-age-range
- pnpm expo install expo-age-range
- bun expo install expo-age-range

If you are installing this in an existing React Native app, make sure to install expo in your project.

Configuration in app config

Set up the iOS project

To use the age range API on iOS, you need to build your project with Xcode 26.0 or later but we recommend you build with the latest Xcode to have access to the latest APIs.

The com.apple.developer.declared-age-range entitlement is required. Add it to your app config file:

app.json
{ "expo": { "ios": { "entitlements": { "com.apple.developer.declared-age-range": true } } } }
Are you using this library in an existing React Native app?

For existing React Native projects, add the entitlement to your project's ios/[app]/[app].entitlements file:

<key>com.apple.developer.declared-age-range</key> <true/>

Usage

On Android, Play Age Signals only reports an age range while the user consents to sharing it. Call requestAgeSignalsAccessAsync first and continue only when it resolves with 'SHARED'. On iOS the consent prompt is part of requestAgeRangeAsync, so the call resolves with null and the example below continues.

Age Range usage
import * as AgeRange from 'expo-age-range'; import { useState } from 'react'; import { StyleSheet, Text, View, Button } from 'react-native'; export default function App() { const [result, setResult] = useState<AgeRange.AgeRangeResponse | { error: string } | null>(null); const requestAgeRange = async () => { try { // On Android, ask the user to share their age signals first. Resolves with null on iOS. const status = await AgeRange.requestAgeSignalsAccessAsync(); if (status !== null && status !== 'SHARED') { setResult({ error: `Age signals are not shared: ${status}` }); return; } const ageRange = await AgeRange.requestAgeRangeAsync({ threshold1: 10, threshold2: 13, threshold3: 18, }); setResult(ageRange); } catch (error) { setResult({ error: error instanceof Error ? error.message : String(error) }); } }; return ( <View style={styles.container}> <Button title="Request age range" onPress={requestAgeRange} /> {result && ( <Text style={styles.result}> {'error' in result ? `Error: ${result.error}` : `Lower age bound: ${result.lowerBound}`} </Text> )} </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', padding: 20, }, result: { marginTop: 20, fontSize: 16, }, });

Testing age signals on Android

Google Play only reports age signals to accounts it has enabled, so your test accounts may not have the age range you need. Use setFakeAgeSignals to fake them instead, through Google Play's FakeAgeSignalsManager.

Only debuggable builds can fake signals, because faked signals would let any code in the app bypass your age gating. Passing anything other than null in a build that is not debuggable throws ERR_AGE_RANGE_FAKE_SIGNALS_NOT_DEBUGGABLE.

Your requests do not change, only what they report:

// Report a supervised 13 to 15 year old with a change waiting for approval. AgeRange.setFakeAgeSignals({ ageSignalsStatus: 'SHARED', lowerBound: 13, upperBound: 15, ageRangeSource: 'TIER_B', significantChangeStatus: 'PENDING', }); const status = await AgeRange.requestAgeSignalsAccessAsync(); const { lowerBound } = await AgeRange.requestAgeRangeAsync({ threshold1: 18 }); // Report the real signals again. AgeRange.setFakeAgeSignals(null);

To fake a failure, pass an error code instead of signals:

AgeRange.setFakeAgeSignals({ errorCode: -4 });

Additional resources

API

import * as AgeRange from 'expo-age-range';

No API data file found, sorry!

Error codes

Available in the code property of any error thrown by the native module. For Android-specific error codes, see the "Error code reference" in Use Play Age Signals API docs.

CodePlatformDescription
ERR_AGE_RANGE_USER_DECLINED
iOS
User declined to share their age range.
ERR_AGE_RANGE_NOT_AVAILABLE
iOS
Age range not available. The most likely cause is that user is not signed in to their Apple account on the device.
ERR_AGE_RANGE_INVALID_REQUEST
iOS
The provided params were invalid. The age ranges need to be minimum 2 years apart.
ERR_AGE_RANGE_TASK_CANCELLED
Android
The user dismissed the Play Age Signals age sharing consent screen.
ERR_AGE_RANGE_FAKE_SIGNALS_CONFLICT
Android
setFakeAgeSignals was passed both an errorCode and age signals.
ERR_AGE_RANGE_FAKE_SIGNALS_NOT_DEBUGGABLE
Android
setFakeAgeSignals was asked to fake signals in a build that is not debuggable.