shipcheck

Why React Native apps fail the privacy manifest check

Updated September 4, 2026 · quoted from Apple and Expo documentation

Because the requirement is per-bundle, and your dependencies are someone else's bundles.

Apple's rule, from the privacy manifest documentation: "For each executable or dynamic library in an app that uses a required reason API, the bundle that includes the executable or dynamic library needs to include a privacy manifest file." A third-party SDK cannot rely on your app's manifest.

Since May 1, 2024, apps that don't describe their use of required reason APIs are not accepted by App Store Connect.

Hermes is on Apple's list, and it ships in nearly every RN app

Apple maintains a list of commonly used third-party SDKs that require both a privacy manifest and a signature. hermes is on it. So are a lot of things RN and Expo projects pull in routinely: the Firebase family, FBSDK, GoogleSignIn, GoogleUtilities, GTMSessionFetcher, OneSignal, SDWebImage, Lottie, Alamofire, AFNetworking, Kingfisher, OpenSSL, Protobuf, nanopb, RealmSwift, the RxSwift family, Reachability, SnapKit, Starscream, SwiftyJSON, leveldb, FMDB, Capacitor and Cordova.

Most React Native developers have never heard that Hermes is implicated. It is the default engine.

The gap Expo documents openly

Expo's Apple privacy guide states plainly that "Apple does not correctly parse all the PrivacyInfo files included by static CocoaPods dependencies," and its recommended remedy is to manually walk node_modules looking for PrivacyInfo.xcprivacy files and aggregate their values into your own manifest.

That is the actual state of the art: hand-auditing a dependency tree that routinely runs to hundreds of packages. Expo also flags its own guide as still in development.

What the manifest contains

The file must be named exactly PrivacyInfo.xcprivacy. Its four top-level keys, per Apple's documentation:

KeyTypePurpose
NSPrivacyTrackingBooleanWhether the app or SDK uses data for tracking
NSPrivacyTrackingDomainsArrayDomains involved in tracking; required when tracking is true
NSPrivacyCollectedDataTypesArrayData types collected, and why
NSPrivacyAccessedAPITypesArrayRequired reason APIs used, each with declared reason codes

Expo projects configure this through expo.ios.privacyManifests in app config rather than by hand-editing the plist.

The five required reason API categories

Per Expo's guide, the categories that require a declared reason are: UserDefaults, file timestamps, system boot time, disk space, and active keyboard.

We are deliberately not reproducing the reason-code strings here. Apple's reason codes render dynamically on its own documentation page and secondary copies of them circulate with errors. A wrong reason code produces a rejection that looks like a fixed problem. Read them from Apple's page directly.

Why a scan beats a checklist here

The problem is not that the rule is complicated — it is one sentence. The problem is that answering "does this project comply?" requires enumerating every executable and dynamic library in a dependency tree you did not write, and checking each against a list Apple updates. That is a machine's job. It is the job shipcheck was built to do.

Verify against Apple before you act. Every guideline quotation here is linked to Apple's own page. The guidelines are a living document that Apple changes without notice — read the source, don't trust a cached copy.
Cite this pageshipcheck. "Why React Native apps fail the privacy manifest check." Baker Ventures LLC, September 4, 2026. https://shipcheck.bakerventuresstudio.com/rejections/react-native-privacy-manifest