Skip to content

Repository files navigation

IPArchive

A native macOS app for downloading and archiving IPA files of App Store apps licensed to your Apple Account.

Think of it as a SwiftUI counterpart to ipatool: sign in with your own Apple Account, search the App Store, and keep a local copy of the apps you already own.

Note on naming — the repository is IPArchive; the Xcode target, scheme and bundle identifier are still IPAHelper / com.ixlab.IPAHelper. Renaming those would invalidate the Keychain entry of existing installs, so the internal names are intentionally left alone.


What it does

  • Sign in with your Apple Account, including two-factor authentication
  • Search the App Store for iPhone, iPad or Apple TV software
  • Download the IPA of an app your account holds a license for
  • Saves to ~/Downloads/<bundle id>_<app id>.ipa — e.g. com.example.app_1234567890.ipa
  • Keeps a rolling activity log (last 30 entries) so you can see exactly what happened

What it does not do

Please read this before opening an issue — these are deliberate boundaries, not bugs.

  • It does not purchase apps. Paid apps are refused outright (AppStoreClient.purchase throws for any app with price > 0). You can only download apps your account already has a license for, either free apps or ones you previously bought.
  • It does not decrypt anything or bypass DRM. It uses your own credentials to ask Apple for a download the same way the App Store would.
  • The downloaded IPA is not directly sideloadable. IPAPatcher.patch is currently a stub: the IPA is saved exactly as Apple serves it, without iTunesMetadata.plist or the SC_Info/*.sinf license files injected. That makes it suitable for archiving and analysis, not for installing onto a device. (Swift has no standard ZIP writer; the service boundary exists so a ZIP library can be wired in later.)
  • No download progress percentage. The underlying client only reports completion, so the UI shows an indeterminate spinner. Downloads can be cancelled at any time.

Requirements

  • macOS 14 (Sonoma) or later
  • Swift 6.0 / Xcode 16 to build
  • XcodeGen — optional, only if you want to regenerate the Xcode project

Build and run

Via SwiftPM:

swift build
swift run IPAHelper
swift test          # runs the IPAHelperCore unit tests

Via Xcode:

xcodegen generate   # optional — IPAHelper.xcodeproj is committed
open IPAHelper.xcodeproj

Website

The product website lives in site/ and is built with Vue 3, TypeScript and Vite.

cd site
pnpm install
pnpm dev

Run pnpm build from site/ to type-check the project and create a production build. The macOS download URL is currently a placeholder and is defined by DOWNLOAD_URL near the top of site/src/App.vue.

A note on the Keychain prompt

The project uses CODE_SIGN_STYLE: Automatic with no development team, so local builds are typically ad-hoc signed and the signature changes on every rebuild. macOS ties Keychain item access to the signing identity, so after rebuilding you will likely see a "IPAHelper wants to use your confidential information" prompt on the next launch. Choosing Always Allow silences it until the next rebuild. This is expected for local development, not a sign that anything is wrong.

Security and privacy

Credential handling is the part of this project worth scrutinising, so here is exactly what is stored and where.

Your Apple Account password is never persisted. It is never written to the Keychain, never written to disk, and never enters the activity log. It is held in memory only, and cleared on sign-out.

What Where Protection
passwordToken, DSID, email, storefront macOS Keychain, service com.ixlab.IPAHelper kSecAttrAccessibleWhenUnlockedThisDeviceOnly — not synced to iCloud, not included in backups
Apple session cookies ~/Library/Application Support/IPAHelper/cookies.plist file 0600, directory 0700
Downloaded IPAs ~/Downloads standard file permissions

Other measures:

  • Error messages never echo response bodies. Apple's authentication responses contain your passwordToken and DSID. If a response fails to decode, the error reports only the HTTP status, the response size, and the CodingKey path — never the payload. This matters because errors are surfaced in the UI and the activity log, which users copy into bug reports.
  • No logging of any kind. There is no print, NSLog, or os_log anywhere in the source.
  • Automatic cleanup of legacy data. Earlier versions stored the plaintext Apple Account password in the Keychain. On first launch, the stored record is re-encoded and written back, which drops that field. The migration is best-effort: if the Keychain write fails, your session is kept and the cleanup is retried on the next launch.

Known limitations

Stated plainly rather than buried:

  • Session cookies are stored in cleartext on disk. File permissions (0600) keep other user accounts out, but any process running as you can read them, and they include long-lived authentication tokens. Moving them into the Keychain is the obvious next step.
  • The device GUID is your real hardware MAC address (DeviceGUIDProvider), which is what Apple's endpoints expect. It is a persistent hardware identifier and cannot be rotated.
  • The password stays in memory for the whole session. It is cleared on sign-out, but not immediately after a successful sign-in. Discarding it as soon as the token is obtained would narrow the window further.

To sign out and remove the stored credentials, use Sign Out in the app. To wipe the cookie file manually:

rm ~/Library/Application\ Support/IPAHelper/cookies.plist

Project layout

Sources/
  IPAHelper/          SwiftUI app — ContentView, IPAHelperModel, IPAHelperApp
  IPAHelperCore/      Networking, models, Keychain and cookie storage
Tests/
  IPAHelperCoreTests/ Unit tests for the core response decoding
site/                Vue product website

IPAHelperCore has no dependency on SwiftUI and is where all App Store communication lives. The app layer holds no networking logic of its own.

Troubleshooting

Sign-in keeps failing. Use your Apple Account password, not an app-specific password — those are not supported by the endpoint this app talks to. If two-factor authentication is enabled, you will be asked for the 6-digit code after the first attempt; make sure you enter a fresh one.

"Rate limited by Apple". Apple throttles these endpoints. Wait a few minutes before retrying.

The download finished but the app says the IPA has no metadata. That is expected — see What it does not do above.

Contributing

Issues and pull requests are welcome. Two things to keep in mind:

  1. Never paste raw responses into an issue. Apple's authentication payloads contain your passwordToken, DSID and email. The app deliberately keeps them out of error messages; please don't reintroduce them by hand.
  2. Run swift build and swift test before submitting.

Disclaimer

This project is not affiliated with, endorsed by, or sponsored by Apple Inc. It is intended for archiving apps your own Apple Account is licensed to use, and for security research and analysis. You are responsible for complying with the App Store Terms of Service and the laws of your jurisdiction.

License

MIT © 2026 IntelliFuture

About

Native macOS app for downloading and archiving IPA files of App Store apps licensed to your Apple Account.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages