How to List Purchased Apps Using IPATool: Command Guide and Implementation

Use the ipatool list-purchases command to retrieve all apps associated with your authenticated Apple App Store account, with optional pagination flags to handle large libraries.

IPATool is a command-line interface for interacting with the Apple App Store, maintained in the majd/ipatool repository. The list-purchases command provides direct access to your complete purchase history by implementing the private App Store DAAP protocol. This guide explains the command syntax, pagination options, and the underlying architecture that powers the feature.

Prerequisites: Authentication Requirements

Before listing purchased apps, you must authenticate with the Apple App Store. IPATool stores account credentials securely and handles token refresh automatically when running list-purchases.

Run the authentication command first:

ipatool auth login

The tool caches your password token locally. If the token expires during a list-purchases request, IPATool automatically re-authenticates using your stored credentials before fetching the app list.

Basic Command Syntax

The list-purchases subcommand retrieves owned apps with minimal configuration:

ipatool list-purchases

By default, this returns the first page of results using the appstore.DefaultOwnedAppsLimit defined in the source constants. Each app entry includes the bundle ID, name, version, and purchase date.

Pagination Controls

For accounts with large purchase histories, IPATool provides two flags to navigate results efficiently.

The --page Flag

Specify which page of results to retrieve using the -p or --page flag:

ipatool list-purchases --page 3

The validation logic in cmd/purchases.go enforces that page values must be greater than or equal to 1.

The --max-results Flag

Control the number of apps returned per request using -l or --max-results:

ipatool list-purchases --page 2 --max-results 50

This value must be at least 1 and cannot exceed appstore.MaxOwnedAppsLimit. If you request more than the maximum allowed, the command fails validation before making any network requests.

How the List Purchases Command Works

The list-purchases implementation spans multiple packages in the IPATool codebase. Understanding this flow helps troubleshoot issues and extends the tool's functionality.

CLI Initialization and Validation

The command entry point resides in [cmd/purchases.go](https://github.com/majd/ipatool/blob/main/cmd/purchases.go). The listPurchasesCmd() function constructs a cobra.Command with the two pagination flags and defines a PreRunE hook that validates:

  • The page parameter is ≥ 1
  • The max-results parameter is ≥ 1 and ≤ appstore.MaxOwnedAppsLimit

If validation fails, the command exits before making network calls.

Account Authentication Flow

During execution, the command first calls dependencies.AppStore.AccountInfo() to retrieve stored credentials. If the password token has expired (appstore.ErrPasswordTokenExpired), the system automatically invokes AppStore.Login using the cached email and password pair. This retry logic ensures uninterrupted access without manual re-authentication.

The Owned Apps API Implementation

The core retrieval logic lives in [pkg/appstore/appstore_owned_apps.go](https://github.com/majd/ipatool/blob/main/pkg/appstore/appstore_owned_apps.go). The OwnedApps method executes a complex sequence to interface with Apple's private APIs:

  1. Input normalization via normalizeOwnedAppsInput to standardize pagination parameters
  2. Machine identity generation creating a GUID-based machine ID for the request
  3. SAP configuration retrieval to build an authenticated action signer
  4. DAAP endpoint communication through three sequential operations:
    • ownedAppsLoginRequest opens a purchase history session
    • ownedAppsUpdateRequest retrieves the latest revision token
    • ownedAppsItemsRequest fetches the actual app data for the requested page
  5. Response parsing via parseOwnedApps converting raw DMAP responses into structured App structs

Each App struct, defined in pkg/appstore/app.go, contains the ID, bundle identifier, name, version string, and purchase timestamp.

Pagination and Output Processing

After retrieving the complete owned apps list, the system:

  1. Sorts results by purchase date using ownedAppsSortedByPurchaseDate
  2. Slices the array to the requested page using ownedAppsPage
  3. Returns an OwnedAppsOutput struct containing the count, total count, page number, and results slice

The command outputs this data through the structured logger (dependencies.Logger), displaying the paginated app list in the terminal.

Practical Examples

List First Page with Default Settings

Retrieve the most recent purchases using default pagination:

ipatool list-purchases

Retrieve older purchases by incrementing the page number and increasing page size:

ipatool list-purchases --page 5 --max-results 100

Programmatic Integration

The following Go excerpt demonstrates how the command constructs the OwnedAppsInput struct and handles the API response, based on the implementation in cmd/purchases.go:

out, err := dependencies.AppStore.OwnedApps(appstore.OwnedAppsInput{
    Account: info.Account,
    Page:    page,
    Limit:   maxResults,
})
if err != nil {
    return err
}

dependencies.Logger.Log().
    Int("count", out.Count).
    Int("total", out.Total).
    Array("apps", appstore.Apps(out.Results)).
    Send()

This pattern allows developers to integrate purchase listing into custom automation tools using IPATool's underlying packages.

Summary

  • Command location: Defined in cmd/purchases.go as listPurchasesCmd()
  • Core implementation: Resides in pkg/appstore/appstore_owned_apps.go via the OwnedApps method
  • Pagination: Controlled via --page (default 1) and --max-results flags, bounded by MaxOwnedAppsLimit
  • Authentication: Automatic token refresh when ErrPasswordTokenExpired occurs during execution
  • Data returned: Array of App structs containing bundle ID, name, version, and purchase date

Frequently Asked Questions

Do I need to log in before using list-purchases?

Yes. IPATool requires a valid Apple App Store authentication token. Run ipatool auth login first to store credentials. If your token expires during a list-purchases execution, the tool automatically re-authenticates using the stored password.

What is the maximum number of apps I can retrieve per page?

The maximum is defined by appstore.MaxOwnedAppsLimit in the source code. The --max-results flag must be between 1 and this limit. The exact value is enforced in the pre-run validation within cmd/purchases.go.

How does IPATool handle expired authentication tokens?

When dependencies.AppStore.AccountInfo() returns appstore.ErrPasswordTokenExpired, the command automatically invokes AppStore.Login with the cached account credentials. This retry mechanism is wrapped in the command's execution flow, so users do not need to manually re-authenticate.

Can I export the purchased apps list to a file?

While list-purchases outputs to stdout, you can redirect the output to a file using shell redirection. The tool does not currently support native JSON export flags, but the structured logger output can be piped to jq or similar tools for parsing.

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 →