# Shopify App Store API — Apps, Pricing, Ratings & Reviews (`insight.solutions/shopify-app-store-api`) Actor

Scrape the Shopify App Store as data: every app in a category, collection or developer page with rating, review count, pricing plans, launch date, developer and Built for Shopify badge, plus merchant reviews with developer replies. Honours robots.txt. No API key, no browser.

- **URL**: https://apify.com/insight.solutions/shopify-app-store-api.md
- **Developed by:** [Insight Solutions](https://apify.com/insight.solutions) (community)
- **Categories:** E-commerce, Business, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

## Shopify App Store API — Apps, Pricing, Ratings & Reviews

**The Shopify App Store's public pages, as rows: every app in a category, a collection or a developer's catalogue, with its rating, review count, pricing plans, launch date, developer and Built for Shopify badge — and, when you ask, its merchant reviews with the developer's replies.** No API key, no login, no browser. The store's robots.txt is read at the start of every run and honoured for every request.

Give it a category (`marketing-and-conversion-marketing-email-marketing`), a collection (`built-for-shopify`), a developer (`klaviyo`) or a list of apps (`judgeme`), and get back one row per app in the order the store lists them. Turn on reviews and each app's reviews follow it — newest first or most relevant, filtered by star rating if you like. Or run mode `categories` once to get the category tree, free.

**$2 per 1,000 apps with their full listing, $0.50 per 1,000 listing-only apps, $0.50 per 1,000 reviews, proxy included.** A typo'd slug, a delisted app, a page that could not be read, and a run that returns nothing all cost nothing at all.

### Try it in 30 seconds

**Input** — this is the Store prefill; paste it and run:

```json
{
  "mode": "category",
  "categories": ["marketing-and-conversion-marketing"],
  "maxAppsPerSource": 20,
  "includeDetails": true
}
```

That is the "Marketing apps" category page: one listing page and twenty app pages, three at a time. A slug or any URL of the category works (`https://apps.shopify.com/categories/…`, tracking parameters and all).

**Output** — one `app` row per app. The fields you will use most are `rank`, `name`, `rating`, `reviewCount`, `pricingSummary`, `pricingPlans`, `builtForShopify`, `developerName`, `launchedAt` and `url` (full list under *Output reference*). Anything that could not be read comes back as a free diagnostic row (`ok: false`, `errorType`, `error`) instead of a charge.

**Price** — $0.041 for the prefill run (20 apps × $0.002, plus $0.001 for the run). Pay-per-event, no API key, no browser, limited permissions — works over the Apify MCP server (`mcp.apify.com`) and with agentic (x402) payments.

**From code** — `client.actor("insight.solutions/shopify-app-store-api").call(run_input={"mode": "apps", "apps": ["judgeme"], "includeReviews": True})` with `apify-client`, or `POST https://api.apify.com/v2/acts/insight.solutions~shopify-app-store-api/run-sync-get-dataset-items`.

### What comes back

An app row, exactly as the Actor writes it from the captured category page and Klaviyo's app page (description shortened, two plans and some lists cut; the review, category and diagnostic columns, all `null` here, left out):

```jsonc
{
  "ok": true,
  "rowType": "app",                      // "app" | "review" | "category" | "diagnostic"
  "input": "marketing-and-conversion-marketing",
  "handle": "klaviyo-email-marketing",
  "name": "Klaviyo: Email Marketing & SMS",
  "url": "https://apps.shopify.com/klaviyo-email-marketing",
  "iconUrl": "https://cdn.shopify.com/app-store/listing_images/5edd9000b933a8fa88c152d1e498531f/icon/CP6B2OOv3PYCEAE=.png",

  "categorySlug": "marketing-and-conversion-marketing",   // the listing it came from
  "rank": 13,                            // 13th app the category page lists, each app counted once
  "position": 1,                         // 1st card in its section
  "section": "Email marketing",
  "sectionSlug": "marketing-and-conversion-marketing-email-marketing",

  "rating": 4.7,
  "reviewCount": 3359,
  "ratingBreakdown": { "1": 263, "2": 37, "3": 31, "4": 83, "5": 2945 },
  "pricingSummary": "Free to install",
  "builtForShopify": false,
  "summary": "Email marketing, SMS, & WhatsApp that turn messages into sales",

  "detailsRead": true,                   // false = listing card only (billed as app-listing)
  "tagline": "Build email marketing, SMS, and WhatsApp campaigns powered by AI to grow ecommerce sales.",
  "description": "Go beyond the basics with the Klaviyo marketing app. New stores get a guided setup — …",
  "highlights": ["Unify and activate real-time data from Shopify and 350+ apps across the journey", "…"],
  "launchedAt": "2012-09-20",

  "pricingPlans": [
    { "name": "Free", "price": 0, "currency": "USD", "period": null, "priceText": "Free to install", "trialDays": null,
      "notes": "Free to install. Email free forever for up to 250 contacts. SMS free for up to 150 SMS/MMS credits.",
      "features": ["Sync Shopify data–tags, catalog, coupons", "Templates for Email/SMS", "…"] },
    { "name": "SMS", "price": 15, "currency": "USD", "period": "month", "priceText": "$15/month", "trialDays": null,
      "notes": "Up to 1250 SMS/MMS credits. Includes carrier fees. Upgrade as you grow.", "features": ["…"] }
  ],

  "developerName": "Klaviyo",
  "partnerSlug": "klaviyo",
  "developerUrl": "https://apps.shopify.com/partners/klaviyo",
  "developerCountry": "US",              // the country code that ends the developer's published address
  "websiteUrl": "https://developers.klaviyo.com/en",
  "supportEmail": "support@klaviyo.com", // role mailboxes only
  "privacyPolicyUrl": "https://www.klaviyo.com/privacy",
  "faqUrl": "https://help.klaviyo.com/hc/en-us/articles/115005080407",
  "documentationUrl": "https://academy.klaviyo.com/en-us",
  "tutorialUrl": "https://www.klaviyo.com/customer-resources",
  "changelogUrl": "https://developers.klaviyo.com/en/docs/changelog_",
  "demoStoreUrl": null,

  "languages": ["English", "French", "Spanish", "German", "Portuguese (Brazil)", "Korean", "Italian", "Polish", "Swedish", "Dutch"],
  "worksWith": ["Checkout", "Customer accounts", "Shopify Flow", "Shopify Admin", "Aftership", "Gorgias", "…"],
  "categories": ["Email marketing", "SMS marketing"],
  "categorySlugs": ["marketing-and-conversion-marketing-email-marketing", "marketing-and-conversion-marketing-sms-marketing"],
  "screenshotCount": 7,
  "videoUrl": "https://www.youtube-nocookie.com/embed/iJoev3QtygI",

  "error": null,
  "errorType": null,
  "scrapedAt": "2026-10-07T22:01:37.076Z",
  "source": "apps.shopify.com",
  "sourceUrl": "https://apps.shopify.com/klaviyo-email-marketing"
}
```

Every row carries the same 61 columns; the ones that do not apply to a row type are `null`.

With `"includeDetails": false` the row is the listing card only — `handle`, `name`, `url`, `iconUrl`, `rank`, `position`, `section`, `rating`, `reviewCount`, `pricingSummary`, `builtForShopify` and `summary` — at a quarter of the price and with no request per app.

#### Review rows

With `"includeReviews": true`, each app row is followed by its reviews:

```jsonc
{ "ok": true, "rowType": "review", "appHandle": "klaviyo-email-marketing",
  "reviewId": 2380223, "rating": 1, "reviewedAt": "2026-10-01", "isEdited": false,
  "storeName": "The Little Rainbow Company Limited", "country": "New Zealand", "usageDuration": "Almost 3 years",
  "body": "It’s okay but when trying to cancel it makes it extremely hard. …",
  "developerReply": "We appreciate you for sharing this feedback regarding your experience with the cancellation process. …",
  "developerReplyAt": "2026-10-02",
  "url": "https://apps.shopify.com/klaviyo-email-marketing/reviews",
  "sourceUrl": "https://apps.shopify.com/klaviyo-email-marketing/reviews?page=1&sort_by=newest" /* every other column null */ }
```

App Store reviews are signed by the merchant's **store**, a business — `storeName` is that. A review whose store name has the shape of one person's name is returned with `storeName: null` (see *Privacy*). An edited review is flagged and dated by its edit; a rating-only review has `body: null`.

#### Category rows

`"mode": "categories"` with no slugs reads the store's category navigation: the seven top-level categories with their one-line descriptions, and the store's "Top categories". With slugs in `categories`, it reads each category page and returns the category itself (name, parent, pitch) and one row per subcategory it links to — run it again on a subcategory to go a level deeper. Category rows are free; the run bills nothing at all.

```jsonc
{ "ok": true, "rowType": "category", "slug": "marketing-and-conversion", "name": "Marketing and conversion",
  "description": "Get customers with reviews, bundles, upsells, checkout, email marketing",
  "section": "Apps by category", "parentSlug": null, "url": "https://apps.shopify.com/categories/marketing-and-conversion" }
```

### Modes

| `mode` | Reads | One row per |
|---|---|---|
| `category` *(prefill)* | `categories`: slugs or category URLs | app the category lists, in the store's order |
| `collection` | `collections`: `built-for-shopify`, `/collections/<slug>` or the `/app-groups/…` address it redirects to | app in the collection |
| `partner` | `partners`: developer slugs or `/partners/<slug>` URLs | app the developer publishes |
| `apps` | `apps`: handles or app URLs | app you named (its page is always read) |
| `categories` | `categories` (optional) | category (free) |

**There is no keyword-search mode, on purpose.** The store's robots.txt disallows `*q=*` — its search — for every crawler, so this Actor never requests a URL containing `q=`. The `keyword` input instead filters the apps a listing already returned, by name and one-line summary, case-insensitively; apps it drops cost no request and no charge.

### Use cases

- **Competitor tracking for app developers** — run your category daily and diff on `handle`: rating and `reviewCount` movement, new entrants, apps that gained or lost the Built for Shopify badge, rank changes.
- **Review monitoring** — `mode: apps` on your own and your competitors' apps, `reviewSort: newest`, a small `maxReviewsPerApp`: every new review and whether the developer answered it.
- **Complaint mining** — `reviewRatings: ["1", "2"]` for the one- and two-star reviews of a whole category, with `usageDuration` to tell first-week churn from long-time users.
- **Pricing research** — every plan, price, billing period, trial length and feature list across a category, in one schema.
- **Agency and merchant shortlists** — the apps of a category with their ratings, review counts, pricing summary and Built for Shopify badge, ready for a spreadsheet.
- **Market mapping** — `mode: categories` for the tree, then `includeDetails: false` across many categories for a cheap snapshot of who is where.

### How it works, and why it keeps working

Every request is an ordinary page request a browser would make; nothing needs a login or a key.

| Step | Request | What it gets |
|---|---|---|
| R | `/robots.txt` | Read once per run; every URL below is checked against its `User-agent: *` rules first |
| 1 | `/categories/<slug>`, `/collections/<slug>`, `/partners/<slug>` | The listing: each app's card — handle, name, rating, review count, pricing label, badge, section |
| 2… | `?page=2`, `?page=3`, … | The next listing page, only when the page links to one (`rel="next"`) and you want more |
| A | `/categories/<slug>/all` | Once, when a category landing page has no pager and shows fewer apps than you asked for; a 404 there means the landing page was the whole list |
| D | `/<handle>` | With `includeDetails`: the app page — JSON-LD rating, plans, developer, languages, categories, rating breakdown |
| V | `/<handle>/reviews?page=N` (`&sort_by=newest`, `&ratings[]=1`) | With `includeReviews`: ten reviews per page |
| C | `/categories` | Mode `categories`: the navigation (the store redirects it to its home page) |

Details that came out of the captured pages, and that a naive version gets wrong:

- **A category page can be a curated landing page.** The captured "Marketing apps" page shows 39 cards in four sections — and only 31 apps, because the same app is featured in several. Apps are de-duplicated in the order they appear; `rank` counts each app once, while `section` and `position` say where its first card was. Its `?page=2` is page 1 again; a page that adds no new app ends the walk.
- **Reviews' rating filter is `ratings[]`, sorts are `newest` and `relevance`.** Those are the two orders the review page offers ("Date: Newest to oldest", "Most relevant"); the filter is sent to the store and checked again on what comes back.
- **The hero's "Based in …" line is about the visitor, not the developer.** Judge.me, whose address ends in GB, showed "Based in United States" to the US proxy exit that captured it. `developerCountry` comes from the developer's own published address instead.
- **The demo store link carries a short-lived access token** (`_bt=…`); `demoStoreUrl` is returned without it, since it has expired by the time anyone reads the row.

Underneath: **Apify proxy**, one pinned session per parallel worker. When an exit IP is refused — HTTP 403, HTTP 429, a challenge page wearing HTTP 200, or a proxy tunnel that answers 403 — that session is retired and **the same request is made once more from a different address**. A second refusal is final for that page: the run **keeps every row it already delivered** and files one free `blocked` row. Requests from one worker are spaced 300–600 ms apart, and `maxConcurrency` (default 3) bounds how many app pages are read at once.

### Input reference

| Field | Type | Default | What it does |
|---|---|---|---|
| `mode` **(required)** | select | `category` | `category`, `collection`, `partner`, `apps` or `categories` (see *Modes*) |
| `categories` | array of strings | prefilled with one category | Category slugs or URLs. In mode `categories`: optional, the categories to list subcategories of |
| `collections` | array of strings | `[]` (prefill `built-for-shopify`) | Collection slugs or URLs. Read only in mode `collection` |
| `partners` | array of strings | `[]` (prefill `klaviyo`) | Developer slugs or URLs. Read only in mode `partner` |
| `apps` | array of strings | `[]` (prefill `judgeme`) | App handles or URLs (the `/reviews` tab works too). Read only in mode `apps` |
| `keyword` | string | `""` | Keep apps whose name or one-line summary contains this phrase. Filters listing results; not the store's search. Ignored in mode `apps` |
| `includeDetails` | boolean | `true` | Read each app's page (billed as `app`); off = card only (billed as `app-listing`, no request per app) |
| `includeReviews` | boolean | `false` | One row per review, after its app |
| `maxReviewsPerApp` | integer | `30` | 1–10,000 reviews per app |
| `reviewSort` | select | `newest` | `newest` or `relevance` |
| `reviewRatings` | array | `[]` (all) | Only reviews with these stars, `"1"`–`"5"` |
| `maxAppsPerSource` | integer | `50` (prefill `20`) | 1–5,000 apps from each category, collection or developer, in listing order |
| `maxAppsTotal` | integer | `500` | Ceiling across the whole run; an app in two of your sources is returned, and billed, once |
| `maxConcurrency` | integer | `3` | App pages read in parallel; each worker keeps its own proxy session |
| `maxRunSecs` | integer | `240` | Whole-run wall-clock budget. When it runs out the Actor keeps what it has and files a free `timeout` row saying what was not read |
| `proxyConfiguration` | object | Apify datacenter | The App Store serves its pages to datacenter addresses (every capture was made through one). Switch to RESIDENTIAL if a run comes back `blocked` |

In mode `apps`, each named app's page is read and billed as an `app` row — except with `includeDetails: false` and `includeReviews: true`, which reads only the reviews.

### Output reference

Every row carries the same keys. `ok: true` is an app, review or category row; `ok: false` is a free diagnostic row.

| Field | What it is |
|---|---|
| `rowType` | `app`, `review`, `category` or `diagnostic` |
| `input` | The entry you supplied that led to this row |
| `handle`, `name`, `url`, `iconUrl` | The app (on category rows, `name` and `url` are the category's) |
| `categorySlug`, `collectionSlug`, `partnerSlug` | The listing the app came from; `partnerSlug` is also filled from the app page |
| `rank`, `position`, `section`, `sectionSlug` | 1-based order in the source (each app once), position in its section, the section heading and identifier |
| `rating`, `reviewCount`, `ratingBreakdown` | Average stars and review count; per-star counts from the app page. On review rows `rating` is the review's own stars |
| `pricingSummary`, `pricingPlans` | The store's pricing label; every plan `{ name, price, currency, period, priceText, trialDays, notes, features[] }` |
| `builtForShopify`, `summary`, `detailsRead` | The badge, the one-line pitch, and whether the app page was read |
| `tagline`, `description`, `highlights`, `launchedAt` | The app page's headline, full description, bullet points and launch date |
| `developerName`, `developerUrl`, `developerCountry`, `websiteUrl`, `supportEmail` | The developer's business name, App Store page, address country code, website and role support mailbox |
| `privacyPolicyUrl`, `faqUrl`, `documentationUrl`, `tutorialUrl`, `changelogUrl`, `demoStoreUrl` | The listing's resource links (`utm_` tags removed) |
| `languages`, `worksWith`, `categories`, `categorySlugs` | Languages, named integrations, and the app's own categories (names and slugs) |
| `screenshotCount`, `videoUrl` | Gallery size and the promotional video embed |
| `appHandle`, `reviewId`, `reviewedAt`, `storeName`, `country`, `usageDuration`, `body`, `developerReply`, `developerReplyAt`, `isEdited` | On review rows |
| `slug`, `parentSlug`, `appCount` | On category rows (`appCount` when the page shows one); `description` and `section` too |
| `ok`, `error`, `errorType` | Whether this row is data, and if not, why not |
| `scrapedAt`, `source`, `sourceUrl` | When, `apps.shopify.com`, and the exact page the row was read from |

`errorType` on a diagnostic row is one of:

| Value | Meaning | Charged? |
|---|---|---|
| `not-found` | The store answered 404 for the category, collection, developer or app — or the app's URL now redirects somewhere that is not an app | No |
| `blocked` | HTTP 403, 429, a challenge page or a refusing proxy tunnel, from two different proxy exits. Rows already returned are kept | No |
| `timeout` | A page did not answer in time twice, or the run's `maxRunSecs` ran out (the row says what was not read). Rows already returned are kept | No |
| `parse-failed` | The page answered but no longer reads the way it did — the row quotes up to 200 characters of what it said | No |
| `robots-disallowed` | robots.txt disallows the URL, so it was not requested | No |
| `no-apps` | The listing shows no apps, or none matched your `keyword` | No |
| `http` | Any other upstream error (5xx after a retry, a connection that could not be made) | No |
| `invalid-input` | The entry was not a slug, handle or apps.shopify.com URL | No |

An app page that cannot be read in a listing walk still delivers the app's card — as a listing-only row, billed as `app-listing` — next to a free row saying why; an app that is gone (`not-found`) delivers nothing.

### Pricing

**$2 per 1,000 apps with their full listing.** Pay-per-event, with the proxy already inside the number — there is no separate proxy line on your bill.

| Event | What triggers it | FREE | Starter | Scale | Business |
|---|---|---|---|---|---|
| **App** *(primary)* | One app row whose app page was read (`includeDetails`, or mode `apps`) | $0.002 | $0.002 | $0.0016 | $0.0012 |
| App (listing only) | One app row from its listing card only | $0.0005 | $0.0005 | $0.0004 | $0.0003 |
| Review | One review row | $0.0005 | $0.0005 | $0.0004 | $0.0003 |
| Run started | Once per run, after the first paid row | $0.001 | $0.001 | $0.001 | $0.001 |

**Worked examples.** The prefill — 20 apps with details — is **$0.041**. The example task, 25 email-marketing apps with their 10 newest reviews each: 25 × $0.002 + 250 × $0.0005 + $0.001 = **$0.176**. A cheap ranking snapshot of 500 apps across categories with `includeDetails: false`: 500 × $0.0005 + $0.001 = **$0.251**.

**What you are never charged for:** category rows, a typo'd slug or handle, a category or app that does not exist, a blocked page, a page the parser could not read, a URL robots.txt disallows, apps your keyword filtered out, and anything the run did not reach before `maxRunSecs`. A run whose entries were usable but produced nothing finishes **SUCCEEDED with zero results**, a status message that says so and points at the diagnostic rows, and bills **nothing at all**, start fee included. It finishes **FAILED** only when there was nothing usable to attempt, or the Actor itself hit an error.

Set `ACTOR_MAX_TOTAL_CHARGE_USD` on a run and the Actor stops fetching once the ceiling is in sight, rather than handing you rows it cannot bill. It finishes SUCCEEDED with the ceiling named in its status message, and everything already delivered is yours.

### Limits, and the ones that might bite

**The upstream format may change.** This Actor reads HTML pages, not an API. It prefers the most stable markers the pages offer — the JSON-LD block, data attributes, accessibility labels — but when the store redesigns a page, rows stop arriving and you get free `parse-failed` rows quoting what the page said, rather than quietly wrong data. A run that returns nothing bills nothing.

**What you see is what an anonymous US visitor sees.** Prices are in the currency the store bills in (USD on every captured page). The store personalises parts of its pages by the visitor's location; the Actor only returns fields that describe the app itself.

**Category landing pages are curated.** A top-level or mid-level category page shows featured sections, not every app. When you ask for more apps than it shows, the Actor tries the category's full list (`/categories/<slug>/all`) once, and stops there if the store has none. The order is the store's own; `rank` is the order this run saw the apps in.

**No search.** robots.txt disallows the store's search for crawlers, so there is no keyword search; `keyword` filters what a listing returns.

**Reviews are paged at ten.** 3,000 reviews is 300 requests; bound it with `maxReviewsPerApp` and `maxRunSecs`.

**Only what is published.** No login, no merchant data, no developer dashboards — the public listing and nothing else.

### Use it from an AI agent, or from code

One JSON object in, one flat array out — the shape agent runtimes want. The Actor runs with **limited permissions**, uses **pay-per-event** pricing and never enters Standby, so it works over the Apify MCP server and with x402 agentic payments. The **Integrations** tab pushes results to Slack, a webhook, Zapier, Make, Google Sheets, Snowflake or BigQuery.

```bash
curl -X POST "https://api.apify.com/v2/acts/insight.solutions~shopify-app-store-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode":"apps","apps":["judgeme","klaviyo-email-marketing"],"includeReviews":true,"maxReviewsPerApp":10,"reviewRatings":["1","2"]}'
```

```python
## pip install apify-client
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("insight.solutions/shopify-app-store-api").call(run_input={
    "mode": "category",
    "categories": ["marketing-and-conversion-marketing-email-marketing"],
    "includeDetails": True,
    "maxAppsPerSource": 50,
})

for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["rowType"] == "diagnostic":
        print("skipped:", row["input"], row["errorType"], row["error"])
        continue
    if row["rowType"] != "app":
        continue
    cheapest = min((p["price"] for p in row["pricingPlans"] or [] if p["price"]), default=None)
    print(f'{row["rank"]:>3}. {row["name"]}  {row["rating"]}★ ({row["reviewCount"]})  from ${cheapest}/mo  BFS={row["builtForShopify"]}')
```

**Building an app with Lovable?** Apify's Lovable connector runs any Actor from inside a Lovable project with your Apify token. Connect Apify in Lovable once, then ask it: *"Use Apify to run insight.solutions/shopify-app-store-api for a category I choose and build a competitor tracker around the apps, ratings and pricing plans it returns."* At the default settings a run finishes well inside Lovable's 300-second synchronous limit, and every result is one JSON object per row, so the generated app needs no extra parsing. Usage bills to the Apify account whose token is connected.

### FAQ

**Do I need an API key or a Shopify account?**
No. Every page this Actor reads is served to any visitor without logging in.

**Why is there no search?**
The App Store's robots.txt disallows every URL containing `q=` — its search — for all crawlers, and this Actor honours robots.txt. Use a category, collection or developer, and `keyword` to narrow what they return.

**How do I find a category's slug?**
Run mode `categories` (free) for the top-level ones and the store's "Top categories"; put a slug back into `categories` in the same mode to list its subcategories. Or copy it from the store's address bar: `apps.shopify.com/categories/<slug>`. An app row's `categorySlugs` also lists the categories that app is in.

**Why did a category return fewer apps than `maxAppsPerSource`?**
Some category pages are curated landing pages with a few featured sections. The Actor then tries the category's full list once; if the store has none for that category, the landing page was everything there is to read.

**Are reviewers' names included?**
No. Reviews on the App Store are signed by the merchant's store, and `storeName` is that business name. A store name that reads like one person's name (a common first name and a surname, with no trade word) is withheld as `null`, and so is a developer account that reads like a person's name. Review and reply texts are returned as published and can mention people the way any public text can.

**What is the difference between `app` and `app-listing`?**
An `app` row means the app's own page was read: plans, description, developer, languages, categories, breakdown. An `app-listing` row is what the category or collection card shows — name, rating, review count, pricing label, badge — for a quarter of the price and no request per app.

**What happens if one app fails?**
The others still run; the failed one gets a free diagnostic row (and, in a listing walk, its card as a listing-only row unless the app is gone). If *everything* fails, the run still finishes `SUCCEEDED` with zero results, a status message that says so, and you are billed nothing.

**Which proxy should I use?**
The default datacenter proxy; every capture this Actor was built on came through it. If you see `blocked` rows, re-run with the RESIDENTIAL group.

### Legal and data-protection notes

- **Public pages only, robots.txt honoured.** Every request is to a page the App Store serves to anonymous visitors; robots.txt is read at the start of each run and every URL is checked against it. The store's search (`q=`), `/internal/` and `/services/` are never requested.
- **No personal data by design.** Reviews are attributed to the reviewing store, a business. Store names and developer names that read like a person's name are withheld; a support address is returned only when it is a role mailbox (`support@`, `help@`, …); the developer's street address is never returned, only its country code. The Actor sends no cookies and never logs in.
- **Respect the store.** Requests are spaced 300–600 ms apart per worker, a refusal is retried exactly once from a different address, and `maxConcurrency` bounds the parallelism. Please do not defeat that by pointing many parallel runs at the store.
- **Reuse is a separate question.** Collecting ratings, prices and reviews for comparison, research and competitive analysis is ordinary; republishing developers' descriptions, screenshots or merchants' review texts wholesale is different — they belong to whoever wrote them.
- **Not affiliated with Shopify or with any app developer or merchant whose listing or review you retrieve.** All product names and trademarks belong to their respective owners and are used only to describe which public pages this Actor reads.

### Our other Actors

Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.

**Video, audio & social**

- [YouTube Transcript API](https://apify.com/insight.solutions/youtube-transcript-api) — captions as timed segments, text, SRT or VTT, with language fallback and translation.
- [YouTube Comments API](https://apify.com/insight.solutions/youtube-comments-api) — comments and replies with likes, pinned and hearted flags, newest or top sort.
- [YouTube Channel API](https://apify.com/insight.solutions/youtube-channel-api) — a channel's videos, Shorts and live streams, plus YouTube search.
- [Podcast Search, Episodes & Charts API](https://apify.com/insight.solutions/podcast-api) — Apple Podcasts search, charts and full episode feeds.
- [Bluesky Scraper](https://apify.com/insight.solutions/bluesky-scraper) — profiles, posts, followers and follows from the public AT Protocol API.
- [Telegram Channel Scraper](https://apify.com/insight.solutions/telegram-channel-scraper) — posts, views and channel stats from public Telegram channels.
- [Substack Scraper](https://apify.com/insight.solutions/substack-scraper) — posts with full free text, comments and publication profiles.
- [Hacker News API](https://apify.com/insight.solutions/hacker-news-api) — stories, comments, users, front page and a structured "Who is hiring?" parser from the official HN APIs.
- [GitHub Repos, Trending & Releases API](https://apify.com/insight.solutions/github-repos-api) — repository facts, trending lists, releases and search, no token needed for small runs.
- [Discourse Forum API](https://apify.com/insight.solutions/discourse-forum-api) — topics, posts and categories from any Discourse community via its own JSON endpoints, usernames only.

**News, documents & the web**

- [Google News Search, Topics & Real Article URLs](https://apify.com/insight.solutions/google-news-api) — news search and topic feeds with the publisher's real URL decoded.
- [Website to Markdown — Content Extractor for LLMs & RAG](https://apify.com/insight.solutions/website-content-extractor) — any site as clean Markdown, text and heading-aware chunks.
- [WordPress Posts & Pages API](https://apify.com/insight.solutions/wordpress-posts-api) — posts and pages from any WordPress site as clean text or Markdown, with categories, tags and images.
- [Website Metadata API](https://apify.com/insight.solutions/website-metadata-api) — any URL's meta tags, Open Graph, Twitter cards, hreflang, feeds, JSON-LD and microdata, with normalised Product, Article, Event and FAQ entities.
- [Subdomain Finder API](https://apify.com/insight.solutions/subdomain-finder-api) — every subdomain of a domain from certificate-transparency logs, resolved over DNS, with an optional live HTTP check.
- [Internet Archive API](https://apify.com/insight.solutions/internet-archive-api) — archive.org search, item metadata, files and reviews.
- [Wayback Machine Toolkit](https://apify.com/insight.solutions/wayback-toolkit) — archived URL inventories, snapshots and text diffs between dates.
- [Website Technology Detector](https://apify.com/insight.solutions/website-tech-detector) — the tech stack behind any site, with the evidence for each detection.
- [Domain Intelligence API](https://apify.com/insight.solutions/domain-intelligence-api) — DNS, RDAP registration, TLS certificate and HTTP facts in one row per domain.
- [SEO Page Audit](https://apify.com/insight.solutions/seo-page-audit) — sitemap crawl with on-page checks, structured data and broken-link reports.
- [Keyword Suggestions API](https://apify.com/insight.solutions/keyword-suggestions-api) — Google, YouTube, Bing, Amazon and eBay autocomplete with alphabet and question expansions.
- [Website Contact Extractor](https://apify.com/insight.solutions/website-contact-extractor) — emails, phone numbers and social profiles from any list of websites.
- [Web Search Results API](https://apify.com/insight.solutions/web-search-api) — Bing and DuckDuckGo organic results with snippets, no key, no browser.
- [Company Enrichment API](https://apify.com/insight.solutions/company-enrichment-api) — a domain in, a company profile out: firmographics, contacts, tech stack, DNS and hiring signal.
- [Company Dossier API](https://apify.com/insight.solutions/company-dossier-api) — one company in, twelve sections out: profile, tech, contacts, DNS, open roles, news, SEC filings, federal awards, recalls, YC batch and apps.
- [Press Releases API](https://apify.com/insight.solutions/press-releases-api) — GlobeNewswire and PR Newswire releases plus any newsroom feed, by keyword, company, ticker or subject.
- [Federal Register API](https://apify.com/insight.solutions/federal-register-api) — rules, proposed rules, notices and the Public Inspection desk with dockets, comment deadlines and CFR references.
- [Academic Papers Search API](https://apify.com/insight.solutions/academic-papers-api) — OpenAlex, Crossref, arXiv and PubMed in one row per paper: abstract, citations, open-access PDF, authors and venue.
- [RSS & Atom Feed Monitor](https://apify.com/insight.solutions/rss-feed-monitor) — any RSS, Atom or JSON feed (or an OPML file) in, only the new items out, with keyword filters and a webhook.
- [Website Change Monitor](https://apify.com/insight.solutions/website-change-monitor) — watch any pages, diff the text between runs, get change rows with added/removed lines, keyword alerts and a webhook.
- [Wikipedia & Wikidata API](https://apify.com/insight.solutions/wikipedia-api) — article text, search, daily pageviews and Wikidata entity facts, any language edition.

**Business, finance & jobs**

- [Congress & Insider Trades API](https://apify.com/insight.solutions/congress-insider-trades-api) — STOCK Act periodic transaction reports and SEC Form 4 insider trades in one schema.
- [Federal Contracts, Grants & Lobbying API](https://apify.com/insight.solutions/federal-contracts-grants-api) — SAM.gov opportunities, USAspending awards, Grants.gov notices and Senate lobbying filings in one schema.
- [SEC EDGAR API](https://apify.com/insight.solutions/sec-edgar-api) — filings, XBRL financials and full-text search by ticker or CIK.
- [Clinical Trials & FDA API](https://apify.com/insight.solutions/clinical-trials-fda-api) — ClinicalTrials.gov studies plus openFDA recalls, labels, approvals, 510(k)s and adverse-event reports.
- [Product & Vehicle Recalls API](https://apify.com/insight.solutions/product-recalls-api) — CPSC, NHTSA, FDA and USDA recalls, vehicle complaints and ratings, plus a VIN decoder.
- [Y Combinator Companies, Batches & Founders](https://apify.com/insight.solutions/yc-companies-directory) — the YC directory with founders and social links, filterable by batch, industry and hiring status.
- [Career Site Jobs API](https://apify.com/insight.solutions/ats-jobs-api) — jobs straight from Greenhouse, Lever, Ashby, Workable and 10+ other ATS career sites.
- [Workday Jobs API](https://apify.com/insight.solutions/workday-jobs-api) — every posting on any Workday career site, with facets, search, posted dates and full descriptions.
- [New Job Postings Monitor](https://apify.com/insight.solutions/job-postings-monitor) — new, closed and changed postings on the career sites you watch.
- [Hiring Signals API — Open Roles & Hiring Surge by Company](https://apify.com/insight.solutions/hiring-signals-api) — one row per company per run: open roles, what opened and closed, department and seniority breakdowns, and a hiring-surge flag.
- [Remote Jobs API](https://apify.com/insight.solutions/remote-jobs-api) — RemoteOK, Remotive, We Work Remotely, Himalayas, Jobicy and more in one schema, deduplicated.
- [Shopify Products API](https://apify.com/insight.solutions/shopify-products-api) — any Shopify store's catalogue, variants, prices and stock signals.
- [WooCommerce Products API](https://apify.com/insight.solutions/woocommerce-products-api) — any WooCommerce store's catalogue, prices, variants and stock through its public Store API.
- [Luma Events API](https://apify.com/insight.solutions/luma-events-api) — upcoming Luma events by city, category or calendar: dates, venue, price, capacity and organiser calendar, no host names.
- [Shopify Store Monitor](https://apify.com/insight.solutions/shopify-store-monitor) — price drops, sales, restocks, sell-outs and new products on any Shopify store, one row per change.
- [Public Tenders API](https://apify.com/insight.solutions/public-tenders-api) — EU TED, UK Find a Tender and Contracts Finder notices by keyword, CPV code, country, stage and deadline.
- [Nonprofit & IRS 990 Lookup API](https://apify.com/insight.solutions/nonprofit-990-api) — search US nonprofits and get EIN, NTEE code and multi-year Form 990 financials.
- [OpenStreetMap Places API](https://apify.com/insight.solutions/osm-places-api) — businesses and points of interest by category and area from OpenStreetMap: name, address, coordinates, website, phone, opening hours.

**Apps & games**

- [App Store & Google Play Reviews API](https://apify.com/insight.solutions/app-reviews-api) — reviews from both stores with ratings, versions and developer replies.
- [App Store Top Charts & App Search API](https://apify.com/insight.solutions/app-charts-api) — Apple top charts by country and genre, plus app search and details.
- [App Store Keyword Rank Tracker](https://apify.com/insight.solutions/app-store-keyword-rank-tracker) — where any app ranks for any keyword on the App Store and Google Play, with rank changes and ASO suggestions.
- [Steam Reviews API](https://apify.com/insight.solutions/steam-reviews-api) — Steam reviews with playtime, helpfulness and game details.
- [Steam Game Data API](https://apify.com/insight.solutions/steam-store-stats-api) — prices, tags, review scores, live player counts and top charts.
- [Sports Scores & Schedules API](https://apify.com/insight.solutions/sports-scores-api) — scores, schedules, standings, teams and headlines for the NFL, NBA, MLB, NHL, soccer and more, no key.
- [App Store Monitor](https://apify.com/insight.solutions/app-store-monitor) — App Store and Google Play listings watched between runs: new versions with release notes, price, rating and listing changes, one row per change.

# Actor input Schema

## `mode` (type: `string`):

`category`: the apps a category lists (from `categories`). `collection`: a collection such as `built-for-shopify` (from `collections`). `partner`: every app of a developer (from `partners`). `apps`: the apps you name (from `apps`). `categories`: the category tree, free — the store's navigation, or the subcategories of the slugs in `categories`. No search mode: robots.txt disallows the store's search to crawlers, so `keyword` filters listings instead.

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

Category slugs (`marketing-and-conversion-marketing-email-marketing`) or category URLs (`https://apps.shopify.com/categories/…`); tracking parameters and `?page=` are ignored. Run mode `categories` once to get every slug. Read in mode `category`, and in mode `categories` to list subcategories.

## `collections` (type: `array`):

Collection slugs (`built-for-shopify`) or URLs — `https://apps.shopify.com/collections/<slug>` or the `/app-groups/…` address it redirects to. Read in mode `collection`.

## `partners` (type: `array`):

Developer (partner) slugs (`klaviyo`) or URLs (`https://apps.shopify.com/partners/klaviyo`). Every app the developer lists is returned. Read in mode `partner`.

## `apps` (type: `array`):

App handles (`judgeme`) or app URLs (`https://apps.shopify.com/klaviyo-email-marketing`, its `/reviews` tab works too). Read in mode `apps`: each app's page is read and billed as a full app row — or, with `includeDetails` off and `includeReviews` on, only its reviews are read.

## `keyword` (type: `string`):

Keep only apps whose name or one-line summary contains this phrase (case-insensitive). It filters the apps the listing pages return — it is not the store's search, which robots.txt disallows — so a filtered run reads the same listing pages and skips the app pages it does not need. Apps that do not match are not billed. Ignored in mode `apps`.

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

On: one request per app for its full listing — description, highlights, every pricing plan with features and trial days, launch date, developer and website, support address, languages, integrations, categories, screenshots and the star-rating breakdown — billed as an `app` row. Off: only what the category or collection card shows (name, rating, review count, pricing summary, Built for Shopify badge), billed as the cheaper `app-listing` row, with no extra request per app.

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

One extra row per merchant review (star rating, date, the reviewing store's name, country, time using the app, text, developer reply and its date), billed per review. Ten reviews per request.

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

The most reviews to return for each app, in `reviewSort` order.

## `reviewSort` (type: `string`):

The two orders the store offers: `newest` (date, newest first) or `relevance` (the store's default, "Most relevant").

## `reviewRatings` (type: `array`):

Only reviews with these star ratings, e.g. `["1", "2"]` for complaints. The store filters (`ratings[]=`) and the Actor checks again. Empty = every rating.

## `maxAppsPerSource` (type: `integer`):

The most apps to take from each source, in the order the store lists them. A category landing page that shows fewer apps than this is followed by the category's full list when the store has one.

## `maxAppsTotal` (type: `integer`):

A ceiling across all sources. An app listed under two of your sources is returned, and billed, once.

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

How many app pages (and their review pages) are read at once. Each worker keeps its own proxy session; requests from one worker are spaced 300–600 ms apart.

## `maxRunSecs` (type: `integer`):

Whole-run wall-clock budget. When it runs out the Actor keeps every row it already returned and files a free `timeout` row saying what was not read.

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

Apify datacenter proxy by default — the App Store serves its public pages to it. Switch to the RESIDENTIAL group if a run comes back with `blocked` rows.

## Actor input object example

```json
{
  "mode": "category",
  "categories": [
    "marketing-and-conversion-marketing-email-marketing",
    "https://apps.shopify.com/categories/marketing-and-conversion-social-trust-product-reviews"
  ],
  "collections": [
    "built-for-shopify"
  ],
  "partners": [
    "klaviyo",
    "https://apps.shopify.com/partners/judge-me"
  ],
  "apps": [
    "klaviyo-email-marketing",
    "judgeme"
  ],
  "keyword": "",
  "includeDetails": true,
  "includeReviews": false,
  "maxReviewsPerApp": 30,
  "reviewSort": "newest",
  "reviewRatings": [],
  "maxAppsPerSource": 20,
  "maxAppsTotal": 500,
  "maxConcurrency": 3,
  "maxRunSecs": 240,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per app, plus one per review when you ask for them, or one per category in categories mode. Anything that could not be read gets a free diagnostic row saying why. Delivered as JSON items in the default dataset.

# 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 = {
    "mode": "category",
    "categories": [
        "marketing-and-conversion-marketing"
    ],
    "collections": [
        "built-for-shopify"
    ],
    "partners": [
        "klaviyo"
    ],
    "apps": [
        "judgeme"
    ],
    "keyword": "",
    "includeDetails": true,
    "includeReviews": false,
    "maxAppsPerSource": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("insight.solutions/shopify-app-store-api").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 = {
    "mode": "category",
    "categories": ["marketing-and-conversion-marketing"],
    "collections": ["built-for-shopify"],
    "partners": ["klaviyo"],
    "apps": ["judgeme"],
    "keyword": "",
    "includeDetails": True,
    "includeReviews": False,
    "maxAppsPerSource": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("insight.solutions/shopify-app-store-api").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 '{
  "mode": "category",
  "categories": [
    "marketing-and-conversion-marketing"
  ],
  "collections": [
    "built-for-shopify"
  ],
  "partners": [
    "klaviyo"
  ],
  "apps": [
    "judgeme"
  ],
  "keyword": "",
  "includeDetails": true,
  "includeReviews": false,
  "maxAppsPerSource": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call insight.solutions/shopify-app-store-api --silent --output-dataset

```

## MCP server setup

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

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/b94I33griefsV3CHu/builds/RMGH68DdT9F7Qs3An/openapi.json
