How to upload an .ipa to App Store Connect without Xcode in 2026
You built your app on a Linux CI box. You're on Windows. Or you just don't want to open Xcode to push a binary. All three are valid — Apple gives you real alternatives that hold up in production.
Shipping on Android too? Same question on the Play Store side: see how to upload an .aab without Android Studio.
What you need before any upload method
The .ipa must be signed with a Distribution certificate and an App Store provisioning profile. The bundle ID must match an app record already created in App Store Connect. The build number must be higher than any build already uploaded for that version. Bitcode is no longer required (Apple deprecated it), but the binary still has to target a supported architecture.
If the .ipa fails any of these, all five methods below reject it with the same error — fix the binary before you switch tools.
Method 1: Apple Transporter (the official CLI and GUI)
The most direct path — it's the same tool App Store Connect uses internally. On macOS: free download from the Mac App Store, drop the .ipa on the GUI, sign in with an Apple ID or an App Store Connect API key (.p8), click Deliver.
On Linux or in CI, Transporter ships as a Docker image:
docker pull appleinc/transporter docker run -it appleinc/transporter -u your@apple.id -p your-app-specific-password -f /path/to/YourApp.ipa -t DAVFor automation, skip the Apple ID and use an App Store Connect API key instead: generate one in App Store Connect under Users and Access, download the .p8, pass the Issuer ID, Key ID, and .p8 path to Transporter. Common errors: ITMS-90096 (provisioning profile mismatch), ITMS-90535 (CFBundleExecutable issue in Info.plist), ITMS-90725 (unsupported SDK version).
Method 2: altool (legacy, still works)
Ships with Xcode Command Line Tools — so you still need those installed, even without the full IDE.
xcrun altool --upload-app --type ios --file /path/to/YourApp.ipa --apiKey YOUR_KEY_ID --apiIssuer YOUR_ISSUER_IDApple deprecated altool in favor of Transporter; it will eventually stop working outright. For a new pipeline, start with Transporter or the App Store Connect API instead.
Method 3: App Store Connect API, direct binary upload
For custom CI/CD: create a build reservation via POST /v1/builds (or the uploadOperations endpoint), upload the .ipa bytes to the pre-signed S3 URL Apple returns, then confirm the upload. More code than Transporter, but full programmatic control; authenticate with a JWT signed using the .p8 key.
Method 4: Fastlane deliver
fastlane deliver --ipa "YourApp.ipa" --skip_screenshots --skip_metadataWraps Transporter under the hood. It earns its place when you want the upload bundled with metadata and screenshot delivery in one lane. Trade-off: you need Ruby, a Gemfile, and some initial configuration.
Method 5: a unified dashboard (OneStore)
Juggling metadata, screenshots, and binary uploads across three separate tools adds up. OneStoreintegrates Apple Transporter directly — you upload the .ipa from the same dashboard where you edit title, description, and screenshots. The .p8 key sits in a vault encrypted at rest with AES-256-GCM at the application layer; a Data Processing Agreement based on the EU Standard Contractual Clauses is available on request at onestore.so/dpa. No compilation happens on OneStore's servers — the already-signed .ipa passes through to Apple as-is. The free plan (3 apps, 1 seat, no card required) includes binary upload; it's not a paid add-on.
Shipping Android too? The .aab goes to Google Play from the same place. For the full mechanics of that specific pipeline (macOS worker, xcrun altool --upload-app, vault encryption), see the deep-dive: how OneStore uploads your binaries.
Choosing the right method
| Method | OS | GUI | API key | Best for |
|---|---|---|---|---|
| Apple Transporter | macOS + Linux (Docker) | Yes (macOS only) | Yes | Most cases |
| altool | macOS only | No | Yes | Legacy pipelines |
| App Store Connect API | Any OS | No | Yes | Custom CI/CD |
| Fastlane deliver | macOS + Linux | No | Yes | Existing Fastlane setups |
| OneStore | Any OS (web) | Yes | Yes | Unified listing + upload workflow |
App-specific passwords vs API keys
Apple still supports app-specific passwords for Transporter and altool, but API keys (.p8) are the better call for a 2026 pipeline: they don't expire when a password changes, they let you scope permissions precisely, and they don't trigger 2FA prompts in CI. Generate one in App Store Connect under Users and Access, Integrations tab, App Store Connect API section.
FAQs
Can I upload from a Windows machine?
Yes — the Transporter Docker image with Docker Desktop, or calling the App Store Connect REST API directly. Neither needs macOS.
Do I need Xcode Command Line Tools for Transporter?
No — the Mac App Store version of Transporter and the Docker image are both independent of Xcode Command Line Tools. Only altool requires them.
What's the difference between Transporter and altool?
Both upload binaries to App Store Connect. Apple deprecated altool and recommends Transporter for any new setup.
Can I upload a React Native or Flutter .ipa the same way?
Yes — the upload method doesn't care about the framework, as long as the .ipa is correctly signed and the bundle ID matches the App Store Connect record.
How do I generate a .p8 key?
Log into App Store Connect, Users and Access, Integrations tab, create a key under App Store Connect API, and download the .p8 immediately — Apple only lets you download it once.
Is it safe to store my .p8 key in a third-party tool?
Depends how the tool stores it. At OneStore, for example, the key is encrypted at rest with AES-256-GCM (authenticated encryption) at the application layer, never stored in plaintext in the database or logs, and a DPA based on the EU Standard Contractual Clauses is available on request. That's not the same as physical EU hosting or blanket GDPR compliance — always check exactly what a tool claims before handing it a key that can publish on your behalf.
What if my upload succeeds but the build doesn't show up in TestFlight?
Apple's processing typically takes 5 to 30 minutes. If it still hasn't appeared after an hour, check your email for a processing failure notice — common causes are export compliance questions or a missing encryption declaration in Info.plist.