What's inside an .ipa file
An .ipa is a zip archive of an iOS app. Rename it to .zip and you can open it, but most of what matters is in two property lists that are hard to read by hand. This inspector reads them for you.
| In the .ipa | What it is |
|---|---|
| Payload/YourApp.app/ | The app itself. An .ipa is a zip archive with this one folder in it. |
| Info.plist | The app's name, bundle ID, version and build, minimum iOS version, iPhone or iPad, URL schemes, and the text it shows when it asks for a permission. |
| embedded.mobileprovision | The provisioning profile: who signed it, when it expires, its entitlements, and for Ad Hoc and Development builds the UDIDs of the devices allowed to install it. |
| _CodeSignature/ | The signature over every file in the app. Change one file and iOS refuses to install the build. |
| The executable | The compiled app, named after the app. Usually the largest file. |
| Frameworks/ | Embedded frameworks and Swift libraries the app ships with. |
| PlugIns/ | App extensions (.appex): widgets, share sheets, notification extensions, keyboards. |
| Assets.car | The compiled asset catalog: icons and images. |
| SC_Info/ | Only in App Store downloads: the encryption info that ties the app to one Apple ID. |
How to read Info.plist and the provisioning profile
These are the keys that decide whether a build installs, and what testers see.
CFBundleIdentifier- The bundle ID. It must match the App ID in the provisioning profile.
CFBundleShortVersionString and CFBundleVersion- The version people see (2.1) and the build number (77).
MinimumOSVersion- The oldest iOS that can install it.
UIDeviceFamily- 1 is iPhone, 2 is iPad.
…UsageDescription- The sentence iOS shows when the app asks for the camera, location, photos and so on.
ProvisionedDevices- In the profile: the UDIDs that can install an Ad Hoc or Development build. An App Store profile has none, an Enterprise profile has ProvisionsAllDevices instead.
ExpirationDate- In the profile: after this date iPhones refuse to install the build, and installed copies stop opening.
get-task-allow- In the profile's entitlements: true for Development builds (a debugger can attach), false for Ad Hoc, Enterprise and App Store.
On a Mac you can also read them in Terminal:
Show Info.plist on a Mac
unzip -p YourApp.ipa 'Payload/*.app/Info.plist' | plutil -p -
Show the provisioning profile
unzip -o YourApp.ipa 'Payload/*.app/embedded.mobileprovision' -d ipa && security cms -D -i ipa/Payload/*.app/embedded.mobileprovision
Have just the profile? Open it in the mobileprovision viewer.
Why an IPA won't install
When iOS says “Unable to install”, it's almost always one of these. The inspector above shows each of them.
- The iPhone isn't in the profile. Ad Hoc and Development builds install only on the UDIDs listed in their profile. Get the tester's UDID (find your iPhone UDID), add it in Apple Developer, and export again.
- The profile has expired. Check the expiry date above. Export the build again with a fresh profile.
- It's signed for the App Store. An App Store or TestFlight build has no device list. Upload it to App Store Connect, or export it again with Ad Hoc or Development.
- iOS is too old. If the iPhone runs an older iOS than the build's minimum, it can't install it.
- It's a Simulator or unsigned build. Archive for Any iOS Device in Xcode and export an .ipa with a provisioning profile.
- Enterprise or Development builds need one more step. An Enterprise build opens only after the user trusts the developer in Settings → General → VPN & Device Management. Since iOS 16, a Development build needs Developer Mode on (Settings → Privacy & Security).
More in how to install an IPA on iPhone.
Skip the profile juggling
With BuildFerry, testers open one link and you approve their iPhone. It's registered with your Apple account and the build is re-signed in the cloud, so a new tester never means a new export.
Send your first buildQuestions
Is my .ipa uploaded anywhere?
No. The inspector runs in your browser and reads the file where it is. Nothing about the build is sent to BuildFerry or anyone else.
Can it open a large .ipa?
Yes, even several gigabytes, in about a second. It reads only the zip's table of contents and the few small files it needs (Info.plist, the provisioning profile, the icon), never the whole file.
How do I check which iPhones can install an IPA?
Open it here and look at Signing & profile: Ad Hoc and Development builds list every allowed UDID. Paste a UDID into "Is this iPhone in this build?" to check one device. An Enterprise build installs on any device; an App Store build on none until Apple distributes it.
How can I tell Ad Hoc from Development or App Store?
From the provisioning profile. A profile with devices and get-task-allow true is Development; with devices and get-task-allow false it's Ad Hoc; ProvisionsAllDevices means Enterprise; no devices means App Store or TestFlight.
Why does my .ipa have no provisioning profile?
Simulator builds and unsigned builds have none, and neither do apps downloaded from the App Store. iPhones won't install a build without one: export it from Xcode with Ad Hoc or Development.
How do I add a tester's iPhone to an existing build?
You can't change the profile inside a signed build. Add the UDID in Apple Developer, regenerate the profile and export again, or let BuildFerry do it: it registers each tester's iPhone with your Apple account and re-signs the build in the cloud.