@milkinteractive/react-native-age-range
v1.0.5
Published
A React Native Native Module (Legacy Architecture) that provides access to store-level age signals, including Android Play Age Range and iOS Declared Age, to assist with state-level age verification compliance (e.g., Texas).
Maintainers
Readme

📱 Live Demos
Screen Recordings
iOS Age Verification Modal (Real Device)
| Step 1 | Step 2 | Modal |
|:------:|:------:|:-----:|
| |
|
|
Example App UI
| iOS UI | Android UI |
|:------:|:----------:|
|
|
|
React Native Age Range
A production-grade React Native module for verifiable age signals.
Seamlessly integrate with Apple's Declared Age Range API (iOS 26+) and Google Play Age Signals API to meet state-level age verification compliance (e.g., Texas, Utah, Louisiana) without handling sensitive PII yourself.
⚠️ COMPLIANCE NOTICE: Texas SB2420 requires apps to consume age signals from app stores starting January 1, 2026. Similar laws in Utah (May 7, 2026) and Louisiana (July 1, 2026) are also taking effect. This package provides the necessary integration for React Native apps.
Keywords: age verification, texas sb2420, age gate, parental controls, coppa compliance, react native age verification, google play age signals, ios declared age range, app store age verification, react native compliance, child safety, age appropriate design code
🚀 Features
- 🛡️ Privacy-First: Leverages OS-level store APIs. No access to birthdates or PII — only age range classifications.
- 🍎 iOS Integration: Native support for
DeclaredAgeRangeframework (iOS 26.0+). - 🤖 Android Integration: Official wrapper for Google Play
AgeSignalsApi. - 🧪 Mock Mode: Built-in developer tools to simulate all age scenarios on Simulators and Emulators.
- ⚡ Zero Config Mocks: Verification logic works out-of-the-box for development.
- 📱 Broad Compatibility: Works with any React Native version (0.60+) — uses legacy native module architecture.
🏗️ Architecture
graph TD
RN[React Native JS] -->|Standard Interface| Bridge[Native Module Bridge]
Bridge -->|Android| PlayService[Google Play Services]
Bridge -->|iOS| AppleAPI[Apple Declared Age Range]
PlayService -->|Status| Result[Verified / Supervised / Error]
AppleAPI -->|Status| Result
subgraph Privacy Shield
PlayService
AppleAPI
end📦 Installation
npm install @milkinteractive/react-native-age-range
# or
yarn add @milkinteractive/react-native-age-range⚙️ Setup
🍎 iOS Setup
Framework Requirements:
- iOS 26.0+ is required for the
DeclaredAgeRangeAPI to function. - Older versions will return a fallback/unavailable response.
- iOS 26.0+ is required for the
Install Pods:
cd ios && pod installEntitlements (Critical):
- You must enable the
Declared Age Rangecapability in Xcode. - Go to Project Target -> Signing & Capabilities -> + Capability -> Declared Age Range.
- Note: This capability typically requires a paid Apple Developer Program membership. "Personal Team" profiles may not support it.
- You must enable the
⚠️ Apple API Limitations:
- Minimum Range Duration: Age thresholds must create ranges of at least 2 years.
- Example: Thresholds
10, 13, 16work because they create: Under 10, 10-12 (2 yrs), 13-15 (2 yrs), 16+. - Invalid Example:
13, 14, 21would fail because 13-14 is only 1 year. - Common working combinations:
10, 13, 16or13, 16, 18or13, 17, 21.
🤖 Android Setup
No manual configuration required. The package automatically bundles com.google.android.play:age-signals.
- Requirement: Device must have Google Play Services installed.
💻 Usage
import {
getAndroidPlayAgeRangeStatus,
requestIOSDeclaredAgeRange,
isIOSEligibleForAgeFeatures,
isAndroidEligibleForAgeFeatures,
} from '@milkinteractive/react-native-age-range';
import { Platform } from 'react-native';
// 🤖 Android Example
async function checkAndroid() {
if (Platform.OS !== 'android') return;
const result = await getAndroidPlayAgeRangeStatus();
if (result.userStatus === 'OVER_AGE') {
// ✅ User is a verified adult
grantAccess();
} else if (result.userStatus === 'UNDER_AGE') {
// ⚠️ User is supervised (e.g. Family Link)
// result.ageLower and result.ageUpper are available (e.g., 13-17)
enableRestrictedMode(result.ageLower, result.ageUpper);
} else {
// ❌ Verification failed or unknown
handleError(result.error);
}
}
// 🍎 iOS Example
async function checkIOS() {
if (Platform.OS !== 'ios') return;
// Request discrete age signals (e.g. 13+, 17+, 21+)
const result = await requestIOSDeclaredAgeRange(13, 17, 21);
if (result.error) {
// ❌ API error (e.g., iOS < 26.0, missing entitlement)
console.error('iOS Signal Failed:', result.error);
return;
}
if (result.status === 'sharing') {
// ✅ User shared their age range
console.log(`Confirmed Range: ${result.lowerBound} - ${result.upperBound}`);
console.log(`Declaration: ${result.ageRangeDeclaration}`);
} else {
// ❌ User declined
console.log('User declined to share age range');
}
}
// 🔍 Check Eligibility (should age verification be shown?)
async function checkEligibility() {
const result = Platform.OS === 'ios'
? await isIOSEligibleForAgeFeatures()
: await isAndroidEligibleForAgeFeatures();
if (result.error) {
console.log('Eligibility check failed:', result.error);
return false;
}
if (result.isEligible) {
// User is in a region requiring age verification (e.g., Texas)
// Proceed with age verification flow
return true;
}
// User is not subject to age verification requirements
return false;
}🧪 Developer Mock Mode
Testing store APIs usually requires signed production builds. This library includes a powerful Mock Mode for development.
// Simulate a Supervised User (Age 13-17)
const mockResult = await getAndroidPlayAgeRangeStatus({
isMock: true,
mockStatus: 'UNDER_AGE',
mockAgeLower: 13,
mockAgeUpper: 17
});🔧 API Reference
getAndroidPlayAgeRangeStatus(config?)
Retrieves Android Play Age Signal.
| Parameter | Type | Default | Description |
|---|---|---|---|
| config.isMock | boolean | false | Enable to return fake data. |
| config.mockStatus | enum | 'OVER_AGE' | See status values below |
| config.mockErrorCode | number | null | Simulate API error code (e.g. -1). |
Returns: Promise<PlayAgeRangeStatusResult>
userStatus: User verification status:OVER_AGE- Verified adult (18+)UNDER_AGE- Supervised account (child/teen)UNDER_AGE_APPROVAL_PENDING- Supervised, parent hasn't approved pending significant changesUNDER_AGE_APPROVAL_DENIED- Supervised, parent denied approval for significant changesUNKNOWN- Status could not be determined
installId: Unique installation identifierageLower/ageUpper: Age range bounds (for supervised users)mostRecentApprovalDate: Date of last approved significant changeerror/errorCode: Error information if request failed
requestIOSDeclaredAgeRange(threshold1, threshold2, threshold3)
Request iOS Age Signal.
| Parameter | Type | Description |
|---|---|---|
| threshold[1-3] | number | Age thresholds to verify. Must create 2+ year ranges. |
⚠️ Apple API Constraint: Thresholds must result in age ranges of at least 2 years duration.
- ✅ Valid:
10, 13, 16→ Creates ranges: <10, 10-12, 13-15, 16+ - ✅ Valid:
13, 17, 21→ Creates ranges: <13, 13-16, 17-20, 21+ - ❌ Invalid:
13, 14, 21→ 13-14 is only 1 year (API will reject)
Returns: Promise<DeclaredAgeRangeResult>
status:'sharing' | 'declined' | nulllowerBound:number | null- Lower age of user's rangeupperBound:number | null- Upper age of user's rangeageRangeDeclaration: How the age was verified:selfDeclared- User declared their own ageguardianDeclared- Guardian set the age (children in iCloud family)governmentIDChecked/guardianGovernmentIDChecked- Verified via government IDpaymentChecked/guardianPaymentChecked- Verified via payment methodcheckedByOtherMethod/guardianCheckedByOtherMethod- Other verification
parentalControls:{ communicationLimits?: boolean, significantAppChangeApprovalRequired?: boolean }- Active parental controlserror:string | null- Error message if API unavailable or request failed
isIOSEligibleForAgeFeatures()
Check if the current iOS user is subject to age verification requirements (e.g., in Texas).
Returns: Promise<DeclaredAgeEligibilityResult>
isEligible:boolean-trueif user should be shown age verificationerror:string | null- Error message if API unavailable
Requirements: iOS 26.2+ for accurate results. Returns isEligible: false with error on older versions.
isAndroidEligibleForAgeFeatures()
Check if the current Android user is subject to age verification requirements.
Returns: Promise<DeclaredAgeEligibilityResult>
isEligible:boolean-trueif user should be shown age verification (in Texas, Utah, Louisiana, etc.)error:string | null- Error message if API unavailable
Note: Makes a lightweight API call to determine eligibility.
🚨 Troubleshooting
iOS Errors
| Error Code | Meaning | Solution |
|---|---|---|
| Error 0 | Missing Entitlement | 1. Add Declared Age Range capability in Xcode.2. Ensure you are using a Paid Developer Account. Personal teams often block this API.3. Real Device Only: This API does NOT work on Simulators. |
| Error -1 | API Unavailable | Device is running an iOS version older than 26.0. |
Android Errors
📚 Additional Resources
Android Error Codes Reference
| Code | Error | Description | Retryable | |---|---|---|---| | -1 | API_NOT_AVAILABLE | Play Store app version might be old. | Yes | | -2 | PLAY_STORE_NOT_FOUND | No Play Store app found. | Yes | | -3 | NETWORK_ERROR | No network connection. | Yes | | -4 | PLAY_SERVICES_NOT_FOUND | Play Services unavailable or old. | Yes | | -5 | CANNOT_BIND_TO_SERVICE | Failed to bind to Play Store service. | Yes | | -6 | PLAY_STORE_VERSION_OUTDATED | Play Store app needs update. | Yes | | -7 | PLAY_SERVICES_VERSION_OUTDATED | Play Services needs update. | Yes | | -8 | CLIENT_TRANSIENT_ERROR | Transient client error. Retry with backoff. | Yes | | -9 | APP_NOT_OWNED | App not installed by Google Play. | No | | -100 | INTERNAL_ERROR | Unknown internal error. | No |
Official API Documentation
Apple iOS:
- Declared Age Range Framework - Official Apple Developer Documentation
- WWDC25: Deliver age-appropriate experiences in your app - Session video explaining implementation
Google Android:
- Play Age Signals Overview - Introduction and concepts
- Use Play Age Signals API - Implementation guide
- Test your Play Age Signals API integration - Testing with FakeAgeSignalsManager
- Play Age Signals Release Notes - Version history and updates
🤝 Contributing
See the contributing guide to learn how to contribute to the repository and the development workflow.
📄 License
MIT
Made with ❤️ for React Native developers navigating age verification compliance.
