# The Better App Store Reviews Scraper (`betterscrapers/the-better-app-store-reviews-scraper`) Actor

Scrape Apple App Store customer reviews — ratings, titles, text, app version, dates — fast and affordably via the public RSS feed. HTTP-only, no browser, no residential proxy, low compute usage.

- **URL**: https://apify.com/betterscrapers/the-better-app-store-reviews-scraper.md
- **Developed by:** [Better Scrapers](https://apify.com/betterscrapers) (community)
- **Categories:** Automation, Developer tools, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.08 / 1,000 reviews

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

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## The Better App Store Reviews Scraper — Apple App Store customer reviews & ratings export

Scrape **Apple App Store customer reviews** quickly and affordably. This App Store reviews scraper pulls **user reviews, star ratings, review titles, review text, app version and review dates** for any iOS / iPadOS / macOS app, in any App Store country storefront, and exports them to JSON, CSV, or Excel. It reads Apple's **public reviews RSS feed** directly — so there is **no headless browser, no residential proxy, and very low compute usage**, which makes it one of the more affordable ways to monitor App Store ratings and reviews at scale.

Great for **app review monitoring, review sentiment analysis, competitor research, ASO (App Store Optimization), customer feedback tracking, and support triage** — without paying for expensive browser rendering.

### What it extracts

For every customer review the scraper returns:

- **reviewId** — Apple's unique review identifier
- **userName** — the reviewer's display name
- **title** — the review headline
- **text** — the full review body
- **rating** — the star rating as an integer from 1 to 5
- **appVersion** — the app version the review was written against
- **updatedAt** — the review date, normalised to UTC ISO-8601
- **reviewUrl** — the reviewer/review URL when Apple provides one
- **appId**, **country**, **sort**, **page** — the query context for each row

### Features

- **App Store reviews export** to JSON, CSV, Excel, HTML, or via API/webhook (Apify dataset).
- **Any storefront** — set a two-letter country code (`us`, `gb`, `de`, `fr`, `jp`, `br`, …) to collect localized reviews.
- **Most recent or most helpful** sort order.
- **Star-rating extraction** as clean integers, ready for averages, distributions, and dashboards.
- **Automatic pagination** across Apple's review pages (up to ~10).
- **Cross-page deduplication** by review id.
- **HTTP-only and lightweight** — fast runs and low compute-unit cost.
- **Resilient parsing** that handles single-review feeds and empty feeds gracefully.

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `appId` | string (required) | — | Numeric Apple App Store app id (digits only). Find it in the app URL, e.g. `.../id389801252` → `389801252`. |
| `country` | string | `us` | Two-letter App Store storefront code (ISO 3166-1 alpha-2), e.g. `us`, `gb`, `de`, `jp`. |
| `maxPages` | integer | `5` | Number of review pages to fetch (Apple caps at ~10, ~50 reviews per page). Fewer pages = cheaper run. |
| `sort` | string (`mostrecent` \| `mosthelpful`) | `mostrecent` | Order reviews by most recent or most helpful. |
| `proxyConfiguration` | object | `{ "useApifyProxy": true }` | Optional proxy. Datacenter proxies are plenty; residential proxies are **not** required. You can also run with no proxy. |

#### Example input

```json
{
  "appId": "389801252",
  "country": "us",
  "maxPages": 3,
  "sort": "mostrecent",
  "proxyConfiguration": { "useApifyProxy": true }
}
````

### Output

Each dataset item is one customer review:

```json
{
  "reviewId": "11111111111",
  "userName": "Jane D.",
  "title": "Absolutely love it",
  "text": "Fast, reliable, and easy to use. Best update yet!",
  "rating": 5,
  "appVersion": "12.4.1",
  "updatedAt": "2026-07-20T16:15:32.000Z",
  "reviewUrl": "https://itunes.apple.com/us/reviews/id123456789",
  "appId": "389801252",
  "country": "us",
  "sort": "mostrecent",
  "page": 1
}
```

### Example use cases

- **App review monitoring** — track new 1-star and 5-star App Store reviews for your own app daily.
- **Review sentiment analysis** — feed review text and ratings into an NLP / LLM pipeline to quantify customer sentiment over time.
- **Competitor & market research** — collect and compare App Store ratings and reviews across competing iOS apps.
- **ASO (App Store Optimization)** — mine reviews for recurring keywords, feature requests, and pain points.
- **Customer support triage** — surface crash reports and bug complaints tied to a specific `appVersion`.
- **Release impact analysis** — compare rating distributions before and after an app update.

### How it works

The actor requests Apple's public customer-reviews RSS-JSON endpoint:

```
https://itunes.apple.com/{country}/rss/customerreviews/page={p}/id={appId}/sortby={mostrecent|mosthelpful}/json
```

for each page from `1` to `maxPages`, using a plain HTTP crawler (`HttpCrawler`). The first entry in every feed is app metadata, so it is skipped; the remaining entries are parsed into normalised review objects by a small, pure parser (`src/parse.mjs`) and pushed to the dataset. Because the parser is dependency-free, it is fully unit-tested with `npm test` (no network required).

### Why it's efficient and affordable

- **HTTP-only, no browser.** It never launches Chromium/Playwright, so it avoids the heavy CPU and memory that browser-based scrapers consume — meaning **fewer compute units per run**.
- **No residential proxy needed.** The Apple RSS feed is public; datacenter proxies (or none) are sufficient, avoiding the biggest cost driver in most scrapers.
- **Small, bounded workload.** Apple limits reviews to ~10 pages, so runs are fast, predictable, and cheap.
- **Lean data transfer.** It downloads compact JSON, not rendered HTML, images, fonts, or stylesheets.

### FAQ

**Q: Where do I find an app's `appId`?**
Open the app's App Store page and copy the number after `id` in the URL, e.g. `https://apps.apple.com/us/app/example/id389801252` → `389801252`.

**Q: How many reviews can I get per app?**
Apple's public reviews feed exposes roughly the 10 most recent/helpful pages (about 500 reviews). This is an Apple limitation, not an actor limitation. Use both `mostrecent` and `mosthelpful`, and different `country` storefronts, to widen coverage.

**Q: Can I scrape reviews from other countries / languages?**
Yes — set `country` to any two-letter storefront code (`gb`, `de`, `fr`, `jp`, `br`, …) to collect localized App Store reviews.

**Q: Does this scrape Google Play reviews too?**
No — this actor is focused on **Apple App Store** reviews via Apple's RSS feed. That focus is what keeps it fast and cheap.

**Q: Do I need a proxy or an API key?**
No API key is required. A proxy is optional; datacenter proxies are more than enough and residential proxies are unnecessary.

### Legal & ethics

This actor collects **publicly available** App Store review data from Apple's official public RSS feed. Use it responsibly: respect Apple's Terms of Service and `robots.txt`, avoid excessive request rates, and comply with applicable laws (including data-protection rules such as GDPR/CCPA) when storing or processing review data. Do not use scraped personal data — such as reviewer display names — in ways that infringe on individuals' rights. You are responsible for how you use the data you collect.

# Actor input Schema

## `appId` (type: `string`):

The numeric Apple App Store application id (digits only). Find it in the App Store URL: https://apps.apple.com/us/app/name/id389801252 -> "389801252".

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

Two-letter App Store storefront code (ISO 3166-1 alpha-2), e.g. us, gb, de, fr, jp, br. Reviews are returned in the language(s) of that storefront.

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

How many pages of reviews to fetch. Apple returns up to ~10 pages of roughly 50 reviews each; fetching fewer pages means an even cheaper run.

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

Order reviews by most recent or most helpful.

## `proxyConfiguration` (type: `object`):

Proxy settings. Datacenter proxies (the default) are more than enough for this public Apple RSS feed — residential proxies are NOT required, which keeps every run cheap. You can also run with no proxy at all.

## Actor input object example

```json
{
  "appId": "389801252",
  "country": "us",
  "maxPages": 5,
  "sort": "mostrecent",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "appId": "389801252",
    "country": "us",
    "maxPages": 5,
    "sort": "mostrecent",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("betterscrapers/the-better-app-store-reviews-scraper").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 = {
    "appId": "389801252",
    "country": "us",
    "maxPages": 5,
    "sort": "mostrecent",
    "proxyConfiguration": { "useApifyProxy": True },
}

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

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

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

```

## CLI example

```bash
echo '{
  "appId": "389801252",
  "country": "us",
  "maxPages": 5,
  "sort": "mostrecent",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call betterscrapers/the-better-app-store-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=betterscrapers/the-better-app-store-reviews-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "The Better App Store Reviews Scraper",
        "description": "Scrape Apple App Store customer reviews — ratings, titles, text, app version, dates — fast and affordably via the public RSS feed. HTTP-only, no browser, no residential proxy, low compute usage.",
        "version": "0.1",
        "x-build-id": "fSRTu8xVuBBz00KeV"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/betterscrapers~the-better-app-store-reviews-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-betterscrapers-the-better-app-store-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/betterscrapers~the-better-app-store-reviews-scraper/runs": {
            "post": {
                "operationId": "runs-sync-betterscrapers-the-better-app-store-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/betterscrapers~the-better-app-store-reviews-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-betterscrapers-the-better-app-store-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "appId"
                ],
                "properties": {
                    "appId": {
                        "title": "App Store app ID",
                        "pattern": "^[0-9]+$",
                        "type": "string",
                        "description": "The numeric Apple App Store application id (digits only). Find it in the App Store URL: https://apps.apple.com/us/app/name/id389801252 -> \"389801252\"."
                    },
                    "country": {
                        "title": "Country / storefront",
                        "type": "string",
                        "description": "Two-letter App Store storefront code (ISO 3166-1 alpha-2), e.g. us, gb, de, fr, jp, br. Reviews are returned in the language(s) of that storefront.",
                        "default": "us"
                    },
                    "maxPages": {
                        "title": "Max pages",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "How many pages of reviews to fetch. Apple returns up to ~10 pages of roughly 50 reviews each; fetching fewer pages means an even cheaper run.",
                        "default": 5
                    },
                    "sort": {
                        "title": "Sort order",
                        "enum": [
                            "mostrecent",
                            "mosthelpful"
                        ],
                        "type": "string",
                        "description": "Order reviews by most recent or most helpful.",
                        "default": "mostrecent"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Proxy settings. Datacenter proxies (the default) are more than enough for this public Apple RSS feed — residential proxies are NOT required, which keeps every run cheap. You can also run with no proxy at all.",
                        "default": {
                            "useApifyProxy": true
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
