How the ipatool Download Command Resolves Bundle Identifiers and External Version IDs
The ipatool download command uses a two‑stage resolution process: it maps bundle identifiers to internal App Store IDs via a lookup API call, and passes external version IDs directly to the download endpoint to select specific app versions.
This article explains how majd/ipatool translates human‑readable app identifiers into the precise values Apple's servers require. Whether you're downloading by bundle ID (com.example.myapp) or targeting a specific build with an external version ID, the resolution logic lives in the cmd/download.go orchestration layer and the pkg/appstore implementation files.
Bundle Identifier Resolution Process
When you supply --bundle-identifier (-b), ipatool cannot use that string directly with Apple's download API. Instead, it must first obtain the numeric internal App ID that Apple's servers recognize.
The Lookup Request
In cmd/download.go, the command constructs a LookupInput and delegates to the AppStore interface:
lookupResult, err := store.Lookup(appstore.LookupInput{
Account: acc,
BundleID: bundleID,
Platform: platform,
})
This call hits the App Store "lookup" endpoint implemented in pkg/appstore/appstore_lookup.go. The endpoint returns metadata for the matching app, including its internal numeric ID.
Extracting the App ID
The lookupResult.App field (type appstore.App) contains the resolved ID:
app := lookupResult.App
// app.ID now holds the internal App Store identifier
This numeric ID is required for all subsequent operations including store.Download and store.Purchase. The lookup effectively bridges the gap between user‑friendly bundle identifiers and Apple's internal app catalog.
External Version ID Handling
The --external-version-id flag allows targeting specific app versions—beta builds, older releases, or regional variants—without relying on the default "latest" selection.
Passing the Version ID
The external version ID flows directly from CLI flag to download input in cmd/download.go:
out, err := store.Download(appstore.DownloadInput{
Context: cmd.Context(),
Account: acc,
App: app,
OutputPath: outputPath,
Progress: progress,
ExternalVersionID: externalVersionID, // from --external-version-id
Platform: platform,
})
Version Selection Logic
Inside pkg/appstore/appstore_download.go, the Download implementation inspects ExternalVersionID:
- Empty value: Requests the latest available version for the resolved app ID
- Non‑empty value: Includes the identifier in the download request, causing Apple's servers to return that specific build
This design decouples version selection from app identification. You can combine bundle ID lookup with precise version targeting, or use a numeric app ID directly to bypass lookup entirely.
Complete Download Flow
| Step | Component | Key Operation |
|---|---|---|
| Flag parsing | cmd/download.go (lines 24‑28) |
Extracts app-id, bundle-identifier, external-version-id, platform |
| Platform validation | cmd/download.go (line 38) |
appstore.ParsePlatform validates platform string |
| Bundle resolution | cmd/download.go (lines 71‑82) |
store.Lookup → appstore_lookup.go → App Store API |
| License acquisition | cmd/download.go (lines 84‑99) |
Optional store.Purchase if --purchase flag set |
| Package download | cmd/download.go (lines 23‑31) |
store.Download → appstore_download.go with version ID |
| Post‑processing | cmd/download.go (lines 84‑89) |
Optional SINF replication for macOS |
Practical Usage Examples
# Download latest version by bundle identifier
ipatool download -b com.example.myapp -o MyApp.ipa
# Download specific beta version using external version ID
ipatool download -b com.example.myapp --external-version-id 1234567890 -o MyAppBeta.ipa
# Skip bundle lookup with explicit numeric App Store ID
ipatool download -i 12345678 -o MyApp.ipa
# Combine with platform targeting
ipatool download -b com.example.myapp --platform iphone -o MyApp.ipa
Key Source Files
| File | Responsibility |
|---|---|
cmd/download.go |
CLI command implementation, orchestrates lookup and download flows |
pkg/appstore/appstore_lookup.go |
Lookup function – bundle identifier → internal App ID translation |
pkg/appstore/appstore_download.go |
Download function – handles external version ID and fetches IPA |
pkg/appstore/appstore.go |
AppStore interface definition (Lookup, Download, Purchase, etc.) |
pkg/appstore/platform.go |
Platform string parsing (iphone, ipad, appletv, visionos, macos) |
Summary
- Bundle identifiers require an API lookup to obtain the internal numeric App ID used by Apple's servers
- External version IDs pass through unchanged, enabling precise version selection without additional resolution steps
- The
AppStoreinterface inpkg/appstore/appstore.goabstracts both operations behind a clean Go API - Platform validation occurs early, ensuring consistent behavior across iOS, iPadOS, tvOS, visionOS, and macOS targets
Frequently Asked Questions
What happens if I provide both --app-id and --bundle-identifier?
The command uses the numeric app-id directly and skips the lookup step. Bundle identifier resolution only occurs when --app-id (-i) is omitted. This avoids an unnecessary API call when you already know the internal identifier.
Can I use external version IDs without a bundle identifier?
Yes. If you provide --app-id along with --external-version-id, the command bypasses bundle lookup entirely and passes both values to the download endpoint. This is useful for automation workflows that operate on cached app IDs.
Where does the external version ID come from?
External version IDs are assigned by Apple and exposed through the App Store's internal APIs—often visible in enterprise MDM systems, TestFlight metadata, or historical download logs. They represent specific builds rather than marketing version strings like "2.1.0".
Does platform selection affect bundle identifier resolution?
Yes. The same bundle identifier may map to different internal App IDs across platforms (e.g., iPhone vs. iPad variants of the same app). The platform parameter in the lookup request ensures you receive the correct app metadata for your target device family.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →