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
pageparameter is ≥ 1 - The
max-resultsparameter 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:
- Input normalization via
normalizeOwnedAppsInputto standardize pagination parameters - Machine identity generation creating a GUID-based machine ID for the request
- SAP configuration retrieval to build an authenticated action signer
- DAAP endpoint communication through three sequential operations:
ownedAppsLoginRequestopens a purchase history sessionownedAppsUpdateRequestretrieves the latest revision tokenownedAppsItemsRequestfetches the actual app data for the requested page
- Response parsing via
parseOwnedAppsconverting raw DMAP responses into structuredAppstructs
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:
- Sorts results by purchase date using
ownedAppsSortedByPurchaseDate - Slices the array to the requested page using
ownedAppsPage - Returns an
OwnedAppsOutputstruct 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
Navigate Large Purchase Histories
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.goaslistPurchasesCmd() - Core implementation: Resides in
pkg/appstore/appstore_owned_apps.govia theOwnedAppsmethod - Pagination: Controlled via
--page(default 1) and--max-resultsflags, bounded byMaxOwnedAppsLimit - Authentication: Automatic token refresh when
ErrPasswordTokenExpiredoccurs during execution - Data returned: Array of
Appstructs 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →