How ipsw Downloads Firmware from Apple, AppleDB, and the Developer Portal
The ipsw CLI uses a modular download engine with three distinct backends—AppleDB for public URLs, the Apple Developer Portal for authenticated beta firmware, and the Pallas OTA service for over-the-air updates—to fetch IPSW files, KDKs, and delta packages through a unified TLS transport layer.
The ipsw download firmware capability is built into the blacktop/ipsw repository, a Go-based toolkit for iOS and macOS security research. Rather than relying on a single hardcoded endpoint, the tool implements source-specific adapters that handle authentication, caching, and protocol differences automatically. This architecture allows users to query firmware by version, build, or device identifier without manually navigating multiple Apple services.
The Three-Source Architecture for ipsw Firmware Downloads
ipsw abstracts firmware acquisition into three interchangeable backends defined in internal/download/:
| Source | Purpose | Entry Point |
|---|---|---|
| AppleDB | Community-maintained JSON database mapping versions to public CDN URLs | internal/download/appledb.go |
| Developer Portal | Authenticated downloads for beta IPSWs, KDKs, and internal tools | internal/download/dev_portal.go |
| OTA (Pallas) | Official over-the-air update packages, delta updates, and simulator runtimes | internal/download/ota.go |
All three sources share a unified TLS transport (internal/download/transport_apple.go) that injects the Apple root CA and handles proxy configurations.
Downloading from AppleDB: The Community Firmware Database
AppleDB provides structured metadata without requiring authentication. The ipsw download firmware workflow treats this as the default path for public releases.
Querying the AppleDB Repository
The ADBQuery struct in internal/download/appledb.go defines filter criteria:
type ADBQuery struct {
OSes []string // "iOS", "macOS", "tvOS", etc.
Type string // "ipsw", "ota", "rsr"
Version string
Build string
Device string
Latest bool
Beta bool
// ... proxy, insecure flags
}
The OsFiles.Query(q) method (lines 60-124) filters the dataset and returns []OsFileSource, each containing a Links array with direct URLs to Apple’s CDN.
Local Caching and Remote Fallback
LocalAppleDBQuery checks for a cloned repository at ~/.config/ipsw/appledb. If missing, AppleDBQuery falls back to the GitHub API (ApiContentsURL) to fetch JSON files remotely. This ensures ipsw download firmware operations succeed even when the local cache is stale.
package main
import (
"fmt"
"github.com/blacktop/ipsw/internal/download"
)
func main() {
q := &download.ADBQuery{
OSes: []string{"iOS"},
Type: "ipsw",
Device: "iPhone15,2",
Latest: true,
}
// Try local cache first
srcs, err := download.LocalAppleDBQuery(q)
if err != nil {
srcs, err = download.AppleDBQuery(q) // Remote fallback
}
if err != nil {
panic(err)
}
for _, src := range srcs {
for _, link := range src.Links {
fmt.Printf("URL: %s\n", link.URL)
}
}
}
Accessing the Apple Developer Portal for Beta Firmware
For pre-release software, ipsw implements an authenticated scraper in internal/download/dev_portal.go.
Session Management and Two-Factor Authentication
The DevPortal struct wraps an http.Client using newAppleHTTPTransport for TLS. The Login method handles Apple ID credentials and 2FA, storing session tokens (SessionID, SCNT, WidgetKey) and a signed HashCash header in DevConfig.
type DevPortal struct {
Client *http.Client
Config *DevConfig
// ... session state
}
Scraping More Downloads
The getDownloads function POSTs to listDownloadsActionURL to retrieve the "More Downloads" list. Each MoreDownload entry contains Files with dfile objects. The dfile.URL() method (lines 29-38) generates the final download link, sanitized by sanitizeURL to prevent malformed redirects.
The Download method uses the shared Downloader struct (internal/download/downloader.go) with the authenticated client to save files, supporting resume and skip flags.
package main
import (
"log"
"github.com/blacktop/ipsw/internal/download"
)
func main() {
cfg := &download.DevConfig{
ConfigDir: "/home/user/.config/ipsw",
Insecure: false,
}
dp := download.NewDevPortal(cfg)
if err := dp.Init(); err != nil {
log.Fatal(err)
}
// Login interactively (handles 2FA)
if err := dp.Login("", ""); err != nil {
log.Fatal(err)
}
// Download a specific beta URL obtained from AppleDB or portal scraping
err := dp.Download("https://developer.apple.com/services-account/...", "./beta_firmware")
if err != nil {
log.Fatal(err)
}
}
Fetching OTA Updates via the Pallas Service
For over-the-air updates, internal/download/ota.go implements the Pallas/mesu protocol used by iOS devices.
Building Pallas Requests
The NewOTA function loads the public OTA plist, then buildPallasRequests (lines 75-100) constructs pallasRequest objects. It derives AssetAudienceID from embedded audienceData and expands device/product combinations using the IPSW device database (info.GetIpswDB()).
Decoding JWE Responses
The sendPostAsync function POSTs to https://gdmf.apple.com/v2/assets. Responses are JWE-like blobs split on .; the middle segment is base64-decoded (lines 90-101) to reveal JSON Asset objects. These are filtered by filterOTADevices (lines 84-150) based on version, build, and device allowlists.
Each Asset.URL is passed to the shared Downloader for retrieval.
package main
import (
"fmt"
"github.com/blacktop/ipsw/internal/download"
"github.com/hashicorp/go-version"
)
func main() {
ver, _ := version.NewVersion("17.2")
cfg := download.OtaConf{
Platform: "ios",
Device: "iPhone13,2",
Version: ver,
Delta: true,
}
aset, _ := download.NewAssetSets()
ota, _ := download.NewOTA(aset, cfg)
assets, err := ota.GetPallasOTAs()
if err != nil {
panic(err)
}
for _, a := range assets {
fmt.Printf("Delta OTA: %s -> %s\n", a.Build, a.URL)
}
}
Unified TLS Transport and Security
All three download backends rely on newAppleHTTPTransport in internal/download/transport_apple.go. This helper:
- Loads the system CA pool by default
- Injects the bundled Apple root CA (
rootcert.AppleRootCA) to ensure trust on minimal containers - Respects
--insecureflags viaInsecureSkipVerify - Detects proxy configurations and adjusts TLS settings accordingly
This unified transport ensures that ipsw download firmware operations maintain consistent security posture across AppleDB, Developer Portal, and OTA endpoints.
Summary
- AppleDB backend (
internal/download/appledb.go) provides unauthenticated access to public firmware URLs via community-maintained JSON, with local caching and GitHub API fallback. - Developer Portal backend (
internal/download/dev_portal.go) implements authenticated sessions (Apple ID + 2FA) to scrape "More Downloads" and retrieve beta IPSWs and KDKs. - OTA backend (
internal/download/ota.go) communicates with Apple's Pallas service to fetch delta updates and signed assets using JWE response decoding. - Unified transport (
internal/download/transport_apple.go) handles TLS configuration, Apple root CA injection, and proxy support for all sources.
Frequently Asked Questions
Does ipsw require authentication to download firmware?
No, for public firmware. The AppleDB backend retrieves direct CDN URLs without credentials. However, accessing the Developer Portal for beta firmware requires a valid Apple ID with developer membership and two-factor authentication. The OTA backend also works without authentication for public updates.
How does ipsw handle firmware downloads when AppleDB is offline?
ipsw implements a fallback mechanism. LocalAppleDBQuery first checks the local clone at ~/.config/ipsw/appledb. If the cache is missing or stale, AppleDBQuery automatically queries the GitHub API to fetch osFiles JSON directly, ensuring ipsw download firmware capabilities remain functional even without a local copy.
Can ipsw resume interrupted firmware downloads?
Yes. The Downloader struct in internal/download/downloader.go supports resume functionality. When a download is interrupted, subsequent attempts use HTTP range requests to continue from the last received byte. The --resume flag (or equivalent API configuration) enables this behavior across all three backends: AppleDB, Developer Portal, and OTA.
What is the difference between IPSW and OTA downloads in ipsw?
IPSW (iPhone Software) files are complete firmware bundles used for restore operations via iTunes/Finder or ipsw itself. OTA (Over-The-Air) updates are typically smaller delta packages used by devices for incremental updates. In ipsw, the AppleDB and Developer Portal backends primarily handle IPSW files, while the OTA backend (internal/download/ota.go) specifically implements the Pallas protocol to retrieve delta updates and signed manifests.
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 →