# Shopify App Store Scraper — Statistics, Pricing & Reviews (`kaankaan2635/shopify-app-store-scraper`) Actor

Shopify App Store statistics: app listings with pricing plans, the per-star rating breakdown, categories and merchant reviews.

- **URL**: https://apify.com/kaankaan2635/shopify-app-store-scraper.md
- **Developed by:** [Kaan Salgır](https://apify.com/kaankaan2635) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 app listing scrapeds

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

## Shopify App Store Scraper — Statistics, Pricing & Reviews

This **Shopify App Store scraper** exports app listings with their **pricing plans**, the full **per-star rating breakdown**, categories, launch dates and merchant reviews — the **Shopify App Store statistics** you would otherwise have to click through 27,000 pages to assemble.

No account, no API key.

### Shopify app statistics: the exact star breakdown

Most App Store scrapers return an average rating and a total. This one returns how many 5-star, 4-star, 3-star, 2-star and 1-star reviews an app actually has — the number that tells you whether a 4.6 average is 2,000 happy merchants or a bimodal mess.

The values are read from the accessible label, not the abbreviated `2.9K` shown on screen, and every run asserts that the five buckets sum to the reported review count.

```json
"ratingBreakdown": { "5": 2905, "4": 83, "3": 31, "2": 37, "1": 259 }
```

### Shopify app pricing data

Every plan on a listing, parsed: plan name, price as displayed, additional charges, and the full feature list per tier. Combined with `hasFreePlan` and `pricingPlanCount`, that is a competitive pricing table for an entire category in one run.

### Merchant reviews, with developer replies separated

The review layout orders its three columns with CSS, so positional parsers routinely paste the developer's reply into the store-name field. This scraper matches columns by content, so `storeName`, `body` and `developerReply` never bleed into each other.

Per review: `rating` · `reviewDate` · `body` · `storeName` · `storeCountry` · `timeUsingApp` · `developerReplied` · `developerReply` · `developerReplyDate`

### What you get per app

| Field | Example |
| --- | --- |
| `name`, `handle`, `url`, `description`, `iconUrl` | `Klaviyo: Email Marketing & SMS` |
| `developer` | `{ name: "Klaviyo", handle: "klaviyo" }` |
| `rating`, `reviewCount` | `4.7`, `3315` |
| `ratingBreakdown` | `{ "5": 2905, "4": 83, … }` |
| `pricingPlans` | name, price, additional charges, features |
| `pricingPlanCount`, `hasFreePlan` | `3`, `true` |
| `categories` | slug, name and URL for each |
| `launchedDate` | `September 20, 2012` |
| `worksWith` | `Checkout, Shopify Flow, Gorgias, …` |
| `languages` | 10 locales |
| `builtForShopify` | `true` / `false` |

### How to use this Shopify App Store scraper

Pick one starting point:

- **App handles** — `klaviyo-email-marketing`, `omnisend`. The last part of a listing URL.
- **App URLs** — paste full listing URLs; tracking parameters are stripped.
- **Category slugs** — `marketing-and-conversion-marketing-email-marketing` scrapes every app in that category, page by page.
- **Crawl the whole store** — walks all ~27,000 listings from the official sitemap. Pair it with **Maximum apps**.

```json
{
  "categorySlugs": ["marketing-and-conversion-marketing-email-marketing"],
  "maxApps": 200,
  "includeReviews": true,
  "maxReviewsPerApp": 50,
  "reviewsOutput": "separate"
}
```

Reviews are off by default because they cost extra page loads: reviews paginate 10 per page, so 50 reviews per app means 5 extra requests per app.

### FAQ

**Do I need a Shopify account or API key?**
No. This reads public App Store listing pages.

**Can it scrape the whole Shopify App Store?**
Yes — turn on **Crawl the whole store** and it enumerates all ~27,000 listings from Shopify's official sitemap. Use **Maximum apps** to cap a run.

**Can it search for apps by keyword?**
No, deliberately. The App Store's robots.txt disallows any URL carrying a `q=` search parameter, so this scraper enumerates through the sitemap and category pages instead. Competing scrapers that advertise keyword search are ignoring that rule.

**Can it scrape Shopify store owners' emails or phone numbers?**
No. This is an *App Store* scraper — it reads app listings, not merchant contact details. Store names on reviews are business identities; no person names, emails or phones are collected.

**Why do some apps have no rating?**
An app with no reviews has no rating, so `rating`, `reviewCount` and `ratingBreakdown` come back null rather than zero.

**Does it get "Built for Shopify" status?**
Yes, as a boolean on every app row.

**Is scraping the Shopify App Store legal?**
It reads publicly accessible listing pages, respects the App Store's robots.txt, and collects no personal data. How you use the output is your responsibility.

### Notes on reliability

The App Store rate-limits hard — it returns HTTP 429 long before it returns 404, and it serves those 429s as `text/plain`, which is enough to break a naively configured crawler. This scraper handles both: blocked responses are retried on a fresh session, and the request rate is capped by **Maximum requests per minute**.

Use Apify Proxy (the default). Without it, sustained crawls will be throttled after a few hundred pages.

### Pricing

Pay per event: one charge per app record and one per review record — not for compute time, not for failed requests.

### Development

```bash
npm install
npm test          # offline regression tests against saved fixtures
npm start         # local run; put an INPUT.json in storage/key_value_stores/default/
```

# Actor input Schema

## `appHandles` (type: `array`):

App handles to scrape, for example <code>klaviyo-email-marketing</code>. This is the last part of the listing URL.

## `appUrls` (type: `array`):

Full listing URLs, for example <code>https://apps.shopify.com/klaviyo-email-marketing</code>. Tracking parameters are stripped automatically.

## `categorySlugs` (type: `array`):

Scrape every app in a category, for example <code>marketing-and-conversion-marketing-email-marketing</code>. Take the slug from any <code>/categories/…</code> URL.

## `crawlWholeStore` (type: `boolean`):

Enumerate every app from the official sitemap (about 27,000 listings) instead of using the inputs above. Combine with <b>Maximum apps</b>.

## `maxApps` (type: `integer`):

Hard cap on how many app listings this run scrapes.

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

Also scrape merchant reviews with star rating, store name, country, time using the app and the developer's reply.

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

Reviews are paginated 10 per page, so 50 reviews costs 5 extra page loads per app.

## `reviewsOutput` (type: `string`):

<b>Embedded</b> gives one row per app with a <code>reviews</code> array. <b>Separate</b> gives one row per review, which is easier to load into a spreadsheet or database.

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

Lower this if you see blocked requests. Higher is faster but harder on the target site.

## `maxRequestsPerMinute` (type: `integer`):

The App Store rate-limits aggressively. Measured without a proxy it returns HTTP 429 for about 10% of requests even at 150/min. Blocked requests are retried automatically on a fresh session, but lowering this reduces them at the source.

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

Apify Proxy is strongly recommended. Without it the App Store will start refusing requests after a few hundred pages.

## Actor input object example

```json
{
  "appHandles": [
    "klaviyo-email-marketing",
    "omnisend"
  ],
  "appUrls": [],
  "categorySlugs": [],
  "crawlWholeStore": false,
  "maxApps": 100,
  "includeReviews": false,
  "maxReviewsPerApp": 50,
  "reviewsOutput": "embedded",
  "maxConcurrency": 10,
  "maxRequestsPerMinute": 120,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `apps` (type: `string`):

One row per app listing, or one row per review when the run is set to separate review output.

# 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 = {
    "appHandles": [
        "klaviyo-email-marketing",
        "omnisend"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kaankaan2635/shopify-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 = { "appHandles": [
        "klaviyo-email-marketing",
        "omnisend",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("kaankaan2635/shopify-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 '{
  "appHandles": [
    "klaviyo-email-marketing",
    "omnisend"
  ]
}' |
apify call kaankaan2635/shopify-app-store-scraper --silent --output-dataset

```

## MCP server setup

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