# Apple App Store Scraper — Reviews, Apps & Charts | $0.50/1k (`glasswing/app-store-scraper`) Actor

Scrape the Apple App Store without an API key: apps by URL, app ID or bundle ID, keyword search with rank, a developer's apps, top free, paid and grossing charts in 176 countries, plus customer reviews (stars, title, text, version, date; no reviewer names). JSON, CSV, Excel.

- **URL**: https://apify.com/glasswing/app-store-scraper.md
- **Developed by:** [Raffy](https://apify.com/glasswing) (community)
- **Categories:** Developer tools, Automation, SEO tools
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.40 / 1,000 results

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/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

### What does App Store Scraper do?

App Store Scraper turns **Apple App Store apps, keywords, developers and top charts into clean app data**: name, developer, price and currency, star rating and rating count, age rating, categories, version, release and last-update dates, download size, minimum iOS version, languages, full description, release notes, screenshots and icon. Paste an App Store link, an app ID or a bundle ID, type a keyword, name a developer or pick a chart, and a few seconds later you have one row per app as JSON, CSV or Excel.

It works as an **App Store API and iTunes API alternative** with no API key, no Apple account and no browser. The Actor reads Apple's own public iTunes Search and Lookup API and Apple's public top-chart feeds, so it is fast, cheap and does not break when the App Store website changes.

Four ways in, freely combined in one run, in any of 176 App Store countries, plus optional **customer reviews** for every app found:

- **Look up apps** by App Store URL, numeric app ID or bundle ID (up to 100 apps per request).
- **Search the App Store** by keyword and get each app's `searchRank`, the position Apple shows it at: an ASO keyword-ranking check.
- **List every app of a developer** by developer ID, developer link or developer name.
- **Read the top charts**: top free, top paid and top grossing, for iPhone, iPad or Mac, overall or for one category such as Games, with `chartPosition` and the full app data.
- **Add App Store reviews** (optional): up to 500 written customer reviews per app and country, most recent or most helpful first, with stars, title, text, app version, date and helpful votes. Reviewer names and profiles are never collected.

Typical use cases:

- **App store optimization (ASO).** Track where your app and your competitors rank for your keywords, country by country, on a schedule.
- **Market and competitor research.** Pull the top grossing chart of 10 countries, compare prices, ratings and update frequency, and spot fast climbers.
- **Price monitoring.** See what an app costs in every storefront and currency.
- **Lead and partner research.** List all apps of a publisher, with category, rating count and the developer's website.
- **Review and sentiment analysis.** Pull the latest 500 reviews of your app and your competitors in each country, filter by stars or app version, and feed the text to your sentiment model or an LLM.
- **Data for AI agents and apps.** Give an agent a tool that answers "what is this app, how is it rated, when was it last updated" from Apple's own data.

It never collects reviewer names, reviewer profiles or any other data identifying individual people: review rows carry only the review itself.

### Why use App Store Scraper?

- **Cheap.** $0.50 per 1,000 apps and $0.30 per 1,000 reviews, Apify platform usage included, with no per-search or per-lookup surcharges.
- **Fast.** No browser: one request returns up to 100 apps. The default run finishes in about 4 seconds on Apify; a run with 5 keywords, 3 charts and 2 developers in 4 countries saved 3,269 apps in 49 seconds.
- **Complete rows.** Charts are not just names and positions: every chart row carries the same full app data as a lookup (rating, rating count, version, size, languages, screenshots).
- **Honest results.** Every row carries `status` (`ok`, `not_found`, `error`). An unknown app ID, a bundle ID that does not exist in a country or a keyword with no match is a `not_found` row that you are never charged for, and the run still ends successfully.
- **Built for agents.** Call it with no input and it returns data; plain strings everywhere; developer names, country names and chart names such as "top free" are understood.

### What data can App Store Scraper extract?

| Field | Type | Description |
|---|---|---|
| `appId` | integer | Apple's numeric app ID (the number in the App Store link) |
| `bundleId` | string | Bundle ID, e.g. `com.spotify.client` |
| `name` | string | App name as shown in the App Store |
| `developer` | string | Developer (company) name |
| `developerId` | integer | Apple's developer ID |
| `developerUrl` | string | The developer's App Store page |
| `developerWebsite` | string | The developer's own website, when listed |
| `price` | number | Price in the country's currency (0 = free) |
| `currency` | string | ISO 4217 currency code, e.g. `USD`, `GBP`, `EUR` |
| `formattedPrice` | string | Price as Apple displays it, e.g. `Free`, `$6.99` |
| `rating` | number | Average star rating 0-5 in this country (omitted when there are no ratings) |
| `ratingCount` | integer | Number of ratings in this country |
| `ratingCurrentVersion` | number | Average rating of the current version |
| `ratingCountCurrentVersion` | integer | Number of ratings of the current version |
| `contentRating` | string | Age rating, e.g. `4+`, `12+`, `17+` |
| `advisories` | array | Content advisories behind the age rating |
| `primaryGenre` | string | Main category, e.g. `Games`, `Finance` |
| `primaryGenreId` | integer | ID of the main category (6014 = Games) |
| `genres` | array | All categories the app is listed in |
| `genreIds` | array | IDs of those categories |
| `version` | string | Current version number |
| `releaseDate` | string | First release date (ISO 8601) |
| `currentVersionReleaseDate` | string | Date of the latest update (ISO 8601) |
| `fileSizeBytes` | integer | Download size in bytes |
| `minimumOsVersion` | string | Minimum iOS / iPadOS / macOS version |
| `languages` | array | Supported languages, two-letter codes |
| `description` | string | Full App Store description |
| `releaseNotes` | string | What's new in the current version |
| `screenshotUrls` | array | iPhone screenshot links (Mac screenshots for Mac apps) |
| `ipadScreenshotUrls` | array | iPad screenshot links |
| `iconUrl` | string | App icon, 512 x 512 |
| `appStoreUrl` | string | The app's App Store page in this country |
| `platform` | string | `ios` or `mac` |
| `features` | array | Apple's feature flags, e.g. `iosUniversal` |
| `gameCenterEnabled` | boolean | Whether the app uses Game Center |
| `source` | string | How the row was found: `lookup`, `search`, `developer` or `chart` |
| `country` | string | App Store country of the data (two-letter code) |
| `searchTerm` | string | Keyword (or developer name) that found the app |
| `searchRank` | integer | Position in Apple's search results for that keyword (1 = first) |
| `chart` | string | `topFree`, `topPaid` or `topGrossing` |
| `chartPosition` | integer | Position in that chart (1 = number one) |
| `chartGenreId` | integer | Chart category, when the chart was limited to one |
| `device` | string | Store of the search or chart: `iphone`, `ipad` or `mac` |
| `url` | string | Same as `appStoreUrl` on `ok` rows; what was asked for on other rows |
| `status` | string | `ok`, `not_found` or `error` (see below) |
| `error` | string | Reason when `status` is not `ok` |
| `scrapedAt` | string | ISO 8601 time of extraction |

Ratings, rating counts, prices, charts and search rankings are per country: the same app has different numbers in `us` and `de`.

#### Review rows (when Reviews per app is above 0)

Each review is its own row with `source: review`. It names its app (`appId`, `name`, `appStoreUrl`, `country`) and adds:

| Field | Type | Description |
|---|---|---|
| `reviewId` | string | Apple's id of the review |
| `rating` | integer | The review's stars, 1-5 |
| `title` | string | Review headline |
| `text` | string | Review text |
| `version` | string | App version the review was written for |
| `reviewDate` | string | When the review was written or last edited (ISO 8601, UTC) |
| `helpfulVotes` | integer | People who marked the review helpful |
| `totalVotes` | integer | People who voted on the review |
| `reviewSort` | string | `mostRecent` or `mostHelpful` |
| `reviewPosition` | integer | Position in that order for this app and country (1 = first) |

The reviewer's name and profile link are never read or stored. E-mail addresses and phone numbers that reviewers write into a review title or text are replaced with `[email]` and `[phone]`; role mailboxes such as support@ stay.

#### Result status (tri-state output)

| `status` | Meaning | Billed? |
|---|---|---|
| `ok` | The app was found; the row holds its data. | Yes |
| `not_found` | Apple answered, but there is no such app, bundle ID or developer in that country, or a keyword or chart has no apps. `error` says which. | No |
| `error` | Apple's API could not be read after retries, or an input entry was not an app ID, bundle ID or App Store link. `error` says why. | No |

### How to use App Store Scraper

1. Open the Actor and click **Try for free**.
2. Fill in any of the four inputs: **Apps** (links, IDs or bundle IDs), **Search keywords**, **Developers**, **Top charts**.
3. Pick the **Countries** (default `us`) and, for keywords and charts, the **Device** (iPhone, iPad or Mac).
4. Set **Maximum results** (default 20) and, for keywords, developers and charts, **Results per search, developer or chart** (default 50).
5. Click **Start**. Rows appear in the dataset as they arrive; export them as JSON, CSV, Excel, XML or HTML, or read them through the API.

To run it on a schedule (daily ranking or chart tracking), add a **Schedule** in Apify Console. To call it from code, use the **API** tab (Node.js, Python, curl) or the Apify MCP server.

#### Which input finds what

| You give | You get |
|---|---|
| `https://apps.apple.com/us/app/instagram/id389801252`, `389801252`, `id389801252` | That app |
| `com.spotify.client` | The app with that bundle ID |
| `https://apps.apple.com/us/developer/meta-platforms-inc/id284882218` or `284882218` (in Developers) | Every app of that developer (Apple lists up to 200) |
| `Rovio Entertainment` (in Developers) | Apps whose developer name contains that name |
| `habit tracker` (in Search keywords) | Apple's search results with `searchRank` |
| Top free / Top paid / Top grossing | Up to 100 apps per chart with `chartPosition` |

### How much does it cost to scrape the App Store?

This Actor uses **pay-per-event** pricing. Apify platform usage is included in these prices.

| Event | Price |
|---|---|
| Actor start | $0.005 per run |
| Result (`status: ok` app row) | $0.0005 per app |
| Review (`status: ok` review row, only when reviews are on) | $0.0003 per review |

Examples: the default run (5 apps) costs $0.0075. The US top 100 free chart costs $0.055. 1,000 apps cost $0.505, 10,000 apps $5.005. The latest 500 reviews of one app cost $0.0005 + $0.15. A review row is charged `Review` instead of `Result`, never both. Rows with `status` `not_found` or `error` are never billed. You can cap spending with **Maximum results** and the run's **Max total charge** option; the Actor stops gracefully when your run's maximum charge is reached.

### Input

See the **Input** tab for the full schema. The main options:

| Field | Type | Default | Description |
|---|---|---|---|
| `startUrls` | array of strings | 5 well-known apps | App Store links, app IDs, bundle IDs or developer links |
| `searchTerms` | array of strings | - | Keywords to search |
| `developerIds` | array of strings | - | Developer IDs, links or names |
| `charts` | array | - | `topFree`, `topPaid`, `topGrossing` |
| `chartGenre` | string | all categories | Category ID for the charts, e.g. `6014` (Games) |
| `countries` | array of strings | `["us"]` | Two-letter App Store country codes (or country names) |
| `device` | string | `iphone` | `iphone`, `ipad` or `mac` for keywords and charts |
| `resultsPerSource` | integer | `50` | Apps kept per keyword, developer and chart (max 200 / 100 for charts) |
| `maxReviewsPerApp` | integer | `0` | Customer reviews per app and country (0 = off, max 500) |
| `reviewsSort` | string | `mostRecent` | `mostRecent` or `mostHelpful` |
| `reviewsOnly` | boolean | `false` | Save review rows only, not the app rows |
| `maxItems` | integer | `20` | Stop after this many rows in total (review rows count too) |

When you use keywords, developers or charts and leave **Apps** at its built-in example, the example apps are skipped automatically.

Example input: the top 100 grossing iPhone games in the US and the UK, plus two keywords.

```json
{
    "charts": ["topGrossing"],
    "chartGenre": "6014",
    "searchTerms": ["budget planner", "habit tracker"],
    "countries": ["us", "gb"],
    "resultsPerSource": 100,
    "maxItems": 1000
}
```

Example input: the 200 most recent US and UK reviews of two apps, review rows only.

```json
{
    "startUrls": ["https://apps.apple.com/us/app/instagram/id389801252", "com.spotify.client"],
    "countries": ["us", "gb"],
    "maxReviewsPerApp": 200,
    "reviewsOnly": true,
    "maxItems": 1000
}
```

The default input (what an AI agent gets when it calls the Actor with no arguments):

```json
{
    "startUrls": [
        "https://apps.apple.com/us/app/instagram/id389801252",
        "310633997",
        "com.spotify.client",
        "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128",
        "https://apps.apple.com/us/app/minecraft-play-with-friends/id479516143"
    ],
    "countries": ["us"],
    "maxItems": 20
}
```

### Output

You can download the dataset as JSON, CSV, Excel, XML or HTML. A real row from a run on Apify (long texts and lists shortened here):

```json
{
    "url": "https://apps.apple.com/us/app/minecraft-play-with-friends/id479516143",
    "status": "ok",
    "scrapedAt": "2026-09-27T13:32:52.282Z",
    "appId": 479516143,
    "bundleId": "com.mojang.minecraftpe",
    "name": "Minecraft: Play with Friends!",
    "developer": "Mojang",
    "developerId": 479516146,
    "developerUrl": "https://apps.apple.com/us/developer/mojang/id479516146",
    "price": 6.99,
    "currency": "USD",
    "formattedPrice": "$6.99",
    "rating": 4.50753,
    "ratingCount": 840101,
    "ratingCurrentVersion": 4.50753,
    "ratingCountCurrentVersion": 840101,
    "contentRating": "9+",
    "advisories": ["Infrequent/Mild Contests", "Infrequent/Mild Cartoon or Fantasy Violence"],
    "primaryGenre": "Games",
    "primaryGenreId": 6014,
    "genres": ["Games", "Simulation", "Adventure"],
    "genreIds": [6014, 7015, 7002],
    "version": "26.51",
    "releaseDate": "2011-11-17T08:00:00Z",
    "currentVersionReleaseDate": "2026-09-16T15:40:58Z",
    "fileSizeBytes": 1327799296,
    "minimumOsVersion": "13.0",
    "languages": ["DA", "NL", "EN", "FI", "FR", "DE", "..."],
    "description": "Dive into an open world of building, crafting and survival. Gather resources, survive the night, and build whatever you can imagine one block at a time. Explore...",
    "releaseNotes": "Various bug fixes!",
    "screenshotUrls": ["https://is1-ssl.mzstatic.com/image/thumb/Purple211/v4/07/47/6f/07476fcd-1ecf-18ca-e7f7-364d6c6cd5e1/pr_source.png/406x228bb.png", "..."],
    "ipadScreenshotUrls": ["https://is1-ssl.mzstatic.com/image/thumb/Purple211/v4/be/e0/bd/bee0bd58-7fd7-0203-2507-0b95bc2a3f51/pr_source.png/552x414bb.png", "..."],
    "iconUrl": "https://is1-ssl.mzstatic.com/image/thumb/Purple221/v4/6c/04/5b/6c045bf2-3400-f6cb-37e7-30b3f945b024/AppIcon-0-0-1x_U007emarketing-0-10-0-85-220.png/512x512bb.jpg",
    "appStoreUrl": "https://apps.apple.com/us/app/minecraft-play-with-friends/id479516143",
    "platform": "ios",
    "features": ["iosUniversal"],
    "gameCenterEnabled": false,
    "source": "lookup",
    "country": "us"
}
```

A chart row carries the same fields plus `"source": "chart"`, `"chart": "topGrossing"`, `"chartPosition": 1` and `"device": "iphone"`; a search row adds `"searchTerm"` and `"searchRank"`. An app ID that does not exist gives a free row like this, and the run still succeeds:

```json
{
    "url": "https://apps.apple.com/us/app/id1",
    "status": "not_found",
    "error": "No app with id 1 in the US App Store (it may not exist or not be sold in this country).",
    "scrapedAt": "2026-09-27T13:38:44.400Z"
}
```

A real review row from a local run (reviews on); the reviewer's name and profile are never part of it:

```json
{
    "url": "https://apps.apple.com/us/app/id324684580?see-all=reviews",
    "status": "ok",
    "scrapedAt": "2026-10-19T12:02:06.830Z",
    "appId": 324684580,
    "name": "Spotify: Music and Podcasts",
    "appStoreUrl": "https://apps.apple.com/us/app/id324684580",
    "country": "us",
    "source": "review",
    "reviewId": "14680852557",
    "rating": 5,
    "title": "The best",
    "text": "It gives the latest music",
    "version": "9.1.90",
    "reviewDate": "2026-10-18T09:14:08.000Z",
    "helpfulVotes": 0,
    "totalVotes": 0,
    "reviewSort": "mostRecent",
    "reviewPosition": 1
}
```

### Tips

- Put all your apps, keywords and countries in **one run**: you pay the start fee once, and app IDs are looked up 100 at a time.
- For keyword rank tracking, schedule a daily run with your keywords and read `searchRank` for your app ID.
- Raise **Maximum results** when you ask for full charts or several keywords: it caps the whole run (default 20).
- Country names work (`Germany`, `Japan`), and so do the codes (`de`, `jp`).
- With reviews on, set **Maximum results** to cover them: apps x countries x (1 + Reviews per app).

### Limitations

- **Reviews: the latest 500 per app and country.** That is all Apple's public reviews feed holds (10 pages of 50). Reviews are per country storefront; ask several countries for more. Star-only ratings without text are not in the feed (they are counted in `ratingCount`).
- Apple caps its answers: 200 apps per keyword or developer, 100 per chart. Charts exist for top free, top paid and top grossing; for Mac apps Apple publishes only the top free chart.
- Apple's keyword search is Apple's own ranking as its public API returns it; it can differ slightly from what one person sees on their device.
- A developer name is matched against the developers Apple's search returns; for an exact list use the developer ID from the developer's App Store link.
- Values come from Apple at the time of the run. If Apple changes its API, rows come back as `error` and the Actor is updated quickly; report it in the **Issues** tab.

### FAQ

#### Do I need an Apple account, developer account or API key?

No. The Actor uses Apple's public iTunes Search and Lookup API and Apple's public chart feeds, which need no key and no login.

#### Can it scrape App Store reviews?

Yes. Set **Reviews per app** (up to 500 per app and country) and every app the run finds also gets its written customer reviews from Apple's public reviews feed: stars, title, text, app version, date and helpful votes, at $0.30 per 1,000 reviews. Reviewer names and profiles are never collected. Turn on **Reviews only** if you do not need the app rows.

#### How do I track my app's keyword ranking (ASO)?

Add your keywords under **Search keywords**, set your countries, and schedule the run daily. Filter the rows by your `appId` and chart `searchRank` over time. `searchRank` is the position in Apple's search results for that keyword (1 = first).

#### How do I get the top grossing games in Japan?

Set **Top charts** to Top grossing, **Chart category** to Games, **Countries** to `jp`, **Results per search, developer or chart** to 100 and **Maximum results** to 100.

#### Why is an app `not_found`?

The ID or bundle ID does not exist, or the app is not sold in that country's App Store (many apps are region-locked). The row says which country was checked. `not_found` rows are free.

#### Can I use this Actor from an AI agent or MCP client?

Yes. Called with no arguments it returns five well-known apps; every input is a plain string or list, and every row explains itself with `status` and `error`.

#### How fast is it?

About 4 seconds for the default run. Most runs need one request per 100 looked-up apps, one per keyword or developer, and two per chart.

### Related Actors

- [Google Play Scraper](https://apify.com/glasswing/google-play-scraper) - use it to compare the same app's Android listing, ranking and reviews.
- [Steam Store Scraper](https://apify.com/glasswing/steam-store-scraper) - use it when the app in question is also, or instead, a PC game on Steam.
- [Shopify Scraper](https://apify.com/glasswing/shopify-products-scraper) - use it if the app has a companion online store you also need to track.

### Legal and data-protection notice

This Actor reads only data that Apple publishes publicly through its App Store search, lookup and chart services: app listings, the names of the companies that publish them and, when you ask for them, the text, stars and votes of public customer reviews. It does not extract reviewer names, reviewer profiles, e-mail addresses, phone numbers or other data about individual people, and it does not log in or get around any access control. Some developers publish apps under their own name, so a `developer` value can be a person's name; it is the public publisher name shown in the App Store. Review text is written by members of the public and can occasionally mention personal details; handle it accordingly. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you are unsure whether your reason is legitimate, consult your lawyers. You are responsible for complying with Apple's terms and applicable law when using the extracted data.

This Actor is an independent tool and is not affiliated with, endorsed by or sponsored by Apple Inc. App Store and iTunes are trademarks of Apple Inc. All trademarks belong to their respective owners.

# Changelog

This Actor's version history is a separate document: https://apify.com/glasswing/app-store-scraper/changelog.md

# Actor input Schema

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

One per line. Accepted: App Store links (https://apps.apple.com/us/app/instagram/id389801252), numeric app IDs (389801252 or id389801252), bundle IDs (com.spotify.client) and developer links (https://apps.apple.com/us/developer/meta-platforms-inc/id284882218, which list all of that developer's apps). A link that names a country (/gb/) is fetched in that country, unless you list countries under Countries: then every app is fetched in each listed country. An ID that does not exist gives one free `not_found` row. Leave the built-in example here when you use search, developers or charts: it is skipped automatically.

## `searchTerms` (type: `array`):

Keywords to search the App Store for, one per line: `budget planner`, `photo editor`, `meditation`. Each keyword returns up to `Results per search, developer or chart` apps in Apple's own search order; `searchRank` is the position (1 = first result), which makes this an App Store keyword-ranking (ASO) check. A keyword with no match gives one free `not_found` row.

## `developerIds` (type: `array`):

Developers whose apps you want, one per line: a developer ID (284882218), a developer link (https://apps.apple.com/us/developer/meta-platforms-inc/id284882218) or a developer name (Rovio Entertainment). A name is matched against the developer names Apple's search returns; an ID is exact. Apple lists at most 200 apps per developer and country.

## `charts` (type: `array`):

Apple's top charts to read, per country and device: top free, top paid and top grossing. Each chart returns up to 100 apps (Apple's cap) with `chartPosition` 1, 2, 3... and the full app data. Mac: Apple publishes only the top free chart.

## `chartGenre` (type: `string`):

Optional: limit the charts to one App Store category, for example Games. Leave empty for the overall charts.

## `maxReviewsPerApp` (type: `integer`):

How many customer reviews to fetch for each app, per country. 0 (default) = no reviews, only app data. Apple's public feed holds the latest 500 reviews per app and country (50 per page), so 500 is the maximum. Review rows count toward Maximum results: raise it too, for example 3 apps x 200 reviews = Maximum results 603 or more. An app with no written reviews gives one free `not_found` row.

## `reviewsSort` (type: `string`):

Most recent first (default), or most helpful first (Apple's ranking by helpful votes). Each review row keeps its position in this order in `reviewPosition`.

## `reviewsOnly` (type: `boolean`):

Save only review rows, not the app rows they belong to (each review row still names its app: `appId`, `name`, `appStoreUrl`, `country`). If Reviews per app is 0, 100 reviews per app are fetched.

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

App Store countries as two-letter codes, one per line: `us`, `gb`, `de`, `jp`, `br` (176 storefronts; country names such as Germany also work). Prices, currency, ratings, rankings and charts differ by country. Every app ID, keyword, developer and chart is fetched once per country.

## `device` (type: `string`):

Which store the search keywords and top charts use: iPhone apps, iPad apps or Mac apps. App IDs and developers are looked up the same way on every device.

## `resultsPerSource` (type: `integer`):

How many apps to keep from each keyword, developer and chart, best-ranked first. Leave empty to use Apple's own maximum automatically: 200 per keyword or developer, 100 per chart. Only set this to take fewer than Apple's maximum from each source on purpose. The total is still limited by Maximum results.

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

Stop after this many rows have been saved in total. Each row with status `ok` is one billable result; `not_found` and `error` rows are never charged. Raise it for full charts or several keywords.

## `maxResults` (type: `integer`):

Same as Maximum results; accepted for API callers that use this name.

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

Optional. Apple's public App Store API answers Apify's datacenter IPs directly, so no proxy is needed. If a very large run meets rate-limit errors, enable Apify Proxy (datacenter). Residential proxies are not needed.

## Actor input object example

```json
{
  "startUrls": [
    "https://apps.apple.com/us/app/instagram/id389801252",
    "310633997",
    "com.spotify.client",
    "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128",
    "https://apps.apple.com/us/app/minecraft-play-with-friends/id479516143"
  ],
  "maxReviewsPerApp": 0,
  "reviewsSort": "mostRecent",
  "reviewsOnly": false,
  "countries": [
    "us"
  ],
  "device": "iphone",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (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 = {
    "startUrls": [
        "https://apps.apple.com/us/app/instagram/id389801252",
        "310633997",
        "com.spotify.client",
        "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128",
        "https://apps.apple.com/us/app/minecraft-play-with-friends/id479516143"
    ],
    "countries": [
        "us"
    ],
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("glasswing/app-store-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 = {
    "startUrls": [
        "https://apps.apple.com/us/app/instagram/id389801252",
        "310633997",
        "com.spotify.client",
        "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128",
        "https://apps.apple.com/us/app/minecraft-play-with-friends/id479516143",
    ],
    "countries": ["us"],
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("glasswing/app-store-scraper").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 '{
  "startUrls": [
    "https://apps.apple.com/us/app/instagram/id389801252",
    "310633997",
    "com.spotify.client",
    "https://apps.apple.com/us/app/duolingo-language-lessons/id570060128",
    "https://apps.apple.com/us/app/minecraft-play-with-friends/id479516143"
  ],
  "countries": [
    "us"
  ],
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call glasswing/app-store-scraper --silent --output-dataset

```

## MCP server setup

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

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/EjbWJgIuBfAJQbSQt/builds/ecGFhBwtpHaVpb8LF/openapi.json
