# How the ipatool Search Command Queries the App Store Across Different Platforms

> Discover how the ipatool search command queries the App Store differently for VisionOS and other platforms. Understand the dual-request flow and single iTunes API request.

- Repository: [Majd/ipatool](https://github.com/majd/ipatool)
- Tags: internals
- Published: 2026-09-06

---

**The `ipatool search` command queries the App Store through a platform-aware architecture that branches between a dual-request flow for VisionOS and a single iTunes API request for all other platforms.**

The `ipatool search` command is a thin CLI wrapper around the **AppStore** service in `majd/ipatool`. According to the source code, it adapts its HTTP strategy based on the target platform, handling VisionOS as a special case while using a unified approach for iOS, iPadOS, tvOS, and macOS.

## CLI Entry Point and Input Parsing

The search workflow begins in [`cmd/search.go`](https://github.com/majd/ipatool/blob/main/cmd/search.go), where the command registers the `--platform` flag and assembles user input into a structured request.

The `searchCmd()` function constructs an `appstore.SearchInput` containing:
- The search term
- The result limit (`--limit`)
- The parsed platform from `appstore.ParsePlatform`

This input struct is passed directly to the core AppStore service method `Search()` defined in [`pkg/appstore/appstore_search.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/appstore_search.go).

## Platform-Aware Request Routing

The `appstore.Search()` method in [`pkg/appstore/appstore_search.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/appstore_search.go) implements the core branching logic for platform-specific queries.

### iOS, iPadOS, tvOS, and macOS: Standard Search Flow

For all platforms **except VisionOS**, the code path is:

1. Call `searchRequest()` → `searchURL()`
2. Build the iTunes Search API URL using:
   - `platform.searchEntity()` — determines the correct entity parameter
   - Country code derived from the user's storefront
   - URL-encoded search term
   - Requested limit

The `searchEntity()` method (in [`pkg/appstore/platform.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/platform.go)) maps internal platform constants to iTunes API entity strings like `software`, `iPadSoftware`, `tvSoftware`, or `macSoftware`.

### VisionOS: Dual-Request Storefront Flow

VisionOS triggers a fundamentally different approach via `searchVisionOS()`:

1. **First request** — Hits the **storefront endpoint** (`visionSearchURL`) to retrieve a lightweight list of app IDs
2. **Second request** — Enriches results with full metadata via lookup requests

This two-phase design exists because VisionOS apps are not indexed through the standard iTunes Search API, requiring direct storefront interaction.

## HTTP Execution and Response Handling

Both code paths use the shared `http.Client` (`t.searchClient` for standard platforms, `t.storefrontClient` for VisionOS storefront calls). Requests are issued as GET operations with format-specific decoding:

- **Standard platforms**: JSON response decoded via `http.ResponseFormatJSON`
- **VisionOS**: Raw data handling for storefront responses

The response is marshaled into `SearchOutput` with `Count` and `Results []App` fields. Any non-200 status code converts to a structured `appstore.Error` containing request metadata for debugging.

## Platform Constants and Entity Mapping

The [`pkg/appstore/platform.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/platform.go) file defines the platform abstraction:

| Platform | Internal Constant | Search Entity |
|----------|------------------|---------------|
| iPhone | `PlatformIOS` | `software` |
| iPad | `PlatformIPadOS` | `iPadSoftware` |
| Apple TV | `PlatformTVOS` | `tvSoftware` |
| Vision | `PlatformVisionOS` | storefront API |
| Mac | `PlatformMacOS` | `macSoftware` |

The `ParsePlatform()` function normalizes CLI flag values to these constants, while `searchEntity()` and `lookupEntity()` methods determine the correct iTunes API parameters.

## Usage Examples

Search for iPhone apps (default platform):

```bash
ipatool search "candy crush" --limit 5

```

Explicit platform selection:

```bash

# iPad apps

ipatool search "procreate" --platform ipad

# macOS apps

ipatool search "final cut pro" --platform macos

# VisionOS apps (triggers storefront flow)

ipatool search "spatial game" --platform visionos

```

## Summary

- The `ipatool search` command routes queries through [`pkg/appstore/appstore_search.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/appstore_search.go) where platform type determines the HTTP strategy
- **VisionOS** uses a specialized `searchVisionOS()` implementation with storefront API calls
- **All other platforms** use standard iTunes Search API requests constructed via `searchURL()` with platform-specific entities
- Platform parsing and entity mapping live in [`pkg/appstore/platform.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/platform.go) with `ParsePlatform()` and `searchEntity()`
- Responses unify to `SearchOutput` regardless of underlying request complexity

## Frequently Asked Questions

### How does ipatool handle VisionOS differently from other platforms?

VisionOS requires a two-phase query through the storefront API instead of the iTunes Search API. The `searchVisionOS()` function first retrieves a lightweight app list from `visionSearchURL`, then performs secondary lookup requests to fetch complete metadata. This compensates for VisionOS apps not being indexed in the standard search endpoint.

### What file contains the platform-to-entity mapping logic?

The mapping lives in [`pkg/appstore/platform.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/platform.go). The `searchEntity()` method returns `software` for iPhone, `iPadSoftware` for iPad, `tvSoftware` for Apple TV, and `macSoftware` for Mac. VisionOS bypasses this entirely and uses storefront endpoints.

### Can I search without specifying a platform flag?

Yes. When omitted, the platform defaults based on context, and the `ParsePlatform()` function handles normalization. The CLI in [`cmd/search.go`](https://github.com/majd/ipatool/blob/main/cmd/search.go) constructs the `SearchInput` with whatever platform value is provided (or default), and the core service handles the rest.

### Where does the actual HTTP request happen?

The `appstore.Search()` method in [`pkg/appstore/appstore_search.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/appstore_search.go) delegates to `t.searchClient.Send()` for standard platforms and `t.storefrontClient.Send()` for VisionOS. Both use the shared HTTP client abstraction defined elsewhere in the `pkg/appstore` package.