Apple has required a Privacy Manifest (PrivacyInfo.xcprivacy) for all iOS app submissions since May 2024. An app without one — or with an incomplete one — is rejected at review. Beyond compliance, the manifest forces an audit of every SDK that touches protected APIs (NSUserDefaults, file timestamps, disk space, system boot time, active keyboard). GDPR Art. 13 requires informing users of the legal basis and purpose of data collection before collection begins; the Privacy Manifest is Apple's enforcement mechanism for that disclosure at the SDK layer. Missing reason codes for third-party SDKs (e.g., Firebase, Amplitude) are the most common rejection cause, because those SDKs access protected APIs on your behalf even if your own code does not.
Critical because a missing or incomplete Privacy Manifest causes immediate App Store rejection and signals unchecked SDK data access that violates GDPR Art. 13 disclosure requirements.
Create ios/PrivacyInfo.xcprivacy and declare every protected API your app and its SDKs access. Check each SDK's documentation for its required reason codes.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist>
Run xcrun privacy-assistant (Xcode 15+) to detect SDK API access automatically. Add a <dict> block for each accessed API category. Missing entries for Firebase Crashlytics, Amplitude, or Segment are the most common rejection sources — check each SDK's published reason codes.
ID: mobile-permissions-privacy.permission-requests.privacy-manifest-ios
Severity: critical
What to look for: For iOS apps, check for a PrivacyInfo.xcprivacy file in the ios/ directory. Count all required sections: NSPrivacyTracking, NSPrivacyTrackingDomains, NSPrivacyAccessedAPITypes, NSPrivacyAccessedAPITypeReasons. Enumerate all third-party SDKs that access protected APIs and check each is documented.
Pass criteria: A PrivacyInfo.xcprivacy file exists with at least 2 required sections (NSPrivacyTracking and NSPrivacyAccessedAPITypes), and all third-party SDKs that access protected APIs are documented with reason codes.
Fail criteria: No PrivacyInfo.xcprivacy file exists, OR the file is incomplete (missing NSPrivacyAccessedAPITypes for dependencies that access protected APIs), OR the file is invalid XML. Do NOT pass when the file exists but contains only placeholder or empty arrays.
Skip (N/A) when: App is Android-only and has no iOS build (no ios/ directory and no iOS target in app.json).
Detail on fail: Quote the actual file contents or note absence. Example: "No PrivacyInfo.xcprivacy file found in ios/ directory" or "PrivacyInfo.xcprivacy exists but missing NSPrivacyAccessedAPITypes entries for Firebase Analytics"
Remediation: Apple requires all iOS apps to declare their privacy practices in a Privacy Manifest. Create ios/PrivacyInfo.xcprivacy:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist>
Reference Apple's Privacy Manifest documentation to add the correct reason codes for each API your app and its SDKs access.