How to List App Versions Using IPATool: CLI and Programmatic Guide

IPATool provides a dedicated list-versions command that queries Apple's private App Store API to retrieve all available versions of a specific iOS app using either an Apple-assigned numeric ID or a bundle identifier.

IPATool is an open-source command-line utility for interacting with the App Store programmatically. Whether you need to audit version history, verify available releases for downgrading, or automate app management workflows, understanding how to list app versions using IPATool gives you direct access to Apple's version metadata through both terminal commands and Go library interfaces.

Understanding the list-versions Command Structure

The list-versions command is defined in cmd/list_versions.go and serves as the primary interface for version discovery. According to the majd/ipatool source code, the command accepts two mutually exclusive identification methods for targeting the desired application.

Required Parameters

You must provide exactly one of the following flags:

  • --app-id – The numeric Apple-assigned application identifier (e.g., 123456789)
  • --bundle-identifier – The human-readable bundle ID string (e.g., com.example.myapp)

When you supply a bundle identifier, the command automatically performs an app lookup via AppStore.Lookup in pkg/appstore/app.go to resolve it to the internal numeric ID before proceeding with the version query.

Authentication Flow and Automatic Retry Logic

Before executing the version request, the command fetches stored account information through dependencies.AppStore.AccountInfo(). If the authentication token has expired, the system automatically initiates a fresh login via dependencies.AppStore.Login.

The entire operation is wrapped in a retry block utilizing github.com/avast/retry-go. If the API returns ErrPasswordTokenExpired or a "sign-in required" error—as defined in pkg/appstore/error.go—the client automatically re-authenticates and retries the request once, ensuring seamless execution without manual token refresh.

Internal Implementation of Version Retrieval

The core version retrieval logic resides in pkg/appstore/appstore_list_versions.go. When you execute the command, the following sequence occurs:

  1. Machine Identification – The system retrieves the host's MAC address via machine.MacAddress() and converts it to an uppercase, colon-less GUID string for device identification.

  2. Request Construction – The listVersionsRequest function builds a POST request targeting Apple's private API endpoint (https://<pod-prefix>itunes.apple.com/...).

  3. Payload Assembly – The request body includes:

    • The generated GUID
    • The app's salableAdamId (Apple's internal app identifier)
    • A dummy serial number for device verification
  4. API Communication – The HTTP client defined in pkg/http/client.go transmits the authenticated request and parses the response.

  5. Result Extraction – Upon success, the command extracts ExternalVersionIdentifiers (the complete array of version IDs) and LatestExternalVersionID (the most current release).

Practical Usage Examples

CLI Usage

Execute version lookups directly from your terminal using the following patterns:


# List versions by Apple-assigned app ID

ipatool list-versions --app-id 123456789

# List versions by bundle identifier (overrides --app-id if both provided)

ipatool list-versions --bundle-identifier com.example.myapp

Programmatic Usage with Go

You can integrate version listing directly into Go applications by importing the appstore package:

import (
    "fmt"
    "github.com/majd/ipatool/v2/pkg/appstore"
    "github.com/majd/ipatool/v2/pkg/util/must"
)

func listAppVersions(acc appstore.Account, appID int64) {
    // Build the input struct with account and app details
    input := appstore.ListVersionsInput{
        Account: acc,
        App:     appstore.App{ID: appID},
    }

    // Execute the version query
    out, err := appstore.New().ListVersions(input)
    must.NoError(err)

    // Access version data from the output struct
    fmt.Println("Available versions:", out.ExternalVersionIdentifiers)
    fmt.Println("Latest version:", out.LatestExternalVersionID)
}

Key Source Files and Architecture

Understanding the following files helps when customizing or debugging version retrieval:

Summary

  • Use the list-versions command with either --app-id (numeric) or --bundle-identifier (string) to target specific applications
  • Authentication is handled automatically with built-in retry logic that refreshes expired tokens via github.com/avast/retry-go
  • The core API interaction is implemented in pkg/appstore/appstore_list_versions.go, which constructs authenticated POST requests to Apple's private endpoints
  • Successful execution returns ExternalVersionIdentifiers (all available versions) and LatestExternalVersionID (current release)
  • The tool converts your machine's MAC address into a GUID for device identification during API requests

Frequently Asked Questions

What is the difference between --app-id and --bundle-identifier?

The --app-id flag accepts the numeric identifier assigned by Apple (visible in App Store URLs), while --bundle-identifier accepts the reverse-domain string (e.g., com.company.appname). If you provide both flags, the bundle identifier takes precedence and the system performs an intermediate lookup to resolve the numeric ID.

How does IPATool handle expired authentication tokens?

The command implements automatic retry logic that catches ErrPasswordTokenExpired errors from pkg/appstore/error.go. When detected, the system performs a fresh login using stored credentials and retries the version request once without requiring manual intervention.

Can I use IPATool as a Go library instead of CLI?

Yes. Import github.com/majd/ipatool/v2/pkg/appstore and construct a ListVersionsInput struct containing your Account and App objects. Call appstore.New().ListVersions(input) to receive a struct containing ExternalVersionIdentifiers and LatestExternalVersionID.

What information does the list-versions command return?

The command returns an array of ExternalVersionIdentifiers representing all historical version IDs available for the application, plus LatestExternalVersionID indicating the most current version number assigned by Apple.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →