The Privacy Manifest Deep Dive: What Counts As Data Collection
Since May 1, 2024, every app and third-party SDK uploaded to App Store Connect has needed a privacy manifest declaring its use of “required reason APIs,” its tracking behavior, and its collected data types1. The manifest is a property list (PrivacyInfo.xcprivacy) that the App Store ingests at submission time, validates against a known surface of privacy-sensitive APIs, and surfaces in the user-facing privacy nutrition label. Apps that omit the manifest, or that use a privacy-sensitive API without declaring an approved reason, get rejected at submission with ITMS-91053 or related codes2.
Most teams treat the manifest as a one-time compliance task: write it, ship it, never look at it again. The manifest is more than that. It is a structured contract between the app and Apple that codifies what the app does with private data, and it is the only place this contract exists in machine-readable form. Reading it carefully reveals what Apple considers privacy-sensitive (the surface area is broader than most developers expect), what the user actually sees in the nutrition label (more granular than most teams realize), and what third-party SDKs have to disclose (a real obligation, not a courtesy).
TL;DR
- The privacy manifest has four top-level sections:
NSPrivacyTracking,NSPrivacyTrackingDomains,NSPrivacyCollectedDataTypes, andNSPrivacyAccessedAPITypes3. - The Required Reason API list covers five initial categories: file timestamp, system boot time, disk space, active keyboards, and User Defaults. Each category has a closed list of approved reason codes; apps must pick one or rewrite to avoid the API4.
- Tracking is defined narrowly: linking user data to data from other companies for advertising or sharing with data brokers. If
NSPrivacyTrackingistrue, every domain used for tracking must appear inNSPrivacyTrackingDomains3. - Third-party SDKs must ship their own manifests. The app’s manifest is merged with the manifests of all linked SDKs at submission; missing SDK manifests on the Apple-published list block the app5.
- The biggest gotcha:
UserDefaultsaccess always counts as a Required Reason API call. A standardUserDefaults.standard.set(...)requires a declared reason code.
The Four Sections
A complete PrivacyInfo.xcprivacy file has four top-level keys3. The structure is a property list, edited as XML in raw form or through Xcode’s privacy manifest editor.
NSPrivacyTracking (Boolean)
Declares whether the app or SDK tracks the user across other companies’ apps and websites. The semantic definition aligns with App Tracking Transparency: linking user data to data from other companies for the purpose of targeted advertising, delivering targeted advertising, or sharing user data with data brokers6.
If NSPrivacyTracking is true, every domain used for tracking must appear in the NSPrivacyTrackingDomains list. If false, the list is omitted (or empty).
The narrow definition matters. Many apps that show ads (through Apple’s own SKAdNetwork or non-tracking ad SDKs) can declare NSPrivacyTracking as false. Tracking is the linkage to external data, not the showing of ads.
NSPrivacyTrackingDomains (Array of strings)
The list of domains the app or SDK contacts for tracking purposes. Apps that declare NSPrivacyTracking as true must enumerate every tracking endpoint here.
The list is enforced at runtime via App Privacy Report: if the app contacts a domain that’s flagged as tracking but not declared, the App Privacy Report surfaces the discrepancy to the user. Repeated violations risk App Store removal.
NSPrivacyCollectedDataTypes (Array of dictionaries)
The structured data-collection declaration that feeds the App Store privacy nutrition label3. Each entry describes one data type the app collects, with sub-keys:
NSPrivacyCollectedDataType: the data type from Apple’s closed list (e.g.,NSPrivacyCollectedDataTypeName,NSPrivacyCollectedDataTypeEmailAddress,NSPrivacyCollectedDataTypeCrashData).NSPrivacyCollectedDataTypeLinked: Boolean, whether the data is linked to the user’s identity.NSPrivacyCollectedDataTypeTracking: Boolean, whether the data is used for tracking.NSPrivacyCollectedDataTypePurposes: array, the purposes for which the data is collected (analytics, app functionality, advertising, etc.).
This section is the source of truth for the privacy nutrition label. The nutrition label’s “Data Used to Track You” and “Data Linked to You” categories are computed from these flags. Inaccurate declarations produce inaccurate nutrition labels and risk App Store enforcement action.
NSPrivacyAccessedAPITypes (Array of dictionaries)
The Required Reason API declaration. Each entry pairs a Required Reason API category with a set of approved reason codes4.
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
</array>
The reasons are closed lists. The app picks one or more from Apple’s published list per category; arbitrary strings are rejected at submission.
The Five Required Reason API Categories
Apple’s initial 2024 list defined five categories of API that require a declared reason4:
NSPrivacyAccessedAPICategoryFileTimestamp
Triggered by any API that returns file creation, modification, or access time. Common entry points: URL.resourceValues(forKeys: [.creationDateKey, ...]), FileManager.attributesOfItem(atPath:), stat(), fstat(), lstat(). The four approved reasons4:
- DDA9.1. Show file timestamps to the device user. Information accessed for this reason cannot be sent off-device.
- C617.1. Access file metadata (timestamps, size, etc.) for files within the app’s container, app group container, or CloudKit container.
- 3B52.1. Access file metadata for files or directories the user has explicitly granted access to (document picker, etc.).
- 0A2A.1. Third-party SDK wrappers that access file timestamp APIs only when the app calls the wrapper. SDK-only.
Most apps use C617.1 (own-container access) for internal file management. Apps that show file dates in user-facing UI use DDA9.1. Apps that read user-granted files (document picker, share extension targets) use 3B52.1. SDK authors use 0A2A.1 only.
NSPrivacyAccessedAPICategorySystemBootTime
Triggered by mach_absolute_time(), mach_continuous_time(), and related uptime APIs. The privacy concern: system boot time is a fingerprintable signal that can be used to identify the device across reinstalls. The three approved reasons4:
- 35F9.1. Access system boot time to measure time intervals between app events or to enable timers.
- 8FFB.1. Access system boot time to calculate absolute timestamps of events within the app.
- 3D61.1. Add system boot time information in an optional bug report the user chooses to submit.
Most apps use 35F9.1 for performance measurement. 8FFB.1 covers cases where the app derives event timestamps from boot time (relative to the device session). Note that Date() and Date.now do not trigger this category; they use a different time source. The category covers mach_*_time family calls specifically.
NSPrivacyAccessedAPICategoryDiskSpace
Triggered by APIs that return disk capacity or free space, including URL.resourceValues(forKeys: [.volumeAvailableCapacityKey, ...]) and NSFileManager’s file-system attributes APIs. The privacy concern: disk-space patterns are a fingerprintable signal. The four approved reasons4:
- 854F.1. Display disk space information to the device user, in either data units or media-time units.
- E174.1. Check disk space when writing files or to manage low disk space (deciding whether to download an asset, cleaning up cached files).
- 7D9E.1. Include disk space information in an optional bug report the user chooses to submit.
- B728.1. Health-research apps detecting and informing participants about low disk space affecting study data collection.
NSPrivacyAccessedAPICategoryActiveKeyboards
Triggered by UITextInputMode.activeInputModes. Apps that read this list (typically to localize behavior or detect input language) must declare a reason. The two approved reasons4:
- 3EC4.1. A custom keyboard app determining the active keyboards on the device.
- 54BD.1. Accessing active keyboard information to customize the user interface accordingly (typically for input-language-aware UX).
Most apps don’t need this category. If your code calls activeInputModes indirectly through a third-party library, that library’s manifest declares it.
NSPrivacyAccessedAPICategoryUserDefaults
The category that catches almost every app. Any access to UserDefaults (UserDefaults.standard, app group defaults via init(suiteName:), individual set/get calls) triggers the requirement7. The four approved reasons4:
- CA92.1. Access user defaults to read/write data exclusive to the app itself (or to an app extension paired only with the app).
- 1C8F.1. Access user defaults to read/write data only within apps, app extensions, and App Clips that are members of the same App Group.
- C56D.1. Third-party SDK wrappers that access user defaults APIs only when the app calls the wrapper. SDK-only.
- AC6B.1. Access user defaults to retrieve managed app configurations set by an MDM/IT administrator, or to store feedback information for the administrator.
Almost every iOS app uses UserDefaults.standard for at least one piece of state (the user’s last-selected tab, their preferred sort order, a feature flag). The CA92.1 reason covers it. Apps that share state across app extensions through an app group add 1C8F.1. SDK authors use C56D.1. Apps deployed through an MDM that read administrator-set keys (e.g., com.apple.configuration.managed) use AC6B.1.
The catch: a third-party SDK that touches UserDefaults triggers the requirement on behalf of the app. The SDK’s manifest must declare the reason. If the SDK is from Apple’s list of SDKs that must ship a privacy manifest, the absence of the SDK’s manifest blocks the app.
Tracking Domains: Runtime Validation
NSPrivacyTrackingDomains is enforced through App Privacy Report at runtime6. When an app declares NSPrivacyTracking = true, the system tracks every network request and matches the destination against the declared list. Domains contacted for tracking but not declared surface in App Privacy Report’s “Frequent Locations” and “Other Domains Contacted” sections.
The runtime validation creates an interesting incentive structure. An app that declares NSPrivacyTracking = false (no tracking) but is observed contacting known tracking domains gets flagged in App Privacy Report and risks user complaints. The right play is honest declaration.
For SDKs, the SDK’s privacy manifest declares its tracking behavior. The app’s manifest doesn’t need to enumerate the SDK’s tracking domains; the SDK’s manifest already does. At submission, Apple merges the manifests and checks consistency.
SDK Manifests: A Real Obligation
Third-party SDKs in two categories must ship a privacy manifest5:
- SDKs on Apple’s published list of SDKs requiring privacy manifests. The list includes Firebase Analytics, Google Mobile Ads, Adjust, Segment, AppsFlyer, and around 30 others as of iOS 26.
- SDKs distributed as pre-compiled binaries (XCFrameworks, static libraries) that the app links against.
Submission of an app that links a required SDK without the SDK’s manifest fails with an ITMS-91xxx series error covering missing privacy manifest, missing manifest signature, or missing API declaration in the SDK’s namespace2. The fix is either updating to a manifest-shipping version of the SDK or removing the SDK.
For first-party SDKs (your team ships an internal framework used by your apps), you can choose to skip the manifest if the framework isn’t on Apple’s list. The pragmatic move is to ship one anyway: future Apple list expansions, future audit work, future third-party reuse all benefit from having the manifest in place.
Common Gotchas
Five recurring failure modes from the App Store rejection logs:
1. Forgotten UserDefaults declaration. The most common rejection. App uses @AppStorage (which wraps UserDefaults) somewhere innocuous, manifest doesn’t declare it. Fix: every app that uses @AppStorage, UserDefaults, or any wrapper around them needs NSPrivacyAccessedAPICategoryUserDefaults with CA92.1.
2. Hidden file timestamp access through URLResourceValues. Code that reads file modification dates through URL.resourceValues(forKeys: [.contentModificationDateKey]) triggers the category, even though the call site doesn’t look like a stat.
3. SDK manifest expectations. App teams assume the SDK’s manifest is the SDK author’s problem. It is, but the app team’s submission fails until the SDK ships one.
4. NSPrivacyTracking = false despite linked tracking SDK. Linking Firebase Analytics or Google Mobile Ads with default settings often triggers tracking behavior. The app’s manifest declaring NSPrivacyTracking = false while the SDK’s manifest declares true produces a contradiction the merger flags.
5. Stale reason codes. Apple updates the approved reason codes occasionally. Codes that were valid in 2024 may be replaced or expanded. The fix is to re-check the current published list at every major release rather than copying old manifests forward.
Validation Tooling
Three checks worth running before submission:
Xcode’s “Generate Privacy Report” archive workflow. After Product > Archive, the Organizer offers a “Generate Privacy Report” action that produces an aggregate report from the app and every linked SDK’s manifest. The report is what App Store Connect ingests; running it locally is the closest equivalent to a pre-submission dry-run.
Static analysis on Required Reason APIs. Open-source tools scan a project for the API call sites that trigger the five categories. The community-maintained stelabouras/privacy-manifest CLI parses Swift sources and xcframework binaries to surface declared and undeclared reason codes; crasowas/app_store_required_privacy_manifest_analyser provides a similar scan. Either gives a useful pre-submission catch for missing declarations.
App Privacy Report cross-check. Run the app in iOS’s App Privacy Report mode (Settings > Privacy & Security > App Privacy Report). Domains the app contacts surface in the report; cross-check against the manifest’s tracking declarations.
What This Pattern Means For iOS 26+ Apps
Three takeaways.
-
Treat the privacy manifest as a structured contract, not a checkbox. The manifest is the only machine-readable record of what the app does with private data. Building it once, ignoring it forever, is the path to a rejected submission six months later when an SDK update silently expands the manifest’s required surface.
-
Audit your
UserDefaultsand file-timestamp access on every release. These are the two categories that quietly grow with the codebase. A@AppStorage-using SwiftUI view added in a refactor pullsNSPrivacyAccessedAPICategoryUserDefaultsinto scope; a file-listing feature added later pullsNSPrivacyAccessedAPICategoryFileTimestampin. Re-validate every time. -
Use SDKs that ship their own manifests. When evaluating a third-party SDK, the presence and quality of its privacy manifest is now a quality signal. SDKs without manifests force the app team to fight upstream; SDKs with manifests fold cleanly into the merge.
The full Apple Ecosystem cluster: typed App Intents; MCP servers; the routing question; Foundation Models; the runtime vs tooling LLM distinction; three surfaces; the single source of truth pattern; Two MCP Servers; hooks for Apple development; Live Activities; the watchOS runtime; SwiftUI internals; RealityKit’s spatial mental model; SwiftData schema discipline; Liquid Glass patterns; multi-platform shipping; the platform matrix; Vision framework; Symbol Effects; Core ML inference; Writing Tools API; Swift Testing; what I refuse to write about. The hub is at the Apple Ecosystem Series. For broader iOS-with-AI-agents context, see the iOS Agent Development guide.
FAQ
What’s the difference between NSPrivacyTracking and NSPrivacyCollectedDataTypeTracking?
NSPrivacyTracking is the app-level boolean: does this app track users (per Apple’s narrow definition) at all? NSPrivacyCollectedDataTypeTracking is per-data-type: for a given data type the app collects, is that data used for tracking? An app can collect data without tracking (analytics that doesn’t link across companies); the per-type flag captures whether each specific data type contributes to tracking behavior.
Do I need a privacy manifest for an internal-only TestFlight app?
Yes. Privacy manifest enforcement runs at submission to App Store Connect, including TestFlight builds. An internal beta without a manifest fails the same ITMS-91053 check as a public release.
What happens if I declare a Required Reason API without using it?
Nothing functional. The manifest declares an upper bound on the API surface; declaring an unused category is harmless. The cost is documentation drift: future maintainers may assume the declaration reflects current code, when in fact the call has been removed. The right move is to declare what the app actually uses, audited at every major release.
Are there any Required Reason API categories beyond the original five?
As of iOS 26, the original five categories (file timestamp, system boot time, disk space, active keyboards, User Defaults) remain the canonical list4. Apple has added approved reason codes within categories over time but has not expanded the category list. Watch Apple’s Required Reason API documentation page for additions.
How does the privacy manifest interact with App Tracking Transparency?
App Tracking Transparency (ATT) governs the runtime permission prompt for cross-app tracking. The privacy manifest declares the app’s intent statically. They are complementary: an app that does cross-app tracking declares NSPrivacyTracking = true in the manifest and requests ATT permission at runtime. An app declaring NSPrivacyTracking = false should not request ATT (the absence of cross-app tracking means the prompt is unnecessary).
References
-
Apple Developer Documentation: Privacy manifest files. The format reference and the May 1, 2024 enforcement timeline. ↩
-
Apple Developer: App Store Connect submission errors covering ITMS-91053 (missing API declaration) and related codes. ↩↩
-
Apple Developer Documentation: App privacy configuration. The four top-level keys (NSPrivacyTracking, NSPrivacyTrackingDomains, NSPrivacyCollectedDataTypes, NSPrivacyAccessedAPITypes) and their schemas. ↩↩↩↩
-
Apple Developer Documentation: Describing use of required reason API. The five Required Reason API categories with approved reason codes. ↩↩↩↩↩↩↩↩↩
-
Apple Developer: Third-party SDK privacy manifest requirements. The list of SDKs that must ship a privacy manifest. ↩↩
-
Apple Developer Documentation: User privacy and data use. The narrow definition of tracking and the App Tracking Transparency framework. ↩↩
-
Apple Developer Documentation:
NSPrivacyAccessedAPICategoryUserDefaults. The category covering allUserDefaultsaccess including@AppStorage-based wrappers. ↩