# App Store Ratings Scraper for iOS Apps (`elidev/app-store-ratings`) Actor

Extract country-specific App Store ratings and rating counts for iOS applications. Get structured JSON and clean output tables.

- **URL**: https://apify.com/elidev/app-store-ratings.md
- **Developed by:** [EliDev](https://apify.com/elidev) (community)
- **Stats:** 1 total users, 0 monthly users, 99.5% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 app rating results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## App Store Ratings Scraper for iOS Apps

Get an iOS application's aggregate App Store rating and rating count for a specific storefront. Supply an official application URL and receive one structured snapshot, with a readable Output table and JSON exports. No EliDev API key is required.

EliDev uses Apple's documented catalog Lookup API. It does not download apps, collect review texts, access an Apple account or bypass access controls.

### Start with one application

1. Paste an official HTTPS App Store application URL.
2. Keep the default metadata language unless you need Japanese metadata.
3. Check the current Pricing tab and your maximum charge in Apify run options.
4. Start the run. Open **Output > App Ratings** or **Storage > Dataset** for raw JSON.

```json
{
  "url": "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
  "language": "en_us"
}
```

The country is the URL path segment, such as `/us/`, `/fr/` or `/jp/`; there is no separate country input. Supported codes: `at`, `au`, `be`, `br`, `ca`, `ch`, `de`, `dk`, `es`, `fi`, `fr`, `gb`, `ie`, `in`, `it`, `jp`, `kr`, `mx`, `nl`, `no`, `nz`, `pl`, `pt`, `se`, `us`. Metadata languages: `en_us` and `ja_jp`. Language does not select the rating's country or translate reviews.

One listing per run. HTTP URLs, alternate hosts, ports, userinfo, encoded paths, fragments, query parameters and unknown input fields are rejected. The URL must contain a numeric app ID. Some apps are unavailable in particular storefronts.

### Data you receive

| Field | Meaning |
| --- | --- |
| `source_id` | Numeric App Store app ID, represented as a string |
| `data.country` | Storefront country from the URL |
| `data.rating` | Finite aggregate score from 1 to 5 |
| `data.rating_count` | Nonnegative integer count of ratings, not written reviews |
| `url` | Validated application listing URL |
| `observed_at` | UTC observation time, not Apple's last update time |
| `language` | Lookup metadata language |
| `data.scope` | `storefront_all_versions`, never worldwide |
| `data.count_kind` | `ratings` |
| `source`, `kind`, `status` | `apple_appstore`, `ratings`, `completed` |

If either metric is unavailable or invalid, no result item is written. The Actor never invents a zero or mixes current-version ratings with all-version counts.

#### Observed JSON example

Collected in private run `w9iU71OhpdbcdGmtB` on 31 October 2026. These historical values are not promised for a new run.

```json
{
  "source": "apple_appstore",
  "kind": "ratings",
  "status": "completed",
  "url": "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
  "source_id": "310633997",
  "language": "en_us",
  "data": {
    "rating": 4.68295,
    "rating_count": 18873917,
    "count_kind": "ratings",
    "country": "us",
    "scope": "storefront_all_versions"
  },
  "observed_at": "2026-10-31T14:42:46.242099+00:00"
}
```

Output links to the default Dataset's `overview` view. First columns: App ID, Country, App Rating, Number of Ratings, URL, Observed At. Flattening only affects the view; raw JSON keeps nested `data`. The Key-Value Store `OUTPUT` record contains the run outcome and billing confirmation, not another paid snapshot.

### Use cases

- Follow regional rating trends with limited scheduled observations.
- Compare applications in the same storefront and on the same basis.
- Add aggregate reputation indicators to internal dashboards and reports.
- Export JSON, CSV or Excel through Apify or connect your own backend.

No individual reviews, reviewer identities, installations, revenue, rankings, artwork or screenshots are included.

### API examples

These calls require access to the Actor. Keep the Apify token in a secret server environment variable. Private access remains necessary until publication is approved.

During private validation, targets are restricted by the operator. The current recipe allows WhatsApp, app ID `310633997`. This restriction is separate from URL validation and is not selected by customer input.

Python, official client 3.x:

```python
import os
from datetime import timedelta
from decimal import Decimal
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("elidev/app-store-ratings").call(
    run_input={"url": "https://apps.apple.com/us/app/whatsapp-messenger/id310633997"},
    memory_mbytes=256, run_timeout=timedelta(seconds=120), max_total_charge_usd=Decimal("0.02"),
)
if run is None or run.status != "SUCCEEDED":
    raise RuntimeError("No validated snapshot delivered; inspect the run")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)
```

JavaScript, Node.js with `apify-client`:

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('elidev/app-store-ratings').call({
    url: 'https://apps.apple.com/us/app/whatsapp-messenger/id310633997',
}, { memory: 256, timeout: 120, maxTotalChargeUsd: 0.02 });
if (!run || run.status !== 'SUCCEEDED') throw new Error('No validated snapshot');
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

REST API, asynchronous submission:

```bash
curl --fail-with-body -X POST \
  'https://api.apify.com/v2/actors/elidev~app-store-ratings/runs?memory=256&timeout=120&maxTotalChargeUsd=0.02' \
  -H "Authorization: Bearer ${APIFY_TOKEN}" \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://apps.apple.com/us/app/whatsapp-messenger/id310633997"}'
```

Read `data.id`, poll `GET /v2/actor-runs/{runId}` at reasonable intervals, then read `GET /v2/datasets/{defaultDatasetId}/items` after `SUCCEEDED`. Stop a running extraction with `POST /v2/actor-runs/{runId}/abort`. Send Authorization on every call; never put tokens in URLs or public code.

### Pricing and budgets

The Pricing tab is authoritative. One Dataset Result is one application/storefront snapshot, not one person's rating or one written review. A start fee can apply to a failed or cancelled run. A new run or resurrection may have another start event.

Prices must match the operator's explicit approval before extraction. A mismatch stops the run. A positive effective customer ceiling is required; larger Console budgets are accepted without increasing the one-result workload. Zero, missing, invalid or insufficient effective budgets are refused. Your ceiling is never raised. The SDK handles the synthetic Dataset event automatically; the code never charges it a second time.

At most one Dataset item per successful run. A new run is a new observation and may be billed separately. Restarting with confirmed completed state reuses the outcome. An interrupted write with uncertain delivery requires review rather than blind replay. Failed, empty or incomplete extractions do not produce successful result items. A platform start fee can still apply.

### FAQ and limitations

**Is this a worldwide rating?** No. It is the selected storefront's available all-version aggregate.

**Does this include reviews?** No review bodies or reviewer profiles are collected.

**Are results fresh?** Apple may cache responses. `observed_at` is collection time, not the last source update. There is no shared cross-customer cache in the Actor.

**Why no result?** An app may be missing in that storefront, lack ratings, return invalid metrics, or face provider throttling. No fake score is returned.

**What limits apply?** One app per run, bounded networking and retry, response-size protection, 45-second application deadline, 128-256 MB memory and a positive effective run budget. Apple documents approximately 20 calls/minute, subject to change. Avoid bulk parallel extraction and uncontrolled retries.

**Budget error?** `insufficient_run_budget` means your remaining allowance cannot cover the configured result. `run_budget_required` means no positive ceiling was retained by Apify. `pricing_not_authorized` is an operator policy mismatch; contact support with the run ID.

**Can I blindly retry an interrupted run?** No. `replay_requires_review` signals uncertain delivery; support must inspect storage and events before another attempt.

### Privacy, support and permitted use

Default run storage is restricted. Retention and deletion follow your Apify account/storage settings. Delete runs and associated storage when no longer needed. Do not share signed storage links or tokens. No Apple credentials, EliDev key or reviewer personal data are required.

Support: [EliDev on Apify](https://apify.com/elidev). Use the Actor's Issues/support option with a run ID, storefront and problem description. Never send tokens or credentials.

EliDev is independent and is not affiliated with, sponsored by or endorsed by Apple. Apple and App Store are descriptive source references. The icon is original EliDev artwork. An official public API does not grant a resale licence. Use only where source terms and law permit. Store publication is subject to source-contract review and explicit pricing approval.

# Actor input Schema

## `url` (type: `string`):

HTTPS apps.apple.com listing with its storefront country and numeric app ID. The country comes from the URL, not the metadata language.

## `language` (type: `string`):

Apple API metadata language; storefront country is taken separately from the URL.

## Actor input object example

```json
{
  "url": "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
  "language": "en_us"
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `output` (type: `string`):

No description

# 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 = {
    "url": "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
    "language": "en_us"
};

// Run the Actor and wait for it to finish
const run = await client.actor("elidev/app-store-ratings").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 = {
    "url": "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
    "language": "en_us",
}

# Run the Actor and wait for it to finish
run = client.actor("elidev/app-store-ratings").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 '{
  "url": "https://apps.apple.com/us/app/whatsapp-messenger/id310633997",
  "language": "en_us"
}' |
apify call elidev/app-store-ratings --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,elidev/app-store-ratings"
        }
    }
}
```

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/oa8xRlO1QCMdRXH7H/builds/ZVWN9WO1JMnXQ5hfZ/openapi.json
