Verdict
App StoreGoogle Playone scan, both stores

Know why your app would be rejected.

Upload the build you are about to submit. Verdict reports what App Review would find, with the guideline and the fix.

Drop your .ipa, .apk, or .aab here

or click to choose a file. Up to 450MB.

Analyzed in seconds. Deleted right after. Never executed.

47of 100

App Store risk

Rejection likely

Trailhead 2.1.0 · com.example.trailhead

4 to resolve

Signed for distribution outside the App StoreVD-SIGN-01
Camera used with no purpose stringVD-PRIV-01
No privacy manifest at the bundle rootVD-PRIV-04
App Transport Security disabledVD-NET-01
Example report. Findings and scoring shown as the engine produces them.
Signing and provisioningEntitlementsPrivacy manifestPermission stringsTransport securityDeprecated APIsEmbedded SDKsData safetyGuideline citationsDaily policy trackingSigning and provisioningEntitlementsPrivacy manifestPermission stringsTransport securityDeprecated APIsEmbedded SDKsData safetyGuideline citationsDaily policy tracking

Verdict tells you why your app would be rejected, while you can still fix it.

Three steps, no configuration, and no account for the first look. Drop in the build you were about to ship and you get back the same findings a reviewer would reach, each one cited and paired with the change that clears it.

You upload

The build you were about to submit

An .ipa exported from Xcode, or an .apk or .aab from your Gradle release task.

Trailhead.ipa42.6 MB
.ipa.apk.aabup to 450MB
Verdict reads it

The same things a reviewer's tooling reads

Signatures, entitlements, manifests, permissions, embedded SDKs, and deprecated APIs. Nothing is executed.

CFBundleIdentifier
NSCameraUsageDescription
NSAppTransportSecurity
UIRequiredDeviceCapabilities
Info.plistMach-OAndroidManifestDEX
You get back

A score, and every problem with its fix

Each finding is cited to the rule it breaks and paired with the exact change that resolves it.

62
Blockers2
Warnings3
Advisories1
Risk scoreGuideline citedEvidenceThe fix

App review is the last gate before a release, and it is the one part of shipping a mobile app that developers have the least visibility into. Roughly a quarter of submissions are rejected, usually for something small and mechanical, and the feedback arrives days later as a guideline number with little explanation.

Verdict closes that gap. It reads the build you are about to submit and reports what a reviewer would find, before you spend a review cycle finding out. Every finding names the rule it comes from and shows the evidence in your own binary, so you can judge it rather than take our word for it.

It is built for the teams who feel this most: solo developers shipping their first app, studios releasing on a schedule, and anyone who has watched a launch slip because of a missing key in a configuration file.

What it is

A reviewer’s-eye read of the build you are about to submit, every finding cited to the rule it comes from.

What it’s not

Not an approval guarantee, and it does not speak for Apple or Google, or judge whether an app is original enough.

0
Checks on every build
0
Store policies tracked
0.0s
Median scan time
Verdict

An independent tool. Not affiliated with, endorsed by, or sponsored by Apple or Google.

SigningPrivacyMetadataPermissionsTransportCleared

Rejection is not random. It is a short list.

Apple publishes what it rejects and why. Five categories account for roughly nine in ten rejections, and most of what drives them is visible in the build before anyone submits it.

What Apple rejects apps for

Share of rejections by guideline family. Highlighted rows are categories Verdict inspects directly in your build.

App completeness2.1checked41%
Privacy and data5.1checked19%
Spam and templates4.314%
Inaccurate metadata2.3checked11%
Payments3.1checked9%
Everything elsemisc6%

Apple App Store transparency reporting and published rejection analyses, 2025 data.

Rejection rate, year over year

Share of all submissions rejected. Apple reports this annually, so 2025 is the most recent complete year on record.

0%in 2025, the latest full year

202020212022202320242025

Apple App Store transparency reports, 2025 figures published May 2026: 2M+ rejections across 9.1M submissions. Updated when Apple publishes the next report.

What one rejection actually costs

The same release, submitted twice versus checked once. Width is proportional to elapsed days.

Submitted without checking11 days
3d
1d
2d
5d
In reviewRejectedYou fix itBack in review
Checked with Verdict first3 days
1d
2d
You fix itIn review

Eight days back. Most of a rejection cycle is not your work, it is waiting. Reviewers usually stop at the first problem they hit, so the second pass often fails on something they never mentioned in the first.

Illustrative timeline based on commonly reported review and resubmission windows.

The notices you never want to read

These are the rejections developers actually receive, paraphrased from Apple and Google's published templates. Most of them come down to a fact that was already sitting in the build, which is the whole reason this tool exists.

5.1.1Data collection
Your app requests access to the camera but the purpose string does not explain how the data will be used.
Verdict flags this before you submit
2.1App completeness
We were unable to review your app because it was signed with a distribution profile that is not valid for the App Store.
Verdict flags this before you submit
Target APIDevice compatibility
Your app targets an API level below the current requirement. Update targetSdkVersion before this release can be published.
Verdict flags this before you submit
5.1.1(v)Account deletion
Your app supports account creation but does not include an option to initiate account deletion from within the app.
Verdict flags this before you submit
PermissionsSensitive access
Your app declares QUERY_ALL_PACKAGES without a permitted use case for broad package visibility.
Verdict flags this before you submit
2.5.1Software requirements
Your app links against a non public API, which is not permitted on the App Store.
Verdict flags this before you submit
Data safetyDisclosure
The data safety section does not accurately reflect the data types your app collects and shares.
Verdict flags this before you submit
5.1.1Data collection
Your app requests access to the camera but the purpose string does not explain how the data will be used.
Verdict flags this before you submit
2.1App completeness
We were unable to review your app because it was signed with a distribution profile that is not valid for the App Store.
Verdict flags this before you submit
Target APIDevice compatibility
Your app targets an API level below the current requirement. Update targetSdkVersion before this release can be published.
Verdict flags this before you submit
5.1.1(v)Account deletion
Your app supports account creation but does not include an option to initiate account deletion from within the app.
Verdict flags this before you submit
PermissionsSensitive access
Your app declares QUERY_ALL_PACKAGES without a permitted use case for broad package visibility.
Verdict flags this before you submit
2.5.1Software requirements
Your app links against a non public API, which is not permitted on the App Store.
Verdict flags this before you submit
Data safetyDisclosure
The data safety section does not accurately reflect the data types your app collects and shares.
Verdict flags this before you submit
5.1.2Tracking
Your app uses the AdSupport framework but does not request permission through App Tracking Transparency.
Verdict flags this before you submit
2.3.3Accurate metadata
The screenshots in your App Store listing do not show the app in use on the device it targets.
Judgement call, outside static analysis
ForegroundService types
Your app declares a foreground service type that is not matched by a declared and permitted use.
Verdict flags this before you submit
1.2User content
Your app includes user generated content but does not provide a mechanism to report offensive material.
Judgement call, outside static analysis
LocationBackground access
Your app requests background location access without an approved declaration for that use.
Verdict flags this before you submit
3.1.1Payments
Your app unlocks features using a purchase mechanism other than in-app purchase.
Verdict flags this before you submit
4.3Design spam
We noticed your app provides the same feature set as other apps submitted to the App Store.
Judgement call, outside static analysis
5.1.2Tracking
Your app uses the AdSupport framework but does not request permission through App Tracking Transparency.
Verdict flags this before you submit
2.3.3Accurate metadata
The screenshots in your App Store listing do not show the app in use on the device it targets.
Judgement call, outside static analysis
ForegroundService types
Your app declares a foreground service type that is not matched by a declared and permitted use.
Verdict flags this before you submit
1.2User content
Your app includes user generated content but does not provide a mechanism to report offensive material.
Judgement call, outside static analysis
LocationBackground access
Your app requests background location access without an approved declaration for that use.
Verdict flags this before you submit
3.1.1Payments
Your app unlocks features using a purchase mechanism other than in-app purchase.
Verdict flags this before you submit
4.3Design spam
We noticed your app provides the same feature set as other apps submitted to the App Store.
Judgement call, outside static analysis

Paraphrased from published App Store Review Guidelines and Google Play policy pages. Not quotations from named developers.

The checks

Thirty eight checks, every one cited

Each check reads a fact out of your build and compares it against a rule Apple or Google published. Nothing here is inferred.

App Store

The mistakes that never reach a human

We read the provisioning profile out of its CMS envelope and pull entitlements from the Mach-O code signature blob, so we see the same facts App Store Connect validates against. A debug entitlement or the wrong distribution profile stops a submission before review even begins.

Development or ad hoc profile instead of App Store distribution
get-task-allow is true, marking the binary debuggable
Provisioning profile expired
aps-environment is development, so production push fails silently
BlockerWarningAdvisory

Continuous integration

Catch it in the pull request, not in the rejection email.

The expensive rejections are the ones nobody thought to check for. Put Verdict in the pipeline that already builds your artifact and the check stops depending on anyone remembering it.

  • Fails the build on a blockerA non zero exit is the whole feature. The bad build never reaches a reviewer.
  • Reads the artifact you already produceNo console credentials, no store API access. It takes the same .ipa, .apk, or .aab you were going to upload.
  • Every build, not just the one before releaseWhich is how a signing or permission regression gets caught the day it lands.
Read the API docsKeys are minted on your account · 60 scans an hour
.github/workflows/verdict.yml
name: App Store gate
on: [pull_request]

jobs:
  verdict:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # ... your existing build step, producing build/App.ipa

      - name: Fail if this build would be rejected
        run: |
          REPORT=$(curl -sS -X POST https://verdict-umber.vercel.app/api/v1/scans \
            -H "Authorization: Bearer ${{ secrets.VERDICT_API_KEY }}" \
            -F "file=@build/App.ipa")

          echo "$REPORT" | jq -r '"Approval risk: \(.score)/100"'
          echo "$REPORT" | jq -r '.findings[] | "[\(.severity)] \(.ruleId) \(.title)"'

          BLOCKERS=$(echo "$REPORT" | jq '.counts.blocker')
          if [ "$BLOCKERS" -gt 0 ]; then
            echo "::error::$BLOCKERS blocker(s) would fail App Review"
            exit 1
          fi

We take the build apart the way the store does

Verdict unzips the archive and reads the parts a reviewer's tooling reads: Info.plist or the binary AndroidManifest, the Mach-O load commands, entitlements out of the code signature blob, the provisioning profile inside its CMS envelope, every embedded framework, and the DEX string table. Seconds, not hours, because nothing is ever executed.

  • Accepts .ipa, .apk, and .aab up to 450MB
  • Static analysis on Linux, no simulator, no device
  • The build is deleted the moment the report exists
GET /api/v1/scans/:id
{
  "store": "ios",
  "score": 62,
  "app": { "name": "Trailhead", "bundleId": "com.example.trailhead" },
  "counts": { "blocker": 1, "warning": 2, "advisory": 3 },
  "findings": [
    {
      "ruleId": "VD-PRIV-01",
      "severity": "blocker",
      "guideline": "Guideline 5.1.1 - Legal - Privacy",
      "title": "Camera API is used but NSCameraUsageDescription is missing",
      "evidence": "The app binary references AVCaptureDevice, which requires
                   a purpose string. Info.plist has no NSCameraUsageDescription.",
      "fix": "Add NSCameraUsageDescription to Info.plist with one sentence
              naming the feature that needs camera access."
    }
  ],
  "engineVersion": "1.1.0"
}

Every finding arrives with its receipt

A warning that says something is wrong is the easy half. Verdict names the guideline a reviewer would cite, links the official Apple or Google document so you can check the claim yourself, quotes the exact evidence pulled out of your binary, and gives you the specific key, capability, or line to change — ordered by how much score each fix gives back for the work it costs.

  • Cited and linked to the published guideline or ITMS code
  • Evidence quoted from your build, not paraphrased
  • Paste ready patches, ordered by the fastest path to 90
  • A ready made brief for Cursor, Claude, or any coding agent

Camera API is used but NSCameraUsageDescription is missing

VD-PRIV-01 · Guideline 5.1.1 · Legal · Privacy

What we found

The app binary references AVCaptureDevice, which requires a purpose string. Info.plist has no NSCameraUsageDescription. Apple flags this as ITMS-90683 at upload.

The fix

Add the key to Info.plist with one sentence naming the feature that needs camera access. Write it for the person reading the permission alert, not for the reviewer.

Already rejected? Start by decoding the message

Rejection notices say what, never why. Paste yours and Verdict identifies the guideline behind it, explains what reviewers actually mean when they cite it, lists the changes that resolve it, and drafts your Resolution Center reply. It runs in your browser and nothing is stored.

  • Apple guideline numbers and Play policy names
  • A reply draft you can edit and send
  • Free, no account, nothing leaves the page
Decode a rejection

Pasted from App Store Connect

Guideline 2.1 · Performance · App Completeness
We were unable to review your app as it crashed on launch.

2.1App Completeness

The reviewer could not get the app into a working state: a crash, a login they could not pass, or a feature that did nothing on their device.

Reply draft

Thank you for the detailed report. We reproduced the issue and fixed it in this build. We also verified the flow end to end on a clean install with the demo account provided.

You are uploading an unreleased app. We treat it that way.

Your build is the most sensitive artifact you own before a release, so the handling rules are worth stating plainly rather than burying in a policy page. Here is exactly what happens to the file you upload, and what does not.

Retention

Deleted the moment analysis ends

Removal happens in a finally block, so it runs whether the scan succeeded, failed, or timed out. What persists is the report: the score, the findings, and the app name and version.

Execution

Never executed, anywhere

Verdict reads bytes. It does not run your app in a simulator, on a device, or in a sandbox. There is no environment where your code executes on our infrastructure.

Method

Findings are deterministic

Every check is a rule with an explicit condition, written by hand and covered by tests. Two scans of the same build always agree, and a finding cannot be invented.

Currency

Rules tracked against policy

A scheduled job reads Apple and Google's published policy pages every morning and flags changes, and every report records the engine version that produced it.

Pricing

Scanning is free. Pay when you want the fixes.

Every build gets a score and a category breakdown at no cost, because a score you cannot check is worth nothing.

Free

$0forever

Every finding on every build, counted and graded. No account needed.

  • Approval risk score
  • Every finding counted and graded
  • The policy area each one falls under
  • Store listing checked
  • Submission checklist

Pro

Save 75%

$119.99 / yearly

The same Pro, paid once a year. Works out at $10.00 a month instead of $39.99.

  • Everything in Free
  • Findings named, citing the official guideline
  • Evidence from your binary
  • Paste ready patches and the fastest path to 90
  • Build over build comparison
  • The assistant, with cited sources
  • A brief for your AI agent
  • CI gate and API keys

Billed once a year

Team

Save 75%

$239.99 / yearly

The whole team, paid once a year. Works out at $20.00 a month for 5 seats of Pro, or $4.00 a seat.

  • Everything in Pro, for 5 people
  • One dashboard: every member's scans and apps
  • Slack pings when a scan lands or the gate fails
  • One release policy for every member's CI gate
  • Team-wide build over build comparison
  • Invite by email — teammates join by signing in
  • A fraction of the price of 5 solo Pro seats

Billed once a year

Questions worth asking

If something here is not answered, write to us before you buy rather than after.

Get in touch

Ask about a finding you disagree with, report a rule that misfired, or tell us what your build hit that Verdict missed. We read every message.

Building on top of it
Read the scan API reference