# How ipsw Downloads Firmware from Apple, AppleDB, and the Developer Portal

> Learn how ipsw downloads iOS firmware from Apple, AppleDB, and the Developer Portal using its modular engine and unified TLS transport. Get firmware easily.

- Repository: [blacktop/ipsw](https://github.com/blacktop/ipsw)
- Tags: how-to-guide
- Published: 2026-02-26

---

**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`](https://github.com/blacktop/ipsw/blob/main/internal/download/appledb.go) |
| **Developer Portal** | Authenticated downloads for beta IPSWs, KDKs, and internal tools | [`internal/download/dev_portal.go`](https://github.com/blacktop/ipsw/blob/main/internal/download/dev_portal.go) |
| **OTA (Pallas)** | Official over-the-air update packages, delta updates, and simulator runtimes | [`internal/download/ota.go`](https://github.com/blacktop/ipsw/blob/main/internal/download/ota.go) |

All three sources share a unified **TLS transport** ([`internal/download/transport_apple.go`](https://github.com/blacktop/ipsw/blob/main/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`](https://github.com/blacktop/ipsw/blob/main/internal/download/appledb.go) defines filter criteria:

```go
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.

```go
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`](https://github.com/blacktop/ipsw/blob/main/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`.

```go
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`](https://github.com/blacktop/ipsw/blob/main/internal/download/downloader.go)) with the authenticated client to save files, supporting resume and skip flags.

```go
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`](https://github.com/blacktop/ipsw/blob/main/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.

```go
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`](https://github.com/blacktop/ipsw/blob/main/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 `--insecure` flags via `InsecureSkipVerify`
- 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`](https://github.com/blacktop/ipsw/blob/main/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`](https://github.com/blacktop/ipsw/blob/main/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`](https://github.com/blacktop/ipsw/blob/main/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`](https://github.com/blacktop/ipsw/blob/main/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`](https://github.com/blacktop/ipsw/blob/main/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`](https://github.com/blacktop/ipsw/blob/main/internal/download/ota.go)) specifically implements the Pallas protocol to retrieve delta updates and signed manifests.