Privacy Manifest Lint - xcprivacy & ITMS-91053

Checks PrivacyInfo.xcprivacy and your C#, Dart, JS, Swift and Kotlin source for Apple required-reason APIs, and decodes all 17 reason codes back to the category they belong to.

Find a tool

Install free

Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.

VS Code MarketplaceOpen VSX (Cursor, VSCodium)npmMCP server (npx)Docker Hub
ext install ReadyStack.privacy-manifest-lint
npx @readystack/privacy-manifest-lint <file>
npx @readystack/privacy-manifest-lint --mcp

Team? One key for every ReadyStack linter, 5 seats, $149 once

Get the full rule table as a PDF
All 48 rules Privacy Manifest Lint - xcprivacy & ITMS-91053 checks, each with its source and date, on printable pages you can hand to your team or auditor. We email it now, and once more only if a rule changes. No newsletter.

Get the full version $29

Checks PrivacyInfo.xcprivacy and your C#, Dart, JS, Swift and Kotlin source for Apple required-reason APIs, and decodes all 17 reason codes back to the category they belong to.

One payment, one licence key for this tool. The key is shown right after payment.

An experienced freelance iOS developer bills $85-145/hour in 2026.

Buy the full version — $29

· ReadyStack

Worked example

Real numbers from this tool, line by line.

Five defects in a seven-line privacy manifest

Five defects come out of the seven-line PrivacyInfo.xcprivacy below, and they belong to the .NET MAUI, Flutter and React Native teams shipping iOS apps to Apple's App Store.

line 1: The key is NSPrivacyAccessedAPIType; the category name is its <string> value, not the key. Upload returns ITMS-91056.
line 2: Category is plural: NSPrivacyAccessedAPICategoryUserDefaults. Upload returns ITMS-91056.
line 3: The key is NSPrivacyAccessedAPITypeReasons. "Type" is missing here. Upload returns ITMS-91056.
line 5: Not a reason code Apple issues. Exactly 17 exist and every one ends in ".1".
line 6: AC6B.1 belongs to NSPrivacyAccessedAPICategoryUserDefaults - read com.apple.configuration.managed or write com.apple.feedback.managed for MDM managed app configuration - MDM ONLY.

Those five came out of these seven lines, which is the whole file:

<key>NSPrivacyAccessedAPICategory</key>
<string>NSPrivacyAccessedAPICategoryUserDefault</string>
<key>NSPrivacyAccessedAPIReasons</key>
<array>
	<string>CA92.2</string>
	<string>AC6B.1</string>
</array>

The last finding is the expensive one, and it is the reason a language model is a bad place to get these. Ask a chatbot which reason code covers an SDK wrapper around NSUserDefaults and AC6B.1 is a very plausible answer. It is also wrong, it looks correct in the file, and nothing on your machine tells you otherwise. App Store Connect tells you, with ITMS-91055 or ITMS-91056, after the build, on the day you were going to release.

The second half of the problem is where the call actually lives. Apple's tooling inspects Swift and Objective-C. A .NET MAUI app reaches user defaults through Preferences.Default, reads the boot clock through Environment.TickCount, and calls stat through File.GetLastWriteTime. Flutter does it through shared_preferences and File.lastModifiedSync. React Native does it through react-native-device-info. None of those lines are Swift, so none of them show up in the place you are looking.

Privacy Manifest Lint is a VS Code extension and a free web page that read both halves. Open a PrivacyInfo.xcprivacy and it decodes every reason code in it back to the category Apple assigns it to, quoting Apple's own condition on that line, and flags any code Apple never issued. Open a .cs, .dart, .ts, .swift, .m or .kt file and it names the required-reason API you called, the category to declare, and the codes you are allowed to choose from. It ships 48 rules and all 17 reason codes, and it runs entirely on your machine - the file is never uploaded anywhere.

The free version checks one open file completely - every rule, every code, no watermark, no trial clock. The paid version changes the scope rather than the quality: the whole repository instead of one file, the report exported as CSV, JSON or HTML, CI JSON so a pipeline fails before App Store Connect does, and an in-place fix for the misspelled keys. That is $29 once.

Paste your manifest into the free page first. If it comes back clean, you have lost nothing but a minute. If it comes back with five findings, you have just kept a release date.

15 seconds — what it actually does

Questions people ask

What does Privacy Manifest Lint actually do?

It reads a PrivacyInfo.xcprivacy file, or a source file, and reports two things. In the manifest it decodes every required-reason code back to the category Apple assigns it to, and flags codes Apple never issued. In source it finds required-reason API call sites in C#, Dart, JavaScript, TypeScript, Swift, Objective-C and Kotlin, and names the category and the codes you may declare.

Who is this for?

Teams shipping iOS apps built with .NET MAUI, Flutter, React Native, Xamarin or Capacitor. Xcode inspects Swift and Objective-C, so cross-platform code is where required-reason API use hides. If your upload came back with ITMS-91053, ITMS-91055, ITMS-91056 or ITMS-91061, this is the file-level check that finds the cause.

Why not just ask a chatbot for the reason code?

Because the codes are opaque four-character strings and a language model produces plausible ones that do not exist. AC6B.1 is a real code, but it is only for MDM managed app configuration; the third-party SDK wrapper code is C56D.1. A wrong pairing looks correct in the file and is rejected at upload, after the build.

What is free and what does the paid version add?

The free version checks one open file completely, with every rule and every reason code, and the free web page does the same in a browser. The paid version changes the scope, not the quality: it scans the whole repository, exports the report as CSV, JSON or HTML, writes CI JSON so a pipeline can fail early, and fixes misspelled manifest keys in place.

What does the alternative cost?

An experienced freelance iOS developer bills 85 to 145 US dollars an hour in 2026, so a single afternoon of hunting reason codes and resubmitting costs several hundred dollars. A rejected upload also costs a review cycle, which is the part that moves a release date. The full version is 29 dollars once,.

Why not just ask ChatGPT or another AI chat?

A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. Privacy Manifest Lint checks the file you open against 48 rules from a rule set dated 2026-09-20, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files.

Ask about this tool

One question, answered by the person who built it. Your email only if you want the answer sent.

Embed this tool on your site (free)

Paste this code into your page. It runs in your visitor’s browser and stays up to date. Nothing your visitors type is stored.

 All embeddable tools

For businesses: your name and logo instead of ours, and each visitor’s result + e-mail in your inbox (only when they tick consent) — Pro from $19/month. See Pro →