# Apple App Store Reviews Scraper | iOS & Mac (`peerless_columbine/apple-app-store-reviews-scraper-api`) Actor

Collect iOS and Mac App Store reviews across countries. Export ratings, review text, dates and developer replies where available. Filter by date, deduplicate results and schedule product-feedback monitoring.

- **URL**: https://apify.com/peerless\_columbine/apple-app-store-reviews-scraper-api.md
- **Developed by:** [tingyou333 zhuang](https://apify.com/peerless_columbine) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.05 / 1,000 review delivereds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Apple App Store Reviews Scraper | iOS & Mac

Collect iOS and Mac App Store reviews for product feedback, ASO and release monitoring. Export review text, ratings, dates, reviewed versions and source context across multiple storefronts.

[Quick start](#quick-start) · [Workflows](#common-workflows) · [Pricing](#pricing) · [Input reference](#input-reference) · [Output reference](#output-reference) · [API and automation](#api-and-automation) · [FAQ](#faq) · [Technical reference](#technical-reference)

### What you can do

- **One app or a portfolio** — Use app IDs, store URLs or the app-name compatibility input.
- **iOS and Mac coverage** — Choose the source and platform explicitly; archive mode supports deeper pagination where available.
- **Useful review context** — Retain ratings, text, dates, reviewed versions and helpfulness data exposed by Apple.
- **Budget and quality controls** — Set global and per-storefront limits; inspect source metadata instead of assuming the requested history was complete.

#### Who uses it

- Product teams: organize complaints and requests by app version.
- ASO and research teams: compare ratings and written feedback across country storefronts.
- Data teams: feed scheduled review exports into a warehouse or an external sentiment-analysis workflow.

### Quick start

1. Open **Input**, enter your target and a small result limit.
2. Click **Start** and inspect the dataset and run log.
3. Export JSON/CSV, or save the input as a Task for recurring runs.

```json
{
  "appIds": [
    "389801252"
  ],
  "country": "us",
  "sourceMode": "archive",
  "maxItems": 20
}
```

Form prefills, schema defaults and empty API input can differ. Use explicit targets and limits; see the technical reference for source and default behavior.

<details>
<summary>Default input behavior and source options</summary>

Default target is app `389801252`, US. Empty local input selects RSS; platform Schema defaults include `platform=auto` and enable detection/archive. Set `sourceMode` explicitly for reproducible source selection. Form prefills are not API defaults.

</details>

### Countries and storefront coverage

**`us` is a default, not the only supported storefront.** Use `country` for one storefront, or `countries` for multiple storefronts. A nonempty `countries` list takes precedence.

Archive and Mac routing now includes **175 storefronts**, using [Apple's public storefront selector](https://itunes.apple.com/WebObjects/MZStore.woa/wa/countrySelectorPage). The Input form lists country names and codes, with multi-selection through `countries`. Examples include `us`, `gb`, `cn`, `jp`, `sg`, `nl` and `za`.

A September 9, 2026 source check retrieved one iOS archive review from each of the 175 storefronts for app `389801252`, with distinct review IDs. This is a small-sample routing check, not a guarantee of every app, full history, every metadata field or every Mac storefront. App availability and source responses still determine results.

Country selects the review storefront, not a translation language. RSS retains its ceiling of 500 recent reviews per app/storefront. Archive scans use their configured caps and may have incomplete history.

#### Import an existing configuration

Choose `wolvesInput` for The Wolves inputs or `johnvcInput` for the Apple App Store Reviews API inputs. Paste the original JSON object inside the selected field. Keep all overrides inside that object; do not mix it with outer native settings. This preserves the selected reference's defaults without interference from the form's native defaults. Existing top-level inputs remain supported.

```json
{"wolvesInput": {"appIds": ["389801252"], "country": "sg", "maxItems": 20}}
```

Import compatibility covers documented input contracts, not a promise of identical source availability or output metadata. Select the documented output schema separately when needed.

<details>
<summary>175 country options — names and codes</summary>

The form suggestions below identify request values; app, publisher and source availability still apply.

| Code | Name |
|---|---|
| `us` | United States (us) |
| `ae` | UAE (ae) |
| `af` | Afghanistan (af) |
| `ag` | Antigua and Barbuda (ag) |
| `ai` | Anguilla (ai) |
| `al` | Albania (al) |
| `am` | Armenia (am) |
| `ao` | Angola (ao) |
| `ar` | Argentina (ar) |
| `at` | Austria (at) |
| `au` | Australia (au) |
| `az` | Azerbaijan (az) |
| `ba` | Bosnia and Herzegovina (ba) |
| `bb` | Barbados (bb) |
| `be` | Belgium (be) |
| `bf` | Burkina Faso (bf) |
| `bg` | Bulgaria (bg) |
| `bh` | Bahrain (bh) |
| `bj` | Benin (bj) |
| `bm` | Bermuda (bm) |
| `bn` | Brunei Darussalam (bn) |
| `bo` | Bolivia (bo) |
| `br` | Brazil (br) |
| `bs` | Bahamas (bs) |
| `bt` | Bhutan (bt) |
| `bw` | Botswana (bw) |
| `by` | Belarus (by) |
| `bz` | Belize (bz) |
| `ca` | Canada (ca) |
| `cd` | Democratic Republic of the Congo (cd) |
| `cg` | Republic of the Congo (cg) |
| `ch` | Switzerland (ch) |
| `ci` | Côte d’Ivoire (ci) |
| `cl` | Chile (cl) |
| `cm` | Cameroon (cm) |
| `cn` | China mainland (cn) |
| `co` | Colombia (co) |
| `cr` | Costa Rica (cr) |
| `cv` | Cape Verde (cv) |
| `cy` | Cyprus (cy) |
| `cz` | Czech Republic (cz) |
| `de` | Germany (de) |
| `dk` | Denmark (dk) |
| `dm` | Dominica (dm) |
| `do` | Dominican Republic (do) |
| `dz` | Algeria (dz) |
| `ec` | Ecuador (ec) |
| `ee` | Estonia (ee) |
| `eg` | Egypt (eg) |
| `es` | Spain (es) |
| `fi` | Finland (fi) |
| `fj` | Fiji (fj) |
| `fm` | Micronesia, Federated States of (fm) |
| `fr` | France (fr) |
| `ga` | Gabon (ga) |
| `gb` | United Kingdom (gb) |
| `gd` | Grenada (gd) |
| `ge` | Georgia (ge) |
| `gh` | Ghana (gh) |
| `gm` | Gambia (gm) |
| `gr` | Greece (gr) |
| `gt` | Guatemala (gt) |
| `gw` | Guinea-Bissau (gw) |
| `gy` | Guyana (gy) |
| `hk` | Hong Kong (hk) |
| `hn` | Honduras (hn) |
| `hr` | Croatia (hr) |
| `hu` | Hungary (hu) |
| `id` | Indonesia (id) |
| `ie` | Ireland (ie) |
| `il` | Israel (il) |
| `in` | India (in) |
| `iq` | Iraq (iq) |
| `is` | Iceland (is) |
| `it` | Italy (it) |
| `jm` | Jamaica (jm) |
| `jo` | Jordan (jo) |
| `jp` | Japan (jp) |
| `ke` | Kenya (ke) |
| `kg` | Kyrgyzstan (kg) |
| `kh` | Cambodia (kh) |
| `kn` | St. Kitts and Nevis (kn) |
| `kr` | Korea, Republic of (kr) |
| `kw` | Kuwait (kw) |
| `ky` | Cayman Islands (ky) |
| `kz` | Kazakhstan (kz) |
| `la` | Lao People’s Democratic Republic (la) |
| `lb` | Lebanon (lb) |
| `lc` | St. Lucia (lc) |
| `lk` | Sri Lanka (lk) |
| `lr` | Liberia (lr) |
| `lt` | Lithuania (lt) |
| `lu` | Luxembourg (lu) |
| `lv` | Latvia (lv) |
| `ly` | Libya (ly) |
| `ma` | Morocco (ma) |
| `md` | Moldova (md) |
| `me` | Montenegro (me) |
| `mg` | Madagascar (mg) |
| `mk` | North Macedonia (mk) |
| `ml` | Mali (ml) |
| `mm` | Myanmar (mm) |
| `mn` | Mongolia (mn) |
| `mo` | Macao (mo) |
| `mr` | Mauritania (mr) |
| `ms` | Montserrat (ms) |
| `mt` | Malta (mt) |
| `mu` | Mauritius (mu) |
| `mv` | Maldives (mv) |
| `mw` | Malawi (mw) |
| `mx` | Mexico (mx) |
| `my` | Malaysia (my) |
| `mz` | Mozambique (mz) |
| `na` | Namibia (na) |
| `ne` | Niger (ne) |
| `ng` | Nigeria (ng) |
| `ni` | Nicaragua (ni) |
| `nl` | Netherlands (nl) |
| `no` | Norway (no) |
| `np` | Nepal (np) |
| `nr` | Nauru (nr) |
| `nz` | New Zealand (nz) |
| `om` | Oman (om) |
| `pa` | Panama (pa) |
| `pe` | Peru (pe) |
| `pg` | Papua New Guinea (pg) |
| `ph` | Philippines (ph) |
| `pk` | Pakistan (pk) |
| `pl` | Poland (pl) |
| `pt` | Portugal (pt) |
| `pw` | Palau (pw) |
| `py` | Paraguay (py) |
| `qa` | Qatar (qa) |
| `ro` | Romania (ro) |
| `rs` | Serbia (rs) |
| `ru` | Russia (ru) |
| `rw` | Rwanda (rw) |
| `sa` | Saudi Arabia (sa) |
| `sb` | Solomon Islands (sb) |
| `sc` | Seychelles (sc) |
| `se` | Sweden (se) |
| `sg` | Singapore (sg) |
| `si` | Slovenia (si) |
| `sk` | Slovakia (sk) |
| `sl` | Sierra Leone (sl) |
| `sn` | Senegal (sn) |
| `sr` | Suriname (sr) |
| `st` | São Tomé and Príncipe (st) |
| `sv` | El Salvador (sv) |
| `sz` | Eswatini (sz) |
| `tc` | Turks and Caicos (tc) |
| `td` | Chad (td) |
| `th` | Thailand (th) |
| `tj` | Tajikistan (tj) |
| `tm` | Turkmenistan (tm) |
| `tn` | Tunisia (tn) |
| `to` | Tonga (to) |
| `tr` | Türkiye (tr) |
| `tt` | Trinidad and Tobago (tt) |
| `tw` | Taiwan (tw) |
| `tz` | Tanzania (tz) |
| `ua` | Ukraine (ua) |
| `ug` | Uganda (ug) |
| `uy` | Uruguay (uy) |
| `uz` | Uzbekistan (uz) |
| `vc` | St. Vincent and The Grenadines (vc) |
| `ve` | Venezuela (ve) |
| `vg` | British Virgin Islands (vg) |
| `vn` | Vietnam (vn) |
| `vu` | Vanuatu (vu) |
| `xk` | Kosovo (xk) |
| `ye` | Yemen (ye) |
| `za` | South Africa (za) |
| `zm` | Zambia (zm) |
| `zw` | Zimbabwe (zw) |

</details>

### Common workflows

#### Compare two storefronts

```json
{
  "appIds": [
    "389801252"
  ],
  "countries": [
    "us",
    "gb"
  ],
  "sourceMode": "archive",
  "maxItems": 40
}
```

#### Collect Mac app reviews

```json
{
  "appIds": [
    "497799835"
  ],
  "platform": "mac",
  "sourceMode": "archive",
  "maxItems": 20
}
```

#### Filter critical feedback

```json
{
  "appIds": [
    "389801252"
  ],
  "country": "us",
  "ratings": [
    "1",
    "2"
  ],
  "maxItems": 20
}
```

### Output at a glance

Illustrative field subset below; these are example values, not a captured customer review or a claim about source coverage. Native and compatibility output profiles can differ.

```json
{
  "appId": "389801252",
  "id": "example-review-id",
  "score": 4,
  "title": "Example review",
  "text": "Example feedback used to illustrate the output format.",
  "version": "1.2.0",
  "country": "us",
  "coverage": "complete"
}
```

RSS covers up to 500 recent reviews per app/storefront. Archive coverage is source-dependent and configured for 175 storefronts; a larger limit does not guarantee a complete historical archive. Some fields, including developer replies, may be absent. See the source reference below.

### Pricing

Pay per delivered event, with automatic discounts based on **your Apify subscription plan**. These are result fees in USD, not separate subscriptions sold by this Actor. All tiers have the same Actor features. **Apify compute, storage, transfers and any proxy usage are charged additionally.**

| Billable event (1,000 events) | Free | Starter | Scale | Business |
|---|---:|---:|---:|---:|
| Review delivered | $0.08 | $0.07 | $0.06 | $0.05 |

Platinum and Diamond currently use the Business rate. The **Pricing** tab is the source of truth for the active schedule and your applicable plan.

- **Review delivered**: One delivered review after filtering and output mapping. Error rows have no result fee. Apify platform usage is additional.

Example on the Free plan: 10 / 1,000 / 10,000 events cost $0.0008 / $0.08 / $0.8 in result fees, plus platform usage.

There is no additional developer setup or monthly rental fee. A run with no billable results can still consume platform resources. Start small, cap results and review run costs before scheduling a larger workload. Requested counts are ceilings, not guaranteed deliveries.

### Input reference

Fields below are grouped like the Input form. Optional fields need not be supplied. Compatibility input envelopes and transformations are explained in the technical reference.

#### Targets and collection

| Field | Type | Default | Meaning |
|---|---|---|---|
| `appIds` | array | Not set | Numeric Apple App Store IDs, without the id prefix. |
| `product_ids` | array | Not set | Compatibility alias for callers using product\_ids. |
| `startUrls` | array | Not set | Apple App Store application URLs. The app ID and storefront country are parsed automatically. |
| `app_name` | string | Not set | Optional app name to resolve through Apple's public Search API when no exact ID is available. |
| `country` | string | "us" | Select one of 175 Apple storefronts. us is only the default. Archive and Mac requests use the official Apple storefront ID for the selected country; actual reviews depend on app/source availability. Custom two-letter codes are accepted for RSS. A nonempty countries list overrides this field. |
| `countries` | array | Not set | Select multiple storefronts in one run. Overrides country. All 175 listed storefronts have Apple source mappings; an app may have no reviews in a selected market. Custom codes remain accepted for RSS. |
| `start_page` | integer | 1 | Page index/count. RSS ceiling 10; archive ceiling 2000, 25 reviews per page. |
| `since` | string | Not set | Optional ISO date or timestamp. Useful for scheduled incremental monitoring. |
| `deduplicateReviews` | boolean | true | Deduplicate by app ID, country and Apple review ID. |
| `requestDelayMillis` | integer | 500 | Spacing between pages inside one app/country task. Defaults to 500 ms to reduce bursts on long archive scans; set 0 explicitly to disable. |
| `sourceMode` | string | "auto" | RSS uses 50-row pages; iOS archive uses 25-row pages; Mac HTML uses native 10-row pages. Product IDs support automatic platform detection. |
| `platform` | string | "auto" | Automatically identify each product, or explicitly select iOS / Mac. Explicit selection takes precedence over detection. |
| `includeSourceMetadata` | boolean | true | For archive mode, make one extra metadata lookup per app/storefront for written-review and rating totals. Counts are unfiltered; derived page count is not an accessibility guarantee. |
| `includeReviewVersions` | boolean | true | For archive pages, join public XML version metadata by review ID and matching text. Adds one public request per page; failures retain the review and an explicit warning. |
| `include_macos` | boolean | true | Detect app platform and skip Mac apps when false. Explicit platform remains authoritative. |
| `parse_helpfulness` | boolean | true | Include helpful\_count and total\_helpful\_count when present in the public source. |
| `output_file` | string | Not set | Local testing only: save a delivered-result JSON copy under storage/local\_exports. Use a simple .json filename. Existing files are never overwritten. Ignored completely on Apify cloud; auto-generated locally if blank. |

#### Filters and ordering

| Field | Type | Default | Meaning |
|---|---|---|---|
| `sort` | string | "mostrecent" | Source-native Apple review sort. mostrecent and mosthelpful are verified public-feed modes. |
| `ratings` | array | Not set | Optional star ratings to keep after source retrieval, for example \["1","2"] for negative reviews. |
| `sort_order` | string | Not set | 1 helpful, 2 favorable, 3 critical, 4 recent. |
| `normalize_dates` | boolean | true | Include review\_date\_iso in johnvc-compatible output. |

#### Result limits and cost

| Field | Type | Default | Meaning |
|---|---|---|---|
| `maxItems` | integer | Not set | Optional global cap across all app/country combinations. Leave blank to derive the total budget from the per-app/storefront quota and task count for compatibility inputs (product\_ids, app\_name or max\_reviews); native inputs default to 1000 at runtime. An explicitly supplied value takes precedence over the automatic budget. |
| `maxReviewsPerAppCountry` | integer | Not set | Per app/country cap. RSS source ceiling is 500; archive ceiling is 50000. |
| `maxPages` | integer | Not set | Maximum native pages per app and country. Omit to derive the Mac/automatic budget from the requested review count; explicit limits take precedence. |
| `maxRequestRetries` | integer | 2 | Retries for transient Apple HTTP failures. |
| `max_reviews` | integer | Not set | Alias per app/country cap; zero uses selected source ceiling. maxItems remains the global cap. |

#### Compatibility and transformations

| Field | Type | Default | Meaning |
|---|---|---|---|
| `customMapFunction` | string | Not set | JavaScript function applied after output formatting to each review. Must return one JSON object. Isolated runtime with no network, file system or Python access; 50ms CPU and 16MB per row, 10s total. Not a filter. |
| `outputSchema` | string | "extended" | Explicit migration format. Missing source values stay null; extended preserves diagnostics. |

#### Connection and advanced settings

| Field | Type | Default | Meaning |
|---|---|---|---|
| `maxConcurrency` | integer | 8 | Maximum app/country combinations fetched concurrently. |

#### Additional compatibility options

| Field | Type | Default | Meaning |
|---|---|---|---|
| `wolvesInput` | object | Not set | Paste the complete competitor input JSON here to preserve its field types and defaults. Put all options inside this object. This is optional; normal native inputs remain available. |
| `johnvcInput` | object | Not set | Paste the complete competitor input JSON here to preserve its field types and defaults. Put all options inside this object. This is optional; normal native inputs remain available. |

### Output reference

The table describes native fields; fields can be absent or null when the source does not provide them. Error rows and selected compatibility profiles have different shapes. Nested objects remain structured in JSON; CSV exports may serialize them.

| Field | Type | Meaning |
|---|---|---|
| `parentId` | string | Compatibility field; Apple review identifier when no separate parent is exposed. |
| `id` | string | Unique Apple review identifier. |
| `date` | \['string', 'null'] | Review publication timestamp from Apple. |
| `userName` | \['string', 'null'] | Reviewer display name. |
| `userUrl` | \['string', 'null'] | Public iTunes reviewer URL when exposed. |
| `version` | \['string', 'null'] | App version reviewed. |
| `score` | integer | Star rating from 1 to 5. |
| `title` | \['string', 'null'] | Review headline. |
| `text` | string | Full review body. |
| `url` | \['string', 'null'] | Public iTunes review URL. |
| `country` | string | Review storefront code, e.g. `sg`; not a translation language. |
| `appId` | string | Numeric App Store application ID. |
| `voteCount` | \['integer', 'null'] | Apple im:voteCount value. |
| `voteSum` | \['integer', 'null'] | Apple im:voteSum value. |
| `sourcePage` | integer | Page number within the selected source: RSS has 50 rows/page, archive has 25. |
| `sortOrder` | string | Apple source sort used for retrieval. |
| `retrievalMethod` | string | Public Apple source path. |
| `coverage` | string | Completeness classification for the review row. |
| `scrapedAt` | string | UTC extraction timestamp. |
| `sourcePosition` | \['integer', 'null'] | sourcePosition |
| `sourceReviewCount` | \['integer', 'null'] | sourceReviewCount |
| `sourceRatingCount` | \['integer', 'null'] | sourceRatingCount |
| `sourceTotalPages` | \['integer', 'null'] | sourceTotalPages |
| `sourceMetadataStatus` | \['string', 'null'] | sourceMetadataStatus |
| `sourceTotalPagesBasis` | \['string', 'null'] | sourceTotalPagesBasis |
| `sourceMetadataUrl` | \['string', 'null'] | sourceMetadataUrl |
| `sourceMetadataCountry` | \['string', 'null'] | sourceMetadataCountry |
| `sourceMetadataFetchedAt` | \['string', 'null'] | sourceMetadataFetchedAt |
| `sourceMetadataWarning` | \['string', 'null'] | sourceMetadataWarning |
| `sourceMetadataError` | \['string', 'null'] | sourceMetadataError |

### API and automation

The **API** tab provides snippets for this Actor. For scheduled or larger collections, start a run asynchronously and poll its status instead of holding a synchronous request open. Keep your API token in an environment variable.

```python
import os, time, requests

base = "https://api.apify.com/v2"
headers = {"Authorization": "Bearer " + os.environ["APIFY_TOKEN"]}
actor_input = {'appIds': ['389801252'], 'country': 'us', 'sourceMode': 'archive', 'maxItems': 20}
response = requests.post(
    base + "/acts/5eWGsOTxIbgRUYZS5/runs",
    headers=headers, json=actor_input, timeout=30,
)
response.raise_for_status()
run = response.json()["data"]
for _ in range(720):
    if run["status"] not in ("READY", "RUNNING", "TIMING-OUT", "ABORTING"):
        break
    time.sleep(5)
    response = requests.get(base + "/actor-runs/" + run["id"], headers=headers, timeout=30)
    response.raise_for_status()
    run = response.json()["data"]
else:
    raise TimeoutError("Polling ended; inspect the existing run before starting another.")
if run["status"] != "SUCCEEDED":
    raise RuntimeError(run.get("statusMessage", run["status"]))
response = requests.get(
    base + "/datasets/" + run["defaultDatasetId"] + "/items",
    headers=headers, params={"format": "json", "limit": 1000, "offset": 0}, timeout=30,
)
response.raise_for_status()
rows = response.json()
print(rows)  # Paginate with offset for larger datasets; inspect per-row coverage.
```

#### Scheduled monitoring and integrations

1. Save a working input as an Apify Task.
2. Attach a Schedule in your timezone; keep runs sharing an incremental state key sequential.
3. Add a successful-run webhook or connect your downstream workflow to the dataset export/API.
4. Inspect missing/partial data before sending alerts or treating absence as removal.

Use the platform Integrations/API options to connect external workflows such as Make, n8n or a data warehouse. An external sentiment or summarization step is separate from this Actor and may have its own charges. The platform also supports Actor tools through [Apify MCP](https://docs.apify.com/platform/integrations/mcp); availability and client setup depend on your integration.

### FAQ

#### How do I find an app ID?

Use the digits after id in an App Store URL. For example, id389801252 becomes 389801252.

#### Can I retrieve every historical review?

No complete-history guarantee is made. Choose archive mode for supported deeper pages and inspect source coverage, limits and pagination stop reasons.

#### Are sentiment labels included?

Review text can be exported to an AI workflow. This Actor does not promise a built-in sentiment model.

#### Can I export without writing code?

Yes. Run from the Input form, open the dataset and use the export controls for JSON or CSV. Select your preferred output profile before running when migrating an integration.

#### Does a successful run guarantee every field?

No. Inspect coverage, warnings and source-specific status fields. Optional enrichment may be missing even when usable rows were delivered.

### Troubleshooting

| Symptom | What to check |
|---|---|
| Empty dataset | Validate the target, source availability and filters; try the small quick-start input. |
| Fewer rows than requested | Check source limits, pagination and filtering. Increasing a cap cannot create unavailable source records. |
| Partial fields | Inspect coverage/warnings and the relevant source or enrichment status. |
| Access or throttling errors | Check the run log and documented proxy configuration; retry at a lower request volume. |
| Migration mismatch | Check the explicit input/output profile and technical field mapping below. |
| Unexpected bill | Separate result events from platform resources; inspect enrichment, result caps and the Pricing tab. |

### Technical reference

#### Migration-friendly inputs

Existing callers can continue using the common `appIds`, `country`, `startUrls`, and `maxItems` fields. The Actor also accepts `product_ids` and `app_name` for compatibility with another established App Store review API.

Exact targets from `product_ids`, `appIds`, or `startUrls` take precedence over `app_name`: name resolution runs only when there are no exact targets. A supplied name never adds another app to an explicit target list.

For compatibility inputs (`product_ids`, `app_name`, or `max_reviews`), omitting `maxItems` derives the total budget from the per-app/storefront quota and the number of app/storefront tasks. For example, two IDs with `max_reviews: 600` receive a total budget of 1200, up to 600 each. Explicit `maxItems` retains the global cap. Native inputs without those compatibility fields retain the default global limit of 1000. Source/page limits still apply. The form leaves `maxItems` blank (no default or prefill), so automatic budgeting can apply. Remove a saved `maxItems` value from older inputs to use the derived budget; a value already present in the input is treated as explicit.

Extensions include:

- `countries`: fetch several App Store storefronts in one run.
- `sort`: Apple-native `mostrecent` or `mosthelpful` order.
- `ratings`: keep selected star ratings, such as `[1, 2]` for complaint monitoring.
- `since`: scheduled incremental collection by ISO date/time.
- `start_page` and `maxPages`: resumable bounded pagination.
- `voteCount` / `voteSum`, page number, retrieval method, and explicit coverage metadata on every row.

The RSS source exposes up to 50 reviews per page and 10 pages per app/storefront (500 reviews). Archive pagination has separate limits described below.

#### Example

```json
{
  "appIds": ["389801252"],
  "countries": ["us", "gb", "ca"],
  "sort": "mostrecent",
  "ratings": ["1", "2"],
  "since": "2026-09-01",
  "maxItems": 1000
}
```

Each review preserves the familiar 12-field shape (`parentId`, `id`, `date`, `userName`, `userUrl`, `version`, `score`, `title`, `text`, `url`, `country`, `appId`) and adds source telemetry without breaking those fields.

##### Result limits and pagination

`maxItems` is a maximum, not a guaranteed count. Apple may return an empty page before that limit. `SOURCE_DIAGNOSTICS` records each task's `stopReason`, page count, and `duplicatesSuppressed`; `OUTPUT.warnings` reports early empty-page termination. Deduplication occurs before a page task counts unique rows toward its limit. No complete historical review archive is promised.

##### RSS fallback and compatibility

An empty explicit first RSS page is retried through the public default first-page endpoint. Later pages are never replaced with page one. `max_reviews` aliases the per-app/storefront limit; zero uses the selected source ceiling (RSS 500; archive bounded at 50,000). `maxItems` is the global cap. Select `outputSchema=johnvc` for that field layout. Archive mode supports deep pagination, Mac reviews and favorable/critical sorting.

#### Output profiles and custom JavaScript

The default `outputSchema=extended` preserves the existing output. Apple supports `wolves` and `johnvc`. These are explicit field projections, not a guarantee of identical source pagination or data availability. Missing source fields remain null.

`customMapFunction` runs after output projection and before delivery. Example: `(row) => ({...row, exported: true})`. It must synchronously return one JSON object per row. Async functions, filtering and non-object results fail the run before delivery. Each row has 50 ms CPU, 16 MB memory and 256 KB stack limits; total mapping budget is 10 seconds. The interpreter has no network, filesystem or host callbacks.

#### Archive source

`sourceMode=archive` uses 25-row iOS pages and 10-row Mac pages. iOS `start_page=21` starts at offset 500. Archive traversal is bounded by 2,000 pages and 50,000 reviews per app/storefront, subject to source availability; Mac page size imposes a lower attainable page-bound total. `sourceMode=auto` selects archive for platform detection, Mac, a start page above 10, favorable/critical sorting, or a per-app quota above 500. Increasing only global `maxItems` does not force archive. RSS and archive page numbers differ.

Archive storefronts: the 175 named options in Input, sourced from Apple’s public country selector. Unconfigured storefronts fail explicitly. Archive rows may omit reviewed version and total page counts; these remain null. Source rows, identity, rating and review body are preserved; no complete-history guarantee.

Archive requests use each storefront's default language; they do not force US English onto other countries. The country code still selects the review storefront.

##### Archive totals and migration positions

Archive mode defaults to `includeSourceMetadata=true`, which performs an extra
public storefront metadata lookup for each app/country task. It verifies app and
platform identity. `sourceReviewCount` is written reviews; `sourceRatingCount`
includes ratings and must not be used as the written-review count.
`sourceTotalPages` uses the source written-review count and native page size
(25 for iOS archive, 10 for Mac). It does not prove every page is accessible; configured page
and result ceilings still apply. Counts are not adjusted for local date/rating
filters. Disable the option to avoid the metadata lookup.

Metadata failure retains review rows and reports `sourceMetadataStatus=failed`
in rows and source diagnostics. Historical reviewed versions and current-version
review counts remain unknown unless provided by a reliable source.

For `outputSchema=johnvc`, `position_on_page` follows the reference's source-offset
convention: iOS archive page 21 starts at 501. `position_global` remains the emitted
row number. The extended format retains true within-page `positionOnPage` plus
absolute `sourcePosition`. The display date is formatted in English from the
source timestamp when no source display date is provided.

##### Historical review versions

Archive mode now enables `includeReviewVersions` by default. Each page joins Apple public XML metadata by review ID and matching text, recovering the actual reviewed version and current-version review count. Explicit pagination supports thousands separators (74,021 remains 74021). This adds one public request per page. Disable it to reduce requests. Unmatched or unavailable metadata stays unknown with a warning; application release dates are never used to guess a reviewed version. Source page counts do not guarantee all pages can be retrieved.

The `johnvc` compatibility output collapses whitespace in titles and review bodies to match that interface; `extended` preserves source line breaks. Verified XML locales: US, GB, CN, JP, DE, FR, CA, AU, IN, KR, TW, HK, IT, ES, BR and MX. Version labels and pagination are parsed in the source locale. Missing source counts (such as the Japanese current-version `[?]` placeholder) remain unknown. Mac reviews use their public HTML endpoint, with native 10-row pages and per-review versions. Product IDs are platform-detected; include\_macos=false skips Mac applications.

##### Mac compatibility

Mac comments use native ten-row HTML pagination and per-review version metadata. `johnvc` outputs `app_platform=macos` and `reviewed_version=v...`; `normalize_dates` and `parse_helpfulness` are supported. Source day-only dates carry `datePrecision=day` in extended output. Mac sorting is sent to the source and returned sort/page are validated. Unavailable current-version totals remain null.

Automatic platform detection derives the native-page budget from the requested review count when `maxPages` is omitted; Mac pages contain ten reviews. An explicit `maxPages` still limits the scan. A per-app review quota above 500 selects archive in auto mode; global maxItems alone does not. `actualRetrievalMethods` and `actualPlatforms` in OUTPUT identify the sources that actually delivered rows. A Mac current-version review count is left unavailable unless independently established; it is not inferred from the app's overall rating count.

`output_file` is a local-only JSON export option for delivered rows. Blank names are generated automatically and existing files are never overwritten. Cloud runs ignore this option; retrieve cloud results from the run dataset.

Long scans default to 500 ms between pages within each app/country task (`requestDelayMillis=0` explicitly disables spacing). Mac pagination follows the declared last page, including short intermediate pages. An isolated failed request is recorded in `SOURCE_DIAGNOSTICS.tasks[].sourceMetadata.failedPages` and later declared pages are still attempted; three consecutive failures stop the task. Any missing page makes the task report an error, and already collected reviews remain available. Use `start_page` to resume a known range. Retry counts include exhausted requests.

After a complete unfiltered Mac traversal from page 1 through the declared last page, with continuous positions, no missing pages, no duplicate IDs and all review versions available, the Actor can compute the observed written-review count for the current version returned by Apple lookup. `currentVersionReviewCountBasis` explicitly identifies this calculation. The johnvc profile adds `reviews_for_current_version_basis` and `current_app_version` when this count is computed. Partial/filtered scans never extrapolate totals, and rating counts are never substituted for written reviews. Lookup failure preserves all comments and the known traversed count but leaves the version-specific count unavailable.

### Support

Open an issue from this Actor’s **Issues** tab with the run ID, expected result and a redacted input. Do not include tokens, cookies or private credentials. Include the output profile and affected field when reporting a migration mismatch.

### Presentation update

The current listing adds workflow examples, grouped input documentation, output-field explanations and plan-based result discounts. Source-specific limitations above still apply. This is an independent tool and is not affiliated with the source platform.

# Actor input Schema

## `appIds` (type: `array`):

Numeric Apple App Store IDs, without the id prefix.

## `product_ids` (type: `array`):

Compatibility alias for callers using product\_ids.

## `startUrls` (type: `array`):

Apple App Store application URLs. The app ID and storefront country are parsed automatically.

## `app_name` (type: `string`):

Optional app name to resolve through Apple's public Search API when no exact ID is available.

## `country` (type: `string`):

Select one of 175 Apple storefronts. us is only the default. Archive and Mac requests use the official Apple storefront ID for the selected country; actual reviews depend on app/source availability. Custom two-letter codes are accepted for RSS. A nonempty countries list overrides this field.

## `countries` (type: `array`):

Select multiple storefronts in one run. Overrides country. All 175 listed storefronts have Apple source mappings; an app may have no reviews in a selected market. Custom codes remain accepted for RSS.

## `start_page` (type: `integer`):

Page index/count. RSS ceiling 10; archive ceiling 2000, 25 reviews per page.

## `since` (type: `string`):

Optional ISO date or timestamp. Useful for scheduled incremental monitoring.

## `deduplicateReviews` (type: `boolean`):

Deduplicate by app ID, country and Apple review ID.

## `requestDelayMillis` (type: `integer`):

Spacing between pages inside one app/country task. Defaults to 500 ms to reduce bursts on long archive scans; set 0 explicitly to disable.

## `sourceMode` (type: `string`):

RSS uses 50-row pages; iOS archive uses 25-row pages; Mac HTML uses native 10-row pages. Product IDs support automatic platform detection.

## `platform` (type: `string`):

Automatically identify each product, or explicitly select iOS / Mac. Explicit selection takes precedence over detection.

## `includeSourceMetadata` (type: `boolean`):

For archive mode, make one extra metadata lookup per app/storefront for written-review and rating totals. Counts are unfiltered; derived page count is not an accessibility guarantee.

## `includeReviewVersions` (type: `boolean`):

For archive pages, join public XML version metadata by review ID and matching text. Adds one public request per page; failures retain the review and an explicit warning.

## `include_macos` (type: `boolean`):

Detect app platform and skip Mac apps when false. Explicit platform remains authoritative.

## `parse_helpfulness` (type: `boolean`):

Include helpful\_count and total\_helpful\_count when present in the public source.

## `output_file` (type: `string`):

Local testing only: save a delivered-result JSON copy under storage/local\_exports. Use a simple .json filename. Existing files are never overwritten. Ignored completely on Apify cloud; auto-generated locally if blank.

## `sort` (type: `string`):

Source-native Apple review sort. mostrecent and mosthelpful are verified public-feed modes.

## `ratings` (type: `array`):

Optional star ratings to keep after source retrieval, for example \["1","2"] for negative reviews.

## `sort_order` (type: `string`):

1 helpful, 2 favorable, 3 critical, 4 recent.

## `normalize_dates` (type: `boolean`):

Include review\_date\_iso in johnvc-compatible output.

## `maxItems` (type: `integer`):

Optional global cap across all app/country combinations. Leave blank to derive the total budget from the per-app/storefront quota and task count for compatibility inputs (product\_ids, app\_name or max\_reviews); native inputs default to 1000 at runtime. An explicitly supplied value takes precedence over the automatic budget.

## `maxReviewsPerAppCountry` (type: `integer`):

Per app/country cap. RSS source ceiling is 500; archive ceiling is 50000.

## `maxPages` (type: `integer`):

Maximum native pages per app and country. Omit to derive the Mac/automatic budget from the requested review count; explicit limits take precedence.

## `maxRequestRetries` (type: `integer`):

Retries for transient Apple HTTP failures.

## `max_reviews` (type: `integer`):

Alias per app/country cap; zero uses selected source ceiling. maxItems remains the global cap.

## `customMapFunction` (type: `string`):

JavaScript function applied after output formatting to each review. Must return one JSON object. Isolated runtime with no network, file system or Python access; 50ms CPU and 16MB per row, 10s total. Not a filter.

## `outputSchema` (type: `string`):

Explicit migration format. Missing source values stay null; extended preserves diagnostics.

## `maxConcurrency` (type: `integer`):

Maximum app/country combinations fetched concurrently.

## `wolvesInput` (type: `object`):

Paste the complete competitor input JSON here to preserve its field types and defaults. Put all options inside this object. This is optional; normal native inputs remain available.

## `johnvcInput` (type: `object`):

Paste the complete competitor input JSON here to preserve its field types and defaults. Put all options inside this object. This is optional; normal native inputs remain available.

## Actor input object example

```json
{
  "appIds": [
    "389801252"
  ],
  "country": "us",
  "start_page": 1,
  "deduplicateReviews": true,
  "requestDelayMillis": 500,
  "sourceMode": "auto",
  "platform": "auto",
  "includeSourceMetadata": true,
  "includeReviewVersions": true,
  "include_macos": true,
  "parse_helpfulness": true,
  "sort": "mostrecent",
  "normalize_dates": true,
  "maxRequestRetries": 2,
  "outputSchema": "extended",
  "maxConcurrency": 8
}
```

# Actor output Schema

## `results` (type: `string`):

Saved App Store review rows.

## `summary` (type: `string`):

Run-level request, retry, app/country and filtering telemetry.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "appIds": [
        "389801252"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("peerless_columbine/apple-app-store-reviews-scraper-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "appIds": ["389801252"] }

# Run the Actor and wait for it to finish
run = client.actor("peerless_columbine/apple-app-store-reviews-scraper-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "appIds": [
    "389801252"
  ]
}' |
apify call peerless_columbine/apple-app-store-reviews-scraper-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,peerless_columbine/apple-app-store-reviews-scraper-api"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/5eWGsOTxIbgRUYZS5/builds/6dTDRBSXQimkEea2i/openapi.json
