# Shopify App Store Scraper (`devilscrapes/shopify-app-store-scraper`) Actor

Scrape Shopify App Store listings for pricing tiers, ratings, review counts, launch dates, categories, and integrations. Fetch specific app handles or discover up to 40 apps per category. Built for Shopify app developers and DTC agencies doing competitive research.

- **URL**: https://apify.com/devilscrapes/shopify-app-store-scraper.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:** Lead generation, Marketing, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 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.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

<div align="center">
  <img src=".actor/icon.svg" width="160" alt="Devil Scrapes mark" />

## Shopify App Store Scraper

**💰 $2.02 / 1 000 results**  ·  pay only for results  ·  no credit card to try

*The devil's in the data — we go get it.* 😈

Scrape Shopify App Store listings for pricing tiers, ratings, review counts, launch dates, categories, and integrations. Fetch specific app handles or discover up to 40 apps per category. Built for Shopify app developers, DTC agencies, and market-intel analysts doing competitive research.

</div>

***

### 🎯 What this scrapes

`apps.shopify.com` has no public API for app-listing data — we read the app-card markup on category browse pages and the structured LD+JSON block on each app's detail page, so you get one clean row per app with pricing tiers, ratings, launch date, category, and integration tags without hand-scraping the Store yourself.

### 🔥 Features

- 🛡️ **We rotate browser fingerprints** — `curl-cffi` impersonation (Chrome / Firefox) so the target sees a real browser, not a Python client.
- 🔁 **We retry with exponential backoff** on `408 / 429 / 5xx`, honouring `Retry-After`, rotating impersonation profiles between attempts.
- 🧩 **Structured-first parsing** — we prefer each detail page's `application/ld+json` block for name, developer, icon, rating, and review count over brittle HTML text.
- 🧱 **A missing pricing section or malformed detail page never fails the run** — that row degrades gracefully (`pricing_plans: []`, `null` fields) instead of aborting.
- 🧊 **Clean, typed dataset rows** — Pydantic-validated, ISO-8601 timestamps, stable handles, JSON / CSV / Excel export straight from the Apify Console.
- 💰 **You pay only for results that land.** No data, no charge (only the small actor-start warm-up fee).

### 💡 Use cases

- **Competitive pricing research** — compare pricing tiers across Shopify apps in your category before setting your own.
- **DTC agency app-stack vetting** — pull ratings, reviews, and integration tags for the apps you're recommending to clients.
- **Market-intel tracking** — snapshot a category's top 40 apps to watch how the ecosystem shifts over time (scheduling for deltas is on you).
- **Integration audits** — check which platforms (Shopify Flow, POS, Checkout, etc.) an app actually works with before you commit.

### ⚙️ How to use it

1. Click **Try for free** at the top of the page.
2. Provide either **App handles** (specific apps you want) or **Category slugs** (top-40-per-category discovery) — or both.
3. Click **Start**. Output streams into the run's dataset.
4. Export from **Storage → Dataset** as JSON, CSV, or Excel — or fetch via the API.

### 📥 Input

| Field | Type | Required | Default | Notes |
|---|---|:--:|---|---|
| `appHandles` | `array<string>` | no\* | — | Bare handles (e.g. `klaviyo-email-marketing`) or full `apps.shopify.com` URLs, normalized to a handle. The primary, most reliable input mode. |
| `categorySlugs` | `array<string>` | no\* | — | Top-40-per-category discovery mode, e.g. `marketing-and-conversion`, `finding-products`, `orders-and-shipping`, `sales-channels`, `selling-products`, `store-design`, `store-management`. Each category caps at 40 apps — Shopify does not paginate this surface. |
| `maxItems` | `integer` | no | 100 | Hard cap on total dataset rows emitted this run, applied across both input modes combined. |
| `proxyConfiguration` | `object` | no | `{"useApifyProxy": true}` | Apify Proxy config. `apifyProxyGroups` is left unset (datacenter default) — no residential-proxy requirement observed for this target. |

\* At least one of `appHandles` / `categorySlugs` must be set. Both may be combined in one run.

#### Example input

```json
{
  "appHandles": [
    "klaviyo-email-marketing"
  ],
  "maxItems": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

### 📤 Output

Every row is one dataset item.

| Field | Type | Notes |
|---|---|---|
| `handle` | `string` | App's canonical URL handle. |
| `name` | `string` | App name. |
| `developer` | `string` | Developer/company name. |
| `url` | `string` | Canonical `https://apps.shopify.com/{handle}` URL. |
| `icon_url` | `['string', 'null']` | App icon URL. |
| `category` | `['string', 'null']` | Category name; null when not discoverable. |
| `pricing_plans` | `array` | Ordered list of `{name, price, additional_charges}` pricing tiers; empty list when none found. |
| `rating_value` | `['number', 'null']` | Aggregate rating (0-5); null if the app has no reviews. |
| `review_count` | `['integer', 'null']` | Aggregate review count; null under the same condition as `rating_value`. |
| `launched_date` | `['string', 'null']` | ISO-8601 launch date. |
| `works_with` | `array` | Integration/works-with tags; empty list when none found. |
| `install_count` | `['integer', 'null']` | Best-effort only — no such signal is exposed by Shopify on this surface. Ships `null`, never a fabricated proxy metric. |
| `discovered_via` | `string` | `app_handles` or `category_slugs` — whichever input mode produced this row. |
| `scraped_at` | `string` | ISO-8601 UTC timestamp when this row was recorded. |

#### Example output

```json
{
  "handle": "klaviyo-email-marketing",
  "name": "Klaviyo: Email Marketing & SMS",
  "developer": "Klaviyo",
  "url": "https://apps.shopify.com/klaviyo-email-marketing",
  "icon_url": "https://cdn.shopify.com/app-store/listing_images/example/icon/example.png",
  "category": "Marketing and conversion",
  "pricing_plans": [
    {"name": "Free plan", "price": "Free to install", "additional_charges": null},
    {"name": "Growth", "price": "$45/month", "additional_charges": "Additional email/SMS charges may apply."}
  ],
  "rating_value": 4.6,
  "review_count": 3812,
  "launched_date": "2019-05-15",
  "works_with": ["Shopify Flow", "Shopify POS", "Checkout"],
  "install_count": null,
  "discovered_via": "app_handles",
  "scraped_at": "2026-08-06T09:00:00+00:00"
}
```

### 💰 Pricing

Pay-Per-Event — you pay only when these events fire:

| Event | USD | What it is |
|---|---:|---|
| `actor-start` | $0.02 | One-off warm-up charge per run |
| `result-row` | $0.002 | Per app row pushed to the dataset |

Example: 1 000 results at the rates above ≈ **$2.02**. No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.

### 🚧 Limitations

Category discovery is capped at 40 apps per category — Shopify does not expose pagination on this surface, so `categorySlugs` is a top-40 discovery mode, not exhaustive category enumeration. Search-based discovery (`/search?q=...`) is not supported — that endpoint is client-side rendered. No install/merchant-count signal is exposed anywhere on the Store, so `install_count` always ships `null`. Each run is a point-in-time snapshot; historical price-change tracking across runs is on the buyer via scheduling. Individual review text/authors are out of scope — only the aggregate rating and review count.

### ❓ FAQ

**Do I need both `appHandles` and `categorySlugs`?**

No — either alone works. Provide `appHandles` for specific apps, `categorySlugs` for top-40-per-category discovery, or combine both in one run (results are deduplicated by handle).

**Why is `install_count` always null?**

Shopify doesn't expose a merchant/install-count signal anywhere on the App Store. We ship it `null` rather than invent a proxy metric.

**Can I enumerate an entire category beyond 40 apps?**

Not currently — Shopify's category pages return exactly 40 app cards with no working pagination parameter. This is a platform limitation, not a bug.

**Is `price` a parsed number?**

No — it's kept as raw text (e.g. `"$29.99/month"`, `"Free to install"`) because pricing tiers mix flat, trial-qualified, and usage-based phrasing that a single numeric field can't represent without losing information.

### 💬 Your feedback

Spotted a bug, hit a weird edge case, or need a new field? Open an
issue on the Actor's **Issues** tab on Apify Console — we ship
fixes weekly and we read every report.

***

<div align="center">

Built by **[Devil Scrapes](https://apify.com/DevilScrapes)** 😈 — a small fleet of
opinionated public-data Actors. Honest pricing, real engineering, zero fine print.

</div>

# Actor input Schema

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

Direct list of apps to fetch — bare handles (e.g. 'klaviyo-email-marketing-sms') or full apps.shopify.com URLs, normalized to a handle. This is the primary, most reliable input mode. At least one of App handles / Category slugs must be set.

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

Top-40-per-category discovery mode, e.g. 'marketing-and-conversion', 'finding-products', 'orders-and-shipping', 'sales-channels', 'selling-products', 'store-design', 'store-management'. Shopify does not paginate this surface — each category returns at most 40 apps, not an exhaustive enumeration. At least one of App handles / Category slugs must be set.

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

Hard cap on total dataset rows emitted this run, applied across both input modes combined — the priced dimension.

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

Apify Proxy config. apifyProxyGroups is left unset (datacenter default) — apps.shopify.com served all probe requests 200 OK with zero anti-bot friction observed during recon.

## Actor input object example

```json
{
  "appHandles": [
    "klaviyo-email-marketing"
  ],
  "maxItems": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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"
    ],
    "maxItems": 5,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/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"],
    "maxItems": 5,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/shopify-app-store-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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"
  ],
  "maxItems": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call devilscrapes/shopify-app-store-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=devilscrapes/shopify-app-store-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/S9U3l6XLVfN5lb5qq/builds/OfSVQDf5Cc7dtfiMV/openapi.json
