# App Store Scraper (`dami_studio/app-store-scraper`) Actor

App Store scraper API for Apple apps by keyword, ID or link. Each row has name, developer, rating and count, price, genres, version, release notes and screenshots, plus up to 5,000 reviews per app by ID, the first 500 included. $0.09 per 1,000 apps, $0.052 per 1,000 reviews past 500.

- **URL**: https://apify.com/dami_studio/app-store-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Integrations, Developer tools, Other
- **Features:** Limited permissions
- **Stats:** 6 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.09 / 1,000 apps

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

**App Store scraper for Apple App Store searches by keyword, or apps by ID or link, one row per app**:
name, developer, rating and rating count, price, genres, version and release notes, artwork,
screenshots and supported devices. Look an app up by ID and its customer reviews ride along on the
same row, the first 500 at no extra cost.

Two limits: 5,000 reviews per app, and 200 apps per search. Reviews also
need an ID or a link: a keyword search ignores that setting.

| | |
|---|---|
| **Input** | A search term, or App Store IDs, bundle IDs or app links |
| **Output** | One row per app: name, developer, rating and count, price, genres, version, release notes, artwork, screenshots, devices, and its reviews when you ask |
| **Ceiling** | 200 apps per search, 5,000 reviews per app |
| **Account needed** | None, and no API key |
| **Price** | $0.09 per 1,000 apps on the Free plan, a little less on paid plans. The free plan's $5 a month covers about 55,000 |

### 🔍 What App Store Scraper does

Two ways in, and they do different jobs.

**Search.** Give it `habit tracker` and you get the matching apps with their full metadata, up to
200 of them. This is how you find apps you do not know about yet.

**Look up.** Give it numeric track IDs (`1232780281`), bundle IDs (`net.shinyfrog.bear`) or links
copied from the store, and you get exactly those apps. Tick **Include reviews** and each one comes
back with its customer reviews attached. This is how you keep watching apps you already care about.

Fill in both and the IDs and links win, so the search term is ignored.

The storefront is one setting for the whole run. It decides which apps exist for you, what they
cost and which reviews come back, so comparing countries means one run each.

### 📋 What data you get from each App Store app

| What you get | Field |
|---|---|
| Apple's numeric ID and the bundle ID | `trackId`, `bundleId` |
| Name and developer | `appName`, `developer`, `developerId` |
| Price, as a number and as the store prints it | `price`, `formattedPrice`, `currency`, `isFree` |
| Rating and rating count, all versions and the current one | `averageUserRating`, `userRatingCount`, `averageUserRatingCurrentVersion`, `userRatingCountCurrentVersion` |
| Category | `primaryGenre`, `genres` |
| What shipped last and when | `version`, `releaseNotes`, `currentVersionReleaseDate`, `releaseDate` |
| Store text and links | `description`, `sellerUrl`, `appStoreUrl` |
| Icon and screenshots, iPhone and iPad kept apart | `artworkUrl`, `screenshotUrls`, `ipadScreenshotUrls` |
| The technical side | `minimumOsVersion`, `fileSizeBytes`, `supportedDevices`, `languageCodes`, `contentAdvisoryRating`, `advisories` |
| Customer reviews, when you ask for them | `reviews`, `reviewsCount` |

### ▶️ How to scrape App Store apps and reviews

1. Open [App Store Scraper](https://apify.com/dami_studio/app-store-scraper) and click
   **Try for free**.
2. Put a keyword into **Search term**, or IDs into **App IDs (trackId or bundleId)**, or store links
   into **App Store links**.
3. For reviews, use IDs or links, tick **Include reviews** and set **Max reviews per app**.
4. Change **Country / storefront** if you want a store other than `us`, then click **Start**.
5. Download the dataset as JSON, CSV or Excel, or pull it from the Apify API.

The form opens with `notion` in the search box, so pressing Start straight away runs a small search
you can look at. There is no free sample row.

### 💰 How much does it cost to scrape App Store apps?

**$0.09 per 1,000 apps** on the Free plan. Paid plans pay a little less: $0.089 on Starter, $0.088 on Scale and $0.087 on Business. On the free plan, the $5 Apify gives you each month covers about 55,000 apps.

You pay per app row, and its first 500 reviews are part of that row: pulling 500 reviews for an
app costs the same as pulling none. Each review past the 500th is **$0.052 per 1,000** on every plan,
so one app with all 5,000 reviews comes to about 23 cents. Two hundred apps, the most one search
returns, comes to under two cents.

Notes about bad input, a link from the wrong storefront or an app that is not in the store are not
charged.

### 📥 What you give it

```json
{
  "appIds": ["1232780281", "net.shinyfrog.bear"],
  "includeReviews": true,
  "maxReviews": 200,
  "reviewsSort": "mostrecent",
  "country": "us"
}
```

| Field | Default | What it is |
|---|---|---|
| `searchTerm` | none | A keyword, as you would type it into the store. The form opens with `notion` in it as an example. |
| `appIds` | empty | Numeric track IDs or bundle IDs, mixed freely. Used instead of a search term. |
| `startUrls` | none | App Store links, like `https://apps.apple.com/us/app/notion-notes-tasks-ai/id1232780281`. Each is looked up like an ID. A link from a storefront other than `country`, or one that is not an app page, gets a note instead. |
| `includeReviews` | `false` | Attach each app's reviews to its row. IDs and links only. |
| `maxReviews` | `100` | Reviews per app, 1 to 5,000. Past 500, each review is charged. |
| `reviewsSort` | `mostrecent` | `mostrecent` or `mosthelpful`. |
| `maxItems` | `50` | Apps per search, 1 to 200. Search only. |
| `country` | `us` | Two-letter storefront: `us`, `gb`, `de`, `jp`, `in` and the rest. One per run. A code Apple does not know comes back as a note rather than as results. |
| `notionConnector`, `notionParentId` | none | Optional. Also write each app as a page into your connected Notion workspace. |
| `proxyConfiguration` | off | Leave it off. The App Store answers without it. |

### 📤 What you get back

A real row from a run on 30 September 2026, looked up by link with reviews on. The description, the
image and device lists and the review text are cut short, and two of its three reviews are shown.

```json
{
  "ok": true,
  "trackId": 1232780281,
  "bundleId": "notion.id",
  "appName": "Notion: Notes, Tasks, AI",
  "developer": "Notion Labs, Incorporated",
  "developerId": 1232780280,
  "price": 0,
  "formattedPrice": "Free",
  "currency": "USD",
  "isFree": true,
  "averageUserRating": 4.77562,
  "userRatingCount": 90269,
  "averageUserRatingCurrentVersion": 4.77562,
  "userRatingCountCurrentVersion": 90269,
  "primaryGenre": "Productivity",
  "genres": ["Productivity", "Business"],
  "version": "1.7.343",
  "releaseDate": "2017-09-14T19:07:31Z",
  "currentVersionReleaseDate": "2026-09-29T15:16:18Z",
  "releaseNotes": "Bug fixes and performance improvements.",
  "description": "Notion is an AI-powered all-in-one workspace that helps individuals and teams write notes, manage tasks, organize projects, and collaborate in one place...",
  "sellerUrl": "https://www.notion.so",
  "appStoreUrl": "https://apps.apple.com/us/app/notion-notes-tasks-ai/id1232780281?uo=4",
  "artworkUrl": "https://is1-ssl.mzstatic.com/image/thumb/Purple211/v4/77/b0/86/.../512x512bb.jpg",
  "screenshotUrls": ["https://is1-ssl.mzstatic.com/image/thumb/PurpleSource221/v4/94/dd/d8/.../320x480bb.jpg", "..."],
  "ipadScreenshotUrls": ["https://is1-ssl.mzstatic.com/image/thumb/PurpleSource211/v4/33/b0/de/.../576x768bb.png", "..."],
  "minimumOsVersion": "18.0",
  "contentAdvisoryRating": "4+",
  "fileSizeBytes": 718542848,
  "languageCodes": ["AR", "NB", "ZH", "DA", "NL", "EN", "..."],
  "supportedDevices": ["iPhone5s-iPhone5s", "iPadAir-iPadAir", "..."],
  "advisories": [],
  "reviewsCount": 3,
  "reviews": [
    {
      "reviewId": "14600808350",
      "author": "PlexQ",
      "rating": 3,
      "title": "Pretty great until it isn’t",
      "body": "Generally enjoy notion a lot - it’s one of the better note apps out there. The range of features is really good...",
      "version": "1.7.342",
      "voteSum": 0,
      "voteCount": 0,
      "updated": "2026-09-27T12:45:51-07:00"
    },
    {
      "reviewId": "14598140299",
      "author": "K.loves20",
      "rating": 1,
      "title": "what's happening?",
      "body": "So far notion has been great, my number 1 go to for note taking among other things. But now the app has been more of nuisance than anything because it has several glitches now...",
      "version": "1.7.341",
      "voteSum": 0,
      "voteCount": 0,
      "updated": "2026-09-26T21:17:09-07:00"
    }
  ]
}
```

| Field | How to read it |
|---|---|
| `trackId`, `bundleId` | Either one works as input next time. Key your tracking on `trackId`. |
| `averageUserRating`, `userRatingCount` | All versions together. The `CurrentVersion` pair covers only the release that is live now, which is how you spot a rating that fell after an update. |
| `price`, `formattedPrice`, `currency` | Follow the storefront in `country`. |
| `releaseNotes`, `sellerUrl`, the rating fields | `null` on apps that have none. |
| `reviews` | Only with `includeReviews` on and IDs or links given. Each review has `reviewId`, `author`, `rating`, `title`, `body`, `version`, `voteSum`, `voteCount` and `updated`. |
| `reviewsCount` | `0` usually means the app has no reviews in that storefront, but a review feed that did not answer looks the same. |

### 🧾 Reading the output

| Row | How to spot it | Charged |
|---|---|---|
| An app | `ok: true` and a `trackId` | yes |
| A note | `ok: false` and an `errorCode` | no |

Notes about a link also carry the `link` and a `hint` saying what to change.

| Code | What it means |
|---|---|
| `BAD_INPUT` | Nothing to look up: no search term, no IDs, no links. Also written once per link that is not an app page or comes from another storefront. |
| `NO_RESULTS` | Apple returned nothing for that search or those IDs. A storefront code it does not recognise lands here too. |
| `NOT_FOUND` | That ID is not in this storefront. Try another `country`. |
| `NOT_SERVED` | This app was not served this run. Re-run it later. Runs before 13 October 2026 wrote `BLOCKED` here, and runs from 13 to 17 October wrote `NETWORK`. |
| `TIME_LIMIT` | The run got close to its time limit and stopped on its own. The apps delivered before that are complete and charged. Give the run more time, or ask for fewer apps, to get the rest. |
| `UNEXPECTED_ERROR` | The run stopped early on an unexpected error. The results before this row are kept. |

A run that ends on one of these rows still finishes as succeeded, including when the time limit
stopped it before any app came back: the `TIME_LIMIT` row and an amber status message say so.

The default table view shows app columns only, so the reviews do not appear in it. Export the
dataset, or open a row, to read them.

### 💡 What people use it for

- Keeping an eye on a rival app's rating, version and release notes week to week, keyed on
  `trackId`.
- Pulling the latest reviews of your own app into a spreadsheet or Notion, with the version each
  reviewer was on.
- Sizing a category: search the keyword, sort by `userRatingCount`, and see who owns it.
- Checking one app across storefronts, one run per country, to compare price and reception.

From a keyword to what users complain about:

1. Search `habit tracker` with `maxItems` at 200 and sort the rows by `userRatingCount`.
2. Put the top ten `trackId` values into `appIds`, tick `includeReviews`, and read the reviews where
   `rating` is 1 or 2.
3. Add the apps worth watching to
   [App Review Triage](https://apify.com/dami_studio/app-review-triage-monitor) with their store
   link, and new reviews from both stores arrive sorted into bugs, billing and requests.

### 🚧 What it does not do

- **Reviews only with IDs or links.** A keyword search ignores the reviews setting.
- **Up to 5,000 reviews per app.**
- **200 apps per search.** Narrow the keyword and run it again for more.
- **One storefront per run.** Comparing countries means one run each.
- **No chart position or ranking.**
- **No download or revenue figures.**
- **A zero review count can mean two things**, as the field notes above say.
- **No Google Play.** [Google Play Apps Scraper](https://apify.com/dami_studio/google-play-apps-scraper)
  does the same job for Android.
- It is not an official Apple tool. Dami's Studio is independent and is not affiliated with or endorsed by Apple, or by any other company named on this page.

### 🧭 Which app scraper do you need?

| If you want | Use |
|---|---|
| App Store metadata, or an app's reviews by ID or link | This one |
| The same job on Google Play | [Google Play Apps Scraper](https://apify.com/dami_studio/google-play-apps-scraper) |
| Google Play reviews for an Android app | [Google Play Reviews Scraper](https://apify.com/dami_studio/google-play-reviews-scraper) |
| New reviews from both stores, sorted into bugs, billing and requests | [App Review Triage](https://apify.com/dami_studio/app-review-triage-monitor) |

### ❓ Questions people ask

#### Do I need an Apple developer account or an API key to scrape the App Store?

No. There is nothing to sign up for and nothing to sign in to.

#### Why did Include reviews return no reviews?

The run was a search. Reviews need app IDs or App Store links, so put those in and run it again.

#### How do I get App Store reviews from another country?

Set `country` and run it again. Every storefront keeps its own reviews and its own prices.

#### Why do the numbers differ from what I see on my phone?

Your phone shows the store for your own country, and the row shows the one named in `country`.
Ratings also keep moving, so a row from last week is a week behind.

#### Can I call it from code or connect it to an AI assistant?

The [API tab](https://apify.com/dami_studio/app-store-scraper/api/python) has code for Python, JavaScript and the CLI.
MCP clients like Claude and ChatGPT use
`https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/app-store-scraper`; coding assistants can load [our
skill file](https://api.apify.com/v2/key-value-stores/BTBHU3DdiuoF4JOsK/records/apify-search-app-stores-SKILL.md). All
three bill your Apify account at the same price.

#### Is scraping the App Store legal?

This reads what the App Store shows anyone, with no sign-in. Reviews carry author names, which are
personal data under GDPR and similar laws, so have a reason for holding them. Apify's write-up on
[the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) is a good starting
point, and we are not lawyers.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Send the search term or the app IDs, the storefront and
the run ID. If a note landed in the dataset, its `errorCode` usually names the reason already.

# Actor input Schema

## `searchTerm` (type: `string`):

Keyword to search the App Store for (e.g. "notion", "habit tracker"). Returns matching apps with full metadata. Leave empty if you are looking up specific apps by ID instead.

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

Look up specific apps by numeric trackId (e.g. "1232780281") or bundleId (e.g. "net.shinyfrog.bear"). Each app is returned with full metadata; enable "Include reviews" to also fetch its customer reviews. Used instead of Search term. Note: individual metadata fields (e.g. averageUserRating, releaseNotes, sellerUrl, price) can be null for some apps.

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

Links to apps' App Store pages, as you copy them from the browser, e.g. https://apps.apple.com/us/app/notion-notes-tasks-ai/id1232780281. The id is read out of each link and looked up just like an App ID, so "Include reviews" works here too. Country still decides the storefront: a link from another one (the two letters after apps.apple.com/) is skipped with a note rather than read from the wrong store, and so is anything that is not an app page, such as a developer page.

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

Order in which to fetch reviews: most recent first, or most helpful first.

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

Two-letter App Store storefront code, e.g. us, gb, ca, de, fr, jp, in. Affects which apps, prices, and reviews are returned. Use a valid ISO storefront code: an invalid code (e.g. "us-uk") is rejected by Apple's API and the actor returns a diagnostic row with no results instead of charging.

## `maxReviews` (type: `integer`):

How many customer reviews to read per app when "Include reviews" is on, up to 5,000. The first 500 of each app come with the app's price, and each review past them is charged on its own.

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

Maximum number of apps to return when using Search term. Up to 200 results per query.

## `includeReviews` (type: `boolean`):

When looking up apps by ID, also fetch each app's customer reviews (author, rating, title, body, version, date) from Apple's public reviews feed. Ignored in Search mode.

## `notionConnector` (type: `string`):

Optional. Write each app as a page into your Notion when the run finishes. Authorize a Notion connector once in Settings → API & Integrations → MCP connectors, then pick it here. Leave empty to skip (default), results are always saved to the dataset regardless.

## `notionParentId` (type: `string`):

Optional. The Notion data source ID of the database to write into (only used if a Notion connector is set). Leave empty to create the pages privately in your workspace instead.

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

OPTIONAL. Your own proxy servers are used exactly as given.

## Actor input object example

```json
{
  "searchTerm": "notion",
  "appIds": [],
  "reviewsSort": "mostrecent",
  "country": "us",
  "maxReviews": 100,
  "maxItems": 50,
  "includeReviews": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Scraped rows are stored in the default dataset (one row per result). Blocked/empty/error runs return a single uncharged diagnostic row instead.

# 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 = {
    "searchTerm": "notion"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/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 = { "searchTerm": "notion" }

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/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 '{
  "searchTerm": "notion"
}' |
apify call dami_studio/app-store-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/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/kF6hpEFWjPlKYkJAT/builds/zhWwRvXrU1S9bFI6y/openapi.json
