# Shopify App Store Scraper - Ranks, Pricing & Reviews (`benthepythondev/shopify-app-store-scraper`) Actor

Track Shopify App Store category ranks, pricing plans, ratings and reviews. Tags 1-2 star complaints by theme and reports rank moves, new apps and price changes since your last run.

- **URL**: https://apify.com/benthepythondev/shopify-app-store-scraper.md
- **Developed by:** [Ben](https://apify.com/benthepythondev) (community)
- **Categories:** E-commerce, Developer tools, SEO tools
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 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

## Shopify App Store Scraper: Ranks, Pricing Plans & Review Complaints

Track where every app ranks in a Shopify App Store category, what its pricing plans cost, and what its 1-2 star reviews complain about. Run it again next week and you get the changes as their own rows: rank moves, new entrants, dropped apps, rating and review-count deltas, and pricing plan changes. **$3 per 1,000 apps, $1 per 1,000 reviews, change rows free.**

- **Category rank tracking.** Every app row carries its position (`categoryRank`) in the category it came from, read from the full paginated list (24 apps per page).
- **Changes since last run.** The last snapshot is kept in a named key-value store in your own account. No diffing script on your side.
- **Complaint themes.** 1-2 star reviews are tagged by fixed keyword rules (billing, support, bugs, performance, missing feature, uninstall leftovers, theme conflicts, ease of use), and each app gets a theme count. No AI model, so the same review always gets the same tags.
- **Full pricing plans.** Plan name, price, currency, interval, trial days and the feature list of every plan, plus the pricing badge shown on the card.
- Plain HTTP on public pages, no login, no browser. A 24-app category with details runs in about 15 seconds.

### What does the Shopify App Store Scraper do?

It reads public pages on [apps.shopify.com](https://apps.shopify.com): category listings, app pages and review pages. You give it category slugs (or URLs) and/or app handles. It returns one row per app, one row per review (when reviews are on), and one row per changed app on every run after the first.

It is for Shopify app developers watching their category, agencies comparing apps for a client, investors and researchers sizing a niche, and anyone looking for weak leaders: apps with many installs and a pile of recent 1-star reviews about the same problem.

### How is it different from other Shopify App Store scrapers?

| | This Actor | Typical app store scraper |
|---|---|---|
| Rank per category on every row | yes (`categoryRank`, `rankSource`) | position only in some |
| Changes since last run | built in, free change rows | you diff two exports yourself, or pay per item |
| Complaint themes on 1-2 star reviews | yes, keyword rules, per-app counts | raw review text only |
| Reviews sorted newest first, with star filter | yes (`reviewStars`) | varies; sorting has been a reported problem |
| Price | $0.003 per app, $0.001 per review | $0.002 to $0.05 per item |

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `categories` | array | `["marketing-and-conversion-social-trust-product-reviews"]` | Category slugs or URLs. A subcategory gives the full ranked list; a top-level category (like `store-design`) gives its curated picks. Use `[]` to read only `appUrls`. |
| `appUrls` | array | `[]` | App URLs or handles, e.g. `https://apps.shopify.com/judgeme` or `klaviyo-email-marketing`. Read in addition to the categories. |
| `maxApps` | integer | `24` | Ranked apps to read per category. |
| `includeDetails` | boolean | `true` | Open each app page for pricing plans, rating distribution, developer, launch date, languages, works-with and categories. |
| `includeReviews` | boolean | `false` | Read each app's newest reviews and add complaint themes. |
| `maxReviews` | integer | `20` | Reviews per app (10 per page). |
| `reviewStars` | array | `[]` | Only these ratings, e.g. `["1","2"]`. Empty reads all. |
| `trackChanges` | boolean | `true` | Save the snapshot and output change rows on the next run. |
| `stateStoreName` | string | `shopify-app-store-tracker` | Name of the store that keeps the snapshot. Use one name per project. |

#### Example: weekly watch of a category with complaints

```json
{
  "categories": ["marketing-and-conversion-social-trust-product-reviews"],
  "maxApps": 48,
  "includeReviews": true,
  "maxReviews": 20,
  "reviewStars": ["1", "2"]
}
```

Schedule it weekly. The first run saves the baseline; every run after it adds `change` rows.

#### Example: a few named apps

```json
{ "categories": [], "appUrls": ["judgeme", "https://apps.shopify.com/klaviyo-email-marketing"] }
```

### Output

Every row has `recordType`: `app`, `review`, `change`, or `status` (one unbilled `no_results` row when nothing was found).

#### App row (real output, trimmed)

```json
{
  "recordType": "app",
  "source": "category:marketing-and-conversion-social-trust-product-reviews",
  "categoryRank": 2,
  "rankSource": "all",
  "appSlug": "google-review-plus-by-entangle-1",
  "appName": "EC ‑ Google Reviews",
  "appUrl": "https://apps.shopify.com/google-review-plus-by-entangle-1",
  "rating": 5.0,
  "reviewsCount": 602,
  "pricingBadge": "Free plan available",
  "builtForShopify": true,
  "pricingPlans": [
    {"name": "Free", "priceLabel": "Free", "price": 0.0, "currency": null, "interval": null, "features": ["..."]},
    {"name": "Platinum", "priceLabel": "$4.99/month", "price": 4.99, "currency": "USD", "interval": "month", "features": ["..."]}
  ],
  "freeTrialDays": 7,
  "ratingDistribution": {"5": 589, "4": 9, "2": 1, "1": 3},
  "developerName": "Entangle Commerce",
  "developerUrl": "https://apps.shopify.com/partners/entangle-commerce",
  "developerAddress": "Toronto, ON, CA",
  "developerEmail": "support@entanglecommerce.com",
  "developerWebsite": "https://googlereviewsrocket.com/",
  "launchDate": "July 18, 2023",
  "categories": ["Product reviews", "Social proof"],
  "lowRatingReviewsRead": 4,
  "complaintThemes": {"bugs": 1, "billing": 1}
}
```

App rows also carry `tagline`, `iconUrl`, `description`, `languages`, `worksWith` and `privacyPolicyUrl`.

#### Review row

`appSlug`, `appUrl`, `appName`, `reviewId`, `reviewUrl`, `stars`, `reviewDate` (ISO), `reviewEdited`, `reviewBody`, `merchantStore`, `country`, `usageDuration` (e.g. "8 months using the app"), `developerReply`, `developerReplyDate`, `complaintThemes` (on 1-2 star reviews).

#### Change row

```json
{
  "recordType": "change",
  "source": "category:marketing-and-conversion-social-trust-product-reviews",
  "appSlug": "google-reviews-trust-badge",
  "changeTypes": ["new_entrant"],
  "previousRank": null, "rank": 4, "rankDelta": null,
  "previousRating": null, "rating": 5.0,
  "previousReviewsCount": null, "reviewsCount": 1567, "reviewsDelta": null,
  "comparedWith": "2026-11-01T09:09:06+00:00"
}
```

`changeTypes` can hold `new_entrant`, `dropped`, `rank_move` (`rankDelta` positive = moved up), `rating_change`, `reviews_delta` and `pricing_change`. An app below this run's depth (you lowered `maxApps`) is not reported as dropped.

### How much does it cost?

Pay per event: $0.003 per app row, $0.001 per review row, a $0.00005 start fee. Change rows and the status row are free. A weekly 48-app watch with 20 low-star reviews per app costs about $0.14 + $0.96 = $1.10 a run; without reviews, $0.14. Higher Apify plans get the Store discount automatically.

### Complaint themes: how tagging works

Each 1-2 star review is matched against keyword rules, and a review can get several themes:

- `billing`: charged, refund, subscription, cancel, overcharged
- `support`: support, no response, ticket, on hold
- `bugs`: broken, error, crash, stopped working, not showing
- `performance`: slow, page speed, load time
- `missing_feature`: missing, no option, doesn't support, needs at least
- `uninstall_leftovers`: uninstall, leftover code, still in my theme
- `theme_conflicts`: theme, conflict, layout, CSS
- `ease_of_use`: complicated, confusing, tedious, hard to set up

The rules are English. Reviews in other languages are still returned, they just get no theme.

### FAQ

**Can it search the App Store by keyword?** No. apps.shopify.com's robots.txt disallows search URLs (`*q=*`) for crawlers, so this Actor stays on category, app and review pages. Pick the subcategory that matches your keyword instead.

**Does it need a Shopify account or a proxy?** No account. It uses direct requests and moves to the Apify proxy only if the site answers 403 or 429.

**How fresh is the data?** Live: every run reads the pages at that moment.

**Where is the change history kept?** In the named key-value store `stateStoreName` in your own Apify account, one record per category. Delete that record to start a new baseline.

**Why does a top-level category return only about 30 apps?** Top-level pages like `store-design` show curated groups, not a ranked list (`rankSource: "curated"`). Subcategories like `store-design-site-optimization-seo` have the full paginated list.

### Use it from code, Make, Zapier or n8n

Call it through the Apify API, the Python or JavaScript client, or the Apify integrations for Make, Zapier and n8n. Schedule it from the Apify Console to get a weekly change report.

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("benthepythondev/shopify-app-store-scraper").call(run_input={
    "categories": ["store-design-site-optimization-seo"], "maxApps": 48,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["recordType"] == "change":
        print(row["appName"], row["changeTypes"], row.get("rankDelta"))
```

### Is it legal to scrape the Shopify App Store?

It reads only public pages that any visitor can open without logging in, follows the site's robots.txt, and collects no personal data beyond what developers publish as business contact details. You are responsible for how you use the data; check Shopify's terms for your use case.

# Actor input Schema

## `categories` (type: `array`):

Shopify App Store category slugs or URLs to rank, e.g. 'marketing-and-conversion-social-trust-product-reviews' or https://apps.shopify.com/categories/store-design-site-optimization-seo. Subcategories give the full ranked list; top-level categories give the curated picks. Use \[] to read only appUrls.

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

Specific apps to read, as URLs or handles, e.g. https://apps.shopify.com/judgeme or 'klaviyo-email-marketing'. Read in addition to the categories.

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

How many ranked apps to read from each category, e.g. 24 (one page) or 100. Each app is one billed result.

## `includeDetails` (type: `boolean`):

Open every app page for pricing plans (name, price, interval, trial days, features), rating distribution, developer, launch date, languages, works-with and categories. Off: only the ranked card data.

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

Also read each app's newest reviews, tag 1-2 star reviews with complaint themes (billing, support, bugs...) and add a per-app theme count. Each review is one billed result.

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

How many newest reviews to read per app when reviews are on, e.g. 20 or 200 (10 reviews per page).

## `reviewStars` (type: `array`):

Read only reviews with these ratings, e.g. \['1','2'] for complaints only. Empty list reads all ratings.

## `trackChanges` (type: `boolean`):

Save each category's ranks, ratings, review counts and pricing in a named key-value store and output free 'change' rows on the next run: rank moves, new entrants, dropped apps, rating and review-count deltas, pricing plan changes.

## `stateStoreName` (type: `string`):

Name of the key-value store that keeps the last snapshot, e.g. 'shopify-app-store-tracker'. Use a different name per project to keep separate histories.

## Actor input object example

```json
{
  "categories": [
    "marketing-and-conversion-social-trust-product-reviews"
  ],
  "appUrls": [
    "https://apps.shopify.com/judgeme"
  ],
  "maxApps": 24,
  "includeDetails": true,
  "includeReviews": false,
  "maxReviews": 20,
  "reviewStars": [],
  "trackChanges": true,
  "stateStoreName": "shopify-app-store-tracker"
}
```

# 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 = {
    "categories": [
        "marketing-and-conversion-social-trust-product-reviews"
    ],
    "appUrls": [
        "https://apps.shopify.com/judgeme"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("benthepythondev/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 = {
    "categories": ["marketing-and-conversion-social-trust-product-reviews"],
    "appUrls": ["https://apps.shopify.com/judgeme"],
}

# Run the Actor and wait for it to finish
run = client.actor("benthepythondev/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 '{
  "categories": [
    "marketing-and-conversion-social-trust-product-reviews"
  ],
  "appUrls": [
    "https://apps.shopify.com/judgeme"
  ]
}' |
apify call benthepythondev/shopify-app-store-scraper --silent --output-dataset

```

## MCP server setup

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