Skip to content

Part of: Online IPA Installer

Manifest.plist and itms-services Link Generator

For the developer who built the build. Drop your .ipa to fill the metadata, point the manifest at hosting you already control, and take away the plist, the itms-services link and its QR code. Everything is generated in this page: nothing is uploaded, hosted or fetched here.

Step 1. Read the build

Drop the .ipa you built to fill the bundle identifier, version and title from its Info.plist. The file is parsed in this page and is not sent anywhere. If you would rather not open the build here, type the three values in yourself.

Drop an .ipa here, or

Step 2. Check the metadata

Step 3. Point at your own HTTPS URLs

Both files stay on hosting you control. This page does not upload, fetch, proxy or shorten either address: it writes the first into the plist and the second into the link.

Optional icon assets

Left empty, both asset entries are omitted from the plist. They are the artwork the manifest offers for the placeholder icon shown while the app installs.

manifest.plist

Fill the three metadata fields and the https:// URL of your .ipa for a manifest you can ship. The preview below updates as you type.

<?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>items</key>
  <array>
    <dict>
      <key>assets</key>
      <array>
        <dict>
          <key>kind</key>
          <string>software-package</string>
          <key>url</key>
          <string></string>
        </dict>
      </array>
      <key>metadata</key>
      <dict>
        <key>bundle-identifier</key>
        <string></string>
        <key>bundle-version</key>
        <string></string>
        <key>kind</key>
        <string>software</string>
        <key>title</key>
        <string></string>
      </dict>
    </dict>
  </array>
</dict>
</plist>

itms-services link

Enter the URL where manifest.plist will live to get the link and its QR code. The link carries the manifest address, not the address of the build.

What a manifest.plist actually is

A manifest is a small XML property list that stands between a link and a build. Apple describes it as the file Apple devices use to find, download and install apps from your web server. It does two jobs at once: it names the address of the .ipa, and it repeats a few facts about the app so the device can put a correct prompt on screen before the transfer has finished.

That second job is the part people skip. The device has nothing but the manifest at the moment it asks the person to confirm, so a bundle identifier or a title that disagrees with the build inside the archive produces an install that looks wrong, installs beside an existing copy rather than replacing it, or is refused outright. The generator above reads those values out of the archive instead of asking you to remember them.

A manifest is not a signature and it is not permission. Signing decides who may install a build: a build signed for testing installs only on the devices listed in its provisioning profile, whatever the manifest says. If you are not sure which profile signed an archive or which devices it covers, the IPA inspector reads both out of the file in the browser.

The keys this generator writes, annotated

The structure is fixed and short: one items array, one entry inside it, an assets array naming files and a metadata dictionary describing the app. Apple's schema carries more than this generator writes: an optional subtitle in the metadata, a fourth asset kind asset-pack-manifest for on-demand resources, and the optional integrity keys noted below (apple/device-management, other/manifesturl.yaml, checked on 2026-09-03).

KeyWhere it sitsValueWhat it does
itemsTop levelarrayThe array of things to install. A manifest for a single build holds exactly one entry, and that entry is a dictionary with an assets array and a metadata dictionary.
assetsInside the itemarray of dictionariesThe files that make up the entry. Each asset this generator writes is a dictionary with a kind and a url. Apple's schema also allows optional md5, md5-size, md5s, sha256, sha256-size and sha256s integrity keys, and advises preferring SHA-256 over MD5.
kindInside an assetsoftware-package, display-image, full-size-imagesoftware-package is the .ipa and is the one asset you cannot leave out. The two image kinds are artwork the manifest offers for the placeholder icon shown while the app installs.
urlInside an assetHTTPS URLWhere that file is. The software-package url is the address of your build, and it is the only place in the whole flow that names it. It is not the address that goes in the link.
metadataInside the itemdictionaryWhat the device needs before the transfer finishes: enough to name the app in the install prompt and to match it against anything already on the device.
bundle-identifierInside metadataCFBundleIdentifier from the buildThe identifier inside the .ipa, copied out. It has to be the real one: it is how the device knows whether this is a new app or a replacement for one already installed.
bundle-versionInside metadataCFBundleShortVersionString, or CFBundleVersionThe version string shown during installation. The tool above fills it from the short version string and falls back to the build number when a build has no short version.
kindInside metadatasoftwareA fixed value for an iOS app, and unrelated to the asset kind two levels up. The repeated key name is the most common source of confusion when people copy a manifest by hand.
titleInside metadataDisplay nameThe name in the install prompt, so make it the name your testers recognise rather than the target name. Anything here is text you chose, not something the device verifies.

Two keys are named kind and they mean different things: inside an asset it selects which file this is, and inside metadata it is the fixed value software. The images are optional. Leave them out and the manifest is shorter and still installs; put them in and the placeholder icon during installation is your artwork instead of a blank tile.

The link carries the address of the manifest. Nothing anywhere in it names the .ipa, which is the single most common mistake: a link built around the build address asks the device to parse a zip archive as a property list, and it fails immediately.

itms-services://?action=download-manifest&url=https%3A%2F%2Fbuilds.example.com%2Fmanifest.plist
itms-services://
The scheme the operating system claims. There is no host after the slashes, which is why the query string starts straight away with a question mark.
action=download-manifest
The only action in normal use, and it is fixed text. It tells the device that the next parameter is a manifest to read rather than anything else.
url=…
The HTTPS address of your manifest.plist. Apple's own example writes it plainly, and a plain path such as https://builds.example.com/manifest.plist does work unencoded. The moment that address carries reserved characters of its own it stops working, because it is a value inside a query string: an & in it ends the url parameter early, which is what happens to anyone serving the manifest from a signed URL with query parameters. Percent-encoding the whole value is correct in both cases, so the generator above does it unconditionally.

One more escaping layer catches people out when the link goes onto a web page. In HTML an & inside an href has to be written &amp;. The browser hands the unescaped character to the operating system; a raw ampersand in the markup is a validity error that some parsers repair in ways that quietly change the URL. The generator above prints the link in its plain form, ready to paste into an href once that one substitution is made.

What your web server has to send

Four requirements, and a failed install usually traces to one of them. None of them produces a message on the device that names the cause, which is why the list is worth working through in order.

HTTPS on both files
Apple states that apps installed this way need to be downloaded from a website whose address begins with HTTPS. That covers the manifest and the .ipa it points at, on a certificate the device already trusts. A self-signed certificate is not enough.
The right MIME types
Apple's guide gives them as application/octet-stream for the .ipa and text/xml for the plist. Static hosts commonly answer with text/html for an extension they do not recognise, and the install then stops without saying why.
A real file, not a redirect chain
Keep the manifest at the exact URL you put in the link. Redirects, interstitials and login walls all break an install that never renders a page for a person to click through.
Opened in Safari
The itms-services link is handled by the operating system when Safari opens it. In-app browsers inside chat and email clients frequently do not hand the scheme over, which is why a link that works when pasted into Safari can appear dead when tapped in a message.

Exporting the .ipa: release-testing, never ad-hoc

A manifest can only point at a build that was exported for distribution outside the store. In Xcode that is Product, Archive, then Distribute App. Apple describes the Release Testing option as default settings to distribute a version to test before release, exporting to install on devices your team registers with App Store Connect. Enterprise is the other route, and only for members of the Apple Developer Enterprise Program.

From the command line the value lives in an ExportOptions.plist:

<key>method</key>
<string>release-testing</string>
<key>teamID</key>
<string>ABCDE12345</string>

The older ad-hoc value is on its way out and should not be used in new configuration. xcodebuild -help in Xcode 26.6 lists the available options as app-store-connect, release-testing, enterprise, debugging, developer-id, mac-application and validation, and records ad-hoc as deprecated in favour of release-testing. Anything that writes that plist for you inherits the same rule, fastlane included, because its export method is copied straight into this key.

Xcode will also write a manifest itself if you let it: the packaging step for a self-distributed export offers a checkbox for including a manifest for over-the-air installation, and xcodebuild exposes the same thing as a manifest dictionary in the export options, with the sub-keys appURL, displayImageURL and fullSizeImageURL. Use the generator above when you want the file without re-exporting the archive, or when the build is already sitting on your server and only the URLs have changed.

Checked on 2026-09-03 against Apple's own documentation: the itms-services link form, the HTTPS requirement and the MIME types come from Distribute proprietary in-house apps to Apple devices in Apple Platform Deployment; the Release Testing description and the over-the-air manifest checkbox from Distributing your app for beta testing and releases; the export method list from xcodebuild -help on Xcode 26.6, build 17F113.

What this page does not do

It does not host your build, and it never will. It does not fetch, resolve or check the URLs you type: they are written into a plist and into a link, and that is the whole of it. It does not shorten them, does not store them, and does not keep the QR code after you leave the page. The .ipa you drop in is parsed in your browser and is not uploaded, which is what makes it safe to use on a build under NDA.

The tool is for the person who built and signed the app and is publishing it to their own testers. It is not a way to install a build somebody else made: the manifest is inert without a signature that already covers the device. If you come across a link generated here pointing at something that infringes copyright, impersonates an app or distributes malware, tell us on report abuse and it will be dealt with.

If you would rather not run the hosting

Writing the manifest is the easy half. The rest is a server with a trusted certificate, the right MIME types, a URL per build, some way to expire old links and somewhere to see who installed what. BetaDrop does that part: you upload the .ipa and get an install page with the manifest, the link and a QR code already generated, or you share an APK for the Android half of the same job. The long-form version of the whole flow, including what testers see on the device, is in installing an IPA over the air.

Frequently asked questions

What is a manifest.plist file?

It is an XML property list that tells an Apple device where a build lives and what it is. One assets entry of kind software-package carries the URL of the .ipa, and a metadata dictionary repeats the bundle identifier, the version and the title so the device can show a correct install prompt before it has the app.

Does my .ipa get uploaded when I use this generator?

No. The archive is unzipped and its Info.plist decoded by JavaScript inside this page, and the manifest, the link and the QR code are all assembled locally. Nothing is uploaded, and the page never fetches, proxies, shortens or stores the URLs you type into it.

Why does everything have to be served over HTTPS?

Apple's deployment guide states that apps installed this way need to be downloaded from a website whose address begins with HTTPS. That covers the manifest and the .ipa it points at, so a plain HTTP address for either one ends the install before it starts, with no useful message on the device.

What Content-Type should my server send for the manifest and the .ipa?

Apple's guide gives the MIME types as application/octet-stream for the .ipa and text/xml for the plist. A host that answers with text/html for an extension it does not recognise is worth ruling out early, because the install then stops without ever reporting a reason.

Which Xcode export method produces a build I can install this way?

Release Testing or Enterprise. In an ExportOptions.plist the method value is release-testing, and xcodebuild in Xcode 26.6 lists the older ad-hoc value as deprecated in favour of it. Xcode can also write the manifest itself: the packaging step offers a checkbox for including a manifest for over-the-air installation.

Can I use this to install an app somebody else built?

No. This is a tool for the developer who built and signed the .ipa and hosts it on their own server. Apple's signing rules settle the rest anyway: a build signed for testing installs only on the devices listed in its provisioning profile, and a manifest cannot change that.