Blogs

Unity iOS Privacy Manifest Guide: Required Reason APIs, Plug-ins, and ITMS Errors

Last updated: September 27, 2026

A Unity iOS submission can contain privacy declarations from at least three owners: your game or app, the Unity engine, and third-party plug-ins. App Store Connect evaluates the packaged result, not the tidy structure visible in the Unity Editor. That is why adding one PrivacyInfo.xcprivacy file to the Xcode project can appear to fix one warning while leaving a plug-in's ITMS-91061 failure untouched.

The reliable workflow is to identify the bundle Apple named, decide which owner is responsible, and then inspect the exported archive. This guide follows Unity's own privacy-manifest guidance and Apple's SDK ownership rules.

Quick answer: put app-owned declarations in a manifest tracked with the Unity project, verify Unity's engine declarations for the version you ship, and require every affected third-party framework or plug-in to provide its own manifest. Never copy a plug-in's declarations into the main app manifest as a shortcut for ITMS-91061.

Understand the three manifest owners

OwnerExamplesWhere the durable fix belongs
Your applicationNative code you wrote, data collection you control, app-specific tracking domainsThe app's source-controlled privacy manifest
Unity enginePlayerPrefs, AssetBundle disk checks, engine timing and file APIsA supported Unity version and Unity-provided engine manifest
Third-party plug-in or SDKAds, analytics, sign-in, notifications, attribution, social SDKsThe plug-in or SDK bundle and its vendor release

Unity's current Apple privacy manifest policy documentation says third-party SDKs, packages, and plug-ins must provide their own manifests when applicable. Apple's third-party SDK requirements also list UnityFramework and many SDKs commonly embedded in Unity games.

Classify the App Store Connect error

ITMS-91053: Missing API declaration

Apple detected a Required Reason API category but did not find an accepted reason covering the use. Determine whether the call comes from your code, Unity engine code, or a plug-in before choosing a reason.

ITMS-91056: Invalid privacy manifest

Apple found a manifest but rejected its structure or values. The error path matters: it may point to the app manifest, UnityFramework.framework, or a third-party framework inside the exported app.

ITMS-91061: Missing privacy manifest

Apple identified a privacy-impacting third-party SDK without its required manifest. Upgrade or correct the SDK itself. Adding the SDK's declarations to the top-level application manifest is not the safe fix.

Use the App Store Privacy Error Checker to extract the error code, framework path, SDK name, and API category from the email. Everything stays in the browser. Keep the original path with your release evidence.

Step 1: record the Unity build context

Before changing packages, record:

  • Unity editor version and patch level.
  • iOS Build Support module version.
  • Scripting backend and architecture.
  • Installed packages from Package Manager.
  • Native .framework, .xcframework, .a, and .bundle files under Assets/Plugins.
  • Custom post-process build scripts.
  • The exact Xcode archive and build number Apple analyzed.

The same C# project can produce a different native bundle graph after a Unity upgrade or package change. Without the build context, a successful resubmission does not tell you which component fixed the problem.

Step 2: inventory manifests and native plug-ins in Unity

From the Unity project root, list source manifests:

find Assets Packages -name PrivacyInfo.xcprivacy -print 2>/dev/null

Then inventory native dependencies:

find Assets/Plugins -type f \
  \( -name "*.framework" -o -name "*.xcframework" -o -name "*.a" -o -name "*.bundle" \) \
  -print

Package Manager content may be cached outside Assets, so also review the resolved Packages/manifest.json and Packages/packages-lock.json. For each SDK named in Apple's email, identify the Unity package or asset that delivered it.

If a plug-in contains a manifest, select it in the Unity Editor and verify that its Plugin Inspector settings include iOS. A file present in the repository but excluded from the platform will not reach the exported Xcode project.

Step 3: create the app-owned manifest

Unity instructs app developers to create the privacy manifest and save it under Assets/Plugins. Teams often use an iOS-specific subfolder such as Assets/Plugins/iOS, but the important points are that the file is source controlled, enabled for iOS, and copied into the correct application target.

A minimal Required Reason API section has this shape:

<?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>NSPrivacyAccessedAPITypes</key>
  <array>
    <dict>
      <key>NSPrivacyAccessedAPIType</key>
      <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
      <key>NSPrivacyAccessedAPITypeReasons</key>
      <array>
        <string>CA92.1</string>
      </array>
    </dict>
  </array>
</dict>
</plist>

Do not use this example simply because the app calls PlayerPrefs. Current supported Unity versions already document engine-owned declarations. Add an app declaration only when it accurately represents behavior your application owns and the approved reason conditions are satisfied.

Read Apple's current Required Reason API documentation before committing a reason. The Required Reason API Checker can detect known category/code mismatches, but it cannot decide whether a reason truthfully describes your feature.

Step 4: understand Unity's documented engine reasons

Unity 6.0 documentation lists the following engine declarations:

CategoryDocumented reasonUnity behavior
File timestamp APIs0A2A.1C# timestamp APIs
File timestamp APIsC617.1File checks
User defaults APIsCA92.1PlayerPrefs
System boot time APIs35F9.1Calculating time between events
Disk space APIsE174.1AssetBundle disk-space checks

This table is not a template for adding all five reasons to every app. It is a diagnostic map for understanding engine calls. Verify the documentation for the exact Unity release you ship, because package contents and generated manifests can change between editor versions.

If ITMS-91053 names one of these categories and the archive lacks the Unity engine manifest, upgrade to a supported Unity patch and inspect the exported UnityFramework.framework. Do not mask a missing engine resource by declaring unrelated app behavior.

Step 5: handle third-party plug-ins separately

Advertising, analytics, attribution, authentication, and notification plug-ins often embed their own native frameworks. For each plug-in:

  1. Find the native framework named in Apple's message.
  2. Identify the Unity asset or package that delivered it.
  3. Check the vendor's current iOS release notes for privacy-manifest support.
  4. Upgrade the plug-in and its embedded SDK together.
  5. If no supported version exists, replace, remove, or obtain a corrected build from the vendor.
  6. Confirm the manifest is inside the plug-in or SDK bundle after export.

If you are the plug-in author, put the declarations with the native code they describe. A .framework should contain its own accurate PrivacyInfo.xcprivacy when required. If you distribute loose native source instead, ensure the manifest is included as an iOS resource and document the integration for downstream Unity developers.

For ITMS-91061, do not copy a vendor's manifest into the top-level app and call the issue complete. Apple's requirement applies to the privacy-impacting SDK identified in the email. The ITMS-91061 guide explains why the SDK bundle is the repair target.

Step 6: validate XML and manifest semantics

Validate the source file before exporting:

plutil -lint Assets/Plugins/iOS/PrivacyInfo.xcprivacy
plutil -p Assets/Plugins/iOS/PrivacyInfo.xcprivacy

Adjust the path to match your project. Then use the PrivacyInfo.xcprivacy Validator to check:

  • Supported top-level keys.
  • The expected value type for every key.
  • Empty arrays and empty strings.
  • Required Reason API categories and codes.
  • Tracking-domain formatting.

A tracking domain must be a hostname, not a URL. This is invalid:

https://analytics.example.com/collect/?game=1

The domain value would be written as:

analytics.example.com

Whether it belongs in NSPrivacyTrackingDomains depends on actual tracking behavior and consent—not only its syntax.

For ITMS-91056, validate the exact manifest path reported by Apple. Apple's TN3181 is the primary debugging reference.

Step 7: inspect the exported Xcode project

After Unity exports the iOS project, search it before opening Xcode:

find /path/to/Unity-iPhone -name PrivacyInfo.xcprivacy -print

In Xcode, verify:

  • The app-owned manifest belongs to the Unity-iPhone application target.
  • Unity's engine manifest is packaged with UnityFramework for the shipped editor version.
  • Each affected third-party framework contains or correctly resources its own manifest.
  • Custom post-process scripts did not rename, replace, or drop a manifest.
  • Duplicate resources do not cause one manifest to overwrite another.

If you use a PostProcessBuild script, inspect its output rather than assuming the script still matches the generated Xcode project structure. Build-pipeline code written before privacy manifests existed is a common place for resource-copy omissions.

Step 8: inspect the archive that will be uploaded

Create a Release archive in Xcode. Then list all packaged manifests:

find /path/to/Unity-iPhone.xcarchive -name PrivacyInfo.xcprivacy -print

Validate every result:

find /path/to/Unity-iPhone.xcarchive -name PrivacyInfo.xcprivacy -print0 \
  | xargs -0 -n1 plutil -lint

Follow the framework path from Apple's email into:

Products/Applications/YourGame.app/Frameworks/

The archive should demonstrate that the responsible bundle contains a valid manifest. A correct file under Assets/Plugins is not enough if the export or Xcode build drops it.

Common Unity failure patterns

The manifest disappears after every export

The source file is not imported for iOS, or a custom build script owns the generated project. Fix the Unity source and pipeline rather than manually editing each Xcode export.

ITMS-91056 names an advertising framework

Validate that framework's manifest, update the advertising SDK, and avoid replacing it with the app manifest. The vendor owns the framework declaration.

ITMS-91061 persists after adding an app manifest

This is expected when Apple named a third-party SDK. Upgrade or replace the SDK and verify its bundle in the archive.

A reason code works for another Unity game

That does not make it valid for this game. Approved reasons describe behavior, not merely API symbols or engine choice.

The repository contains several manifests with the same filename

That can be correct when they belong to separate bundles. The filename is standardized; bundle ownership and packaged location distinguish the declarations.

Final Unity submission checklist

  • Unity editor, package, plug-in, and SDK versions are recorded.
  • Every Apple error path is mapped to its owning bundle.
  • App-owned declarations are tracked under Assets/Plugins and enabled for iOS.
  • Unity engine declarations match the shipped editor version.
  • Third-party plug-ins provide their own manifests where required.
  • All source and archived manifests pass plutil -lint.
  • Tracking domains contain no scheme, path, query, fragment, or trailing slash.
  • The archive—not only the Unity project—contains the expected files.
  • A developer confirms each reason against actual app or SDK behavior.

This guide cannot guarantee App Review approval and is not legal advice. Privacy manifests are technical declarations about the exact binary you ship, so re-check them whenever Unity, a package, or a native SDK changes.

Parse the rejection email and validate the manifest locally before exporting another Unity iOS build.

Check My Privacy Manifest