Apple privacy manifest: verify PrivacyInfo.xcprivacy before you upload

A privacy manifest is not paperwork you write once and forget. It is a file Apple parses on every upload, and a single missing declaration — often inside an SDK you didn't write — bounces the whole binary. This page mirrors the exact check: is PrivacyInfo.xcprivacy in the bundle, and does it declare every required-reason API that gets called?

Last reviewed 24 July 2026.

What a privacy manifest actually is

PrivacyInfo.xcprivacy is a property-list file that ships inside your app bundle (and, separately, inside each framework or SDK). It declares three things: the data types your code collects, the tracking domains it contacts, and — the part that causes rejections — the “required-reason” APIs it calls together with an approved reason for each. It is a plain XML plist; you can open it in any text editor.

Apple introduced it so that any API that has historically been abused for device fingerprinting can only be called with a declared, allow-listed justification. There is no runtime enforcement on-device — the enforcement happens at upload, statically, by scanning your binary for symbol references and comparing them against what your manifest declares.

Apple's enforcement timeline

The requirement did not arrive as a hard block. It escalated from an informational email to an outright rejection over the course of 2024, and Apple keeps extending the required-reason list.

WhenWhat changed
25 Mar 2024Apple began emailing developers (informational only) when an uploaded build referenced a required-reason API without declaring it in a manifest. Uploads still went through.
1 May 2024App Store Connect stopped accepting new apps and updates that call a required-reason API without a valid declaration. The email became a hard block — the build fails processing.
From 2024 onApple expanded the list of “commonly used” third-party SDKs that must ship their own signed privacy manifest, and added categories. The set is not frozen — an SDK that passed last year can trip the check after an Apple list update.
Source: Apple Developer — “Upcoming third-party SDK requirements” and the required-reason API documentation.

The required-reason API categories and their codes

There are five categories. The four you will meet most often are below, each with the NSPrivacyAccessedAPIType constant you put in the manifest and the reason codes Apple allows. (The fifth, active keyboards, applies almost exclusively to custom-keyboard apps.) You declare a category once with an array of the reason codes that apply to how you use it.

A reason code is not free-form: Apple rejects any value that is not on its allow-list for that category (that is a separate error, ITMS-91055). Pick the code that matches your actual use.

File timestamp APIs

NSPrivacyAccessedAPICategoryFileTimestamp

Reason codeWhen it applies
DDA9.1Show a file's timestamp to the person using the device. The value must not leave the device.
C617.1Read metadata (timestamps, size) of files inside your own app container, App Group container, or CloudKit container.
3B52.1Read metadata of files or directories the user explicitly granted access to — e.g. a file chosen through a document picker.
0A2A.1You are a third-party SDK: you wrap a file-timestamp API and only touch it when the host app calls your wrapper.

User defaults APIs

NSPrivacyAccessedAPICategoryUserDefaults

Reason codeWhen it applies
CA92.1Read and write data that belongs only to your app — not shared with other apps or the system.
1C8F.1Read and write user defaults shared across the apps, extensions and App Clips in your own App Group.

System boot time APIs

NSPrivacyAccessedAPICategorySystemBootTime

Reason codeWhen it applies
35F9.1Measure the elapsed time between events inside your app, or to drive a timer. (Boot time was a classic fingerprinting vector — hence the required reason.)

Disk space APIs

NSPrivacyAccessedAPICategoryDiskSpace

Reason codeWhen it applies
85F4.1Display available disk space to the person using the device.
E174.1Check there is enough space before writing a file, or free space when the disk is low.

Each category also has a dedicated “third-party SDK wrapper” reason — if you ship an SDK, you declare the wrapper code, not the app-level one. The five categories today are file timestamp, user defaults, system boot time, disk space and active keyboards; Apple has said the list will grow.

The trap nobody warns you about: a missing SDK manifest fails YOUR app

Most guides stop at “add a PrivacyInfo.xcprivacy to your app target.” That is not enough. Apple scans every binary in the bundle — including every framework, static library and resource bundle a dependency drags in. If an ad, analytics, or attribution SDK calls one of these APIs and does not carry its own manifest, the rejection is issued against your app, naming the SDK's path. Your own code can be spotless.

Apple maintains a list of “commonly used SDKs” that must both ship a manifest and be code-signed. Common offenders and their fixes are usually just a version bump — the maintainers shipped manifest-bearing releases in early 2024:

  • Firebase / GoogleUtilities — fixed from the Firebase 10.22 line onward.
  • Alamofire — manifest added in 5.9.0.
  • Ad and attribution SDKs (AppLovin, Facebook/Meta, AppsFlyer, Adjust) — the versions Apple flags are the ones without a bundled manifest; update to the SDK's current release.
  • Any private/internal framework you build — it needs its own PrivacyInfo.xcprivacy declaring what it calls, exactly like a public SDK.

So the debugging order when you get ITMS-91053 is: (1) read which API and which binary path the email names, (2) if the path is inside a framework, update or replace that SDK, (3) only if it is your own code, add the declaration to your app manifest.

How to inspect PrivacyInfo.xcprivacy inside an .ipa without Xcode

An .ipa is a ZIP. You can audit a shipped build on any machine — no Xcode, no signing — with three commands:

# 1. Unzip the archive
unzip -o MyApp.ipa -d ipa_out

# 2. Print the app-level manifest, human-readable
plutil -p ipa_out/Payload/*.app/PrivacyInfo.xcprivacy

# 3. Find EVERY manifest in the bundle — yours and each SDK's
find ipa_out/Payload -name 'PrivacyInfo.xcprivacy'

If step 2 errors with “No such file,” your app target has no manifest at all. If step 3 returns fewer files than you have SDKs that touch these APIs, the missing ones are your ITMS-91053 candidates. On a machine without plutil (non-macOS), the file is XML — open it in any editor and look for the NSPrivacyAccessedAPITypes array.

To see which required-reason symbols are actually referenced, `nm -u ipa_out/Payload/*.app/MyApp | grep -Ei 'stat|NSUserDefaults|systemUptime|volumeAvailableCapacity'` gives a fast signal for the app binary itself.

The rejection email, decoded

Apple delivers these as an email titled with an ITMS code after the build finishes processing. Two codes matter here — they mean different things and have different fixes:

CodeWhat Apple meansFix
ITMS-91053“Missing API declaration.” Your binary (or a bundled SDK) calls a required-reason API but no manifest declares that category. The email names the API category and the file path.Add the category + a valid reason code to the right manifest — or update the SDK named in the path.
ITMS-91055“Invalid API reason declaration.” You declared a reason code that is not on Apple's allow-list for that category — a typo, an invented code, or one Apple removed.Replace it with an approved code from the category's list above.
ITMS-91056“Invalid signature” on a bundled SDK — an SDK on Apple's list ships a manifest but is not signed, or the signature doesn't validate.Update to a signed release of that SDK.

The three-step fix

  1. Read the email: note the exact API category and the binary path it names. Path inside a .framework/.bundle = SDK problem. Path at your app root = your problem.
  2. For an SDK: bump it to a version that ships a signed PrivacyInfo.xcprivacy. For your own code: add the category and a matching reason code to your app's manifest.
  3. Re-archive, upload, and confirm the build clears processing — the email arrives (or doesn't) within minutes of processing, before the build is reviewable.

Already holding a rejection email and not sure which bucket it falls into? Paste the wording into the rejection decoder

FAQ

Do I need a privacy manifest if my app doesn't collect any data?

Possibly, yes. The manifest is required not only for data collection but for calling any required-reason API. A trivial app that reads UserDefaults or checks a file's modification date already triggers the requirement, even if it collects nothing about the user.

My own code is clean but I still got ITMS-91053. Why?

Almost always a bundled SDK. Apple scans every binary in the .ipa; a dependency that calls one of these APIs without its own manifest fails the whole build under your name. The email names the file path — if it points inside a .framework, update that SDK.

What's the difference between a privacy manifest and the App Store privacy 'nutrition label'?

The nutrition label is what you fill in on the App Store Connect website and what users see on the listing. The privacy manifest is a file inside the binary that Apple parses automatically; Apple uses it to generate/validate the label and to enforce required-reason APIs. They must be consistent, but they are different artifacts.

Does adding the manifest slow down App Review?

No — the required-reason check is automated and runs at upload processing, before human review. It either passes or bounces the build within minutes. It does not add to the review queue time; it just gates whether your build reaches the queue at all.

Can I declare every reason code to be safe?

No. Declaring a reason you don't actually use is itself a violation, and declaring an invalid code triggers ITMS-91055. Declare only the category you call and only the code that matches your real usage.

Related: iOS export compliance (ITSAppUsesNonExemptEncryption) · The most common App Store rejection reasons

Sources

Check your build before you submit

Run your .ipa or .apk through App Review Checker and catch these issues in seconds.

Check an app