# Apify Store Analytics Scraper (`pradio/store-intel`) Actor

Scrape any niche of the Apify Store and see who already built what you are about to build. Get 30-day user counts, run totals, failure rates, review ratings, review counts, pricing model and maintenance notices for every matching Actor. Unreviewed Actors show as unrated, never as badly rated.

- **URL**: https://apify.com/pradio/store-intel.md
- **Developed by:** [E A](https://apify.com/pradio) (community)
- **Categories:** Agents, AI, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 listing analyses

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?

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

## Apify Store Analytics Scraper

See the niche before you build into it. Search any corner of the Apify Store and get
**real 30-day usage, honest ratings, failure rates and saturation signals** for every
matching Actor — in one run, from one unauthenticated public endpoint.

Built for Actor developers deciding what to build next, and for anyone who wants to know
who actually dominates a category.

### How do I use Apify Store Analytics Scraper?

Ten seconds, and you need no account beyond this one.

Paste this as the input, or press Start with the defaults — every field has a working one.

```json
{
  "search": "instagram",
  "limit": 50,
  "minReviewsForRating": 3,
  "onlyWeak": false
}
```

You get one row per relevant Actor. Here is a real one, from a real run:

```json
{
  "name": "apify/instagram-scraper",
  "title": "Instagram Scraper",
  "url": "https://apify.com/apify/instagram-scraper",
  "users30d": 39971,
  "runs30d": 15864030,
  "failureRate": 0.0001621277821587579,
  "rating": 4.715251824679979,
  "reviewCount": 558,
  "ratingState": "value",
  "pricingModel": "PAY_PER_EVENT",
  "notice": "NONE",
  "weak": false,
  "weakReasons": []
}
```

That is the market leader. This is what a weakness signal looks like, from the same run:

```json
{
  "name": "apify/instagram-reel-scraper",
  "users30d": 10060,
  "rating": 3.846152302424789,
  "reviewCount": 99,
  "ratingState": "value",
  "weak": true,
  "weakReasons": ["rating 3.85 over 99 reviews"]
}
```

Ten thousand people a month use it and it is rated 3.85 across ninety-nine reviews. That
is a real audience being served badly — which is the only kind of gap worth building into.

### Three questions it answers

**"Is this niche taken?"** Sort the output by `users30d`. If one Actor holds most of the
usage and is rated above 4.5, the niche has a leader and you are picking a fight. If the
usage is spread across many mid-rated listings, nobody has won it yet.

**"Is the leader actually good?"** `weak` and `weakReasons` answer this and nothing else
in the Store does. A leader with a 3.8 rating over a hundred reviews is a leader by
inertia.

**"Am I about to build something nobody wants?"** A search that returns almost nothing is
not automatically an opening. Read `examined` on the exhaustion row: if fifty listings
were read and none matched, that is a thin market, and thin markets are usually thin for a
reason.

### The unrated trap

The Store API returns `actorReviewRating = 0` for Actors that have **never been
reviewed** — and 28% of the 1,617-listing catalogue has no reviews. A naive
`rating < 4.2` filter flags **46%** of listings as weak incumbents. Reading the field
correctly flags **13%**.

So this Actor reports `ratingState` explicitly: `value`, `unrated`, `too_few_reviews` or
`missing`. An Actor nobody has reviewed is reported as *unrated* — never as a bad one.

### Input

| Field | Default | Meaning |
|---|---|---|
| `search` | `instagram` | Free-text query |
| `limit` | `50` | Listings to fetch before relevance filtering |
| `minReviewsForRating` | `3` | Below this many reviews, rating is reported as `null` |
| `onlyWeak` | `false` | Return only listings with a genuine weakness signal |
| `weakRatingBelow` | `4.2` | A rating under this counts as a weakness signal |
| `minRunsForHealth` | `100` | Below this many runs, the failure rate is too thin to judge |
| `weakFailureRateAbove` | `0.167` | A failure rate above this counts as a weakness signal |

Every field has a working default, so a run with no input succeeds.

### Output

**Two row shapes share the dataset.** Check `result` to tell them apart.

A **listing row** — one per relevant Actor found:

| Field | Meaning |
|---|---|
| `name` | `username/actor-name` |
| `title` | display title |
| `url` | Store page |
| `users30d` | distinct users in the last 30 days |
| `runs30d` | total runs in the last 30 days, or `null` |
| `failureRate` | failed ÷ total, or `null` when the total is zero |
| `rating` | only when backed by enough reviews, else `null` |
| `reviewCount` | number of reviews, or `null` |
| `ratingState` | `value` · `unrated` · `too_few_reviews` · `missing` |
| `pricingModel` | e.g. `PAY_PER_EVENT` |
| `notice` | e.g. `UNDER_MAINTENANCE` |
| `weak` | whether any weakness signal fired |
| `weakReasons` | which ones, in words |
| `searchTerm` | the query that produced this row |
| `examined` | how many listings were fetched before relevance filtering |
| `relevant` | how many of them matched every query token |
| `discarded` | `examined` minus `relevant` |
| `capped` | `true` if the fetch stopped at your limit, so more may exist |
| `retrievedAt` | when these numbers were read — Store figures change daily |

An **exhaustion row** — when nothing relevant was found, you get a record that says so
instead of an empty dataset that could mean anything:

| Field | Meaning |
|---|---|
| `result` | `NO_RELEVANT_LISTINGS`, or `STOPPED_EARLY` if the charge limit cut the run short |
| `searchTerm` | the query that was run |
| `examined` | how many listings were read before concluding none matched |
| `relevant` | always `0` |
| `why` | why nothing matched |
| `interpretation` | how to read a zero result |
| `charged` | `false` — meaning no `listing-analysed` events. The `apify-actor-start` event still applies; see Pricing. |
| `pushed` | on a `STOPPED_EARLY` row, how many listings were already analysed and saved before the limit was reached |

```json
{
  "result": "NO_RELEVANT_LISTINGS",
  "searchTerm": "quantum ferret grooming",
  "examined": 50,
  "relevant": 0,
  "why": "no listing text contained every query token",
  "interpretation": "a zero here means nothing matched your wording, not that the market is empty - try a broader term before concluding anything",
  "charged": false
}
```

Absent data is reported as absent (`null`), never disguised as a zero — that rule governs
`rating`, `runs30d`, `failureRate` and `reviewCount`.

### Honest limits

- **Relevance is verified here, not by the API.** The Store `search` parameter does not
  filter by relevance — `github` and `goodreads` both return Instagram Scraper as the top
  result. Every query token must appear in the listing text; typically 27–49 of 50
  returned listings are discarded.
- **There is no last-modified field** in the Store API. `lastRunStartedAt` measures
  usage, not maintenance, so weakness is judged from run statistics instead.
- **No proxy required.** One unauthenticated request to a documented public endpoint.
- **No personal data** is collected.

### Pricing

Pay per event. There are exactly two, and these are the prices the platform charges:

| Event | Price | When |
|---|---|---|
| `listing-analysed` | **$0.005** | once per record, and only **after** that record is durably in your dataset |
| `apify-actor-start` | **$0.00005** | once per gigabyte of memory, when the run starts |

So a run that analyses 40 listings costs about **$0.20** — 40 x $0.005, plus a single
start event at $0.00005.

A run that finds nothing relevant charges **no** `listing-analysed` events at all. You pay
the start event and nothing else.

**You can cap what a run may spend.** Apify has a per-run *Limit total charge* setting
(`maxTotalChargeUsd`) in the run options — this Actor does not define it, the platform does,
and it applies to any pay-per-event Actor. Set it and the run stops when it is reached.

When that happens you do **not** silently get a short dataset. The run writes a
`STOPPED_EARLY` row naming how many listings it had already saved and how many relevant ones
it had found, so a run that was cut short can never be mistaken for a market that was small.
Raise the limit and re-run to see the rest.

`apify-actor-start` is Apify's own platform event, charged on every pay-per-event Actor
rather than added by this one. It buys your run five free seconds of compute, so it
usually saves more than it costs. **Memory is capped at 1 GB** in `actor.json`, and the
start event is priced per gigabyte allocated, so the cap holds it to a single event.

### How to read the numbers

| You see | It means | It does not mean |
|---|---|---|
| `rating: null`, `ratingState: "unrated"` | nobody has reviewed it | it is bad |
| `rating: null`, `ratingState: "too_few_reviews"` | fewer than `minReviewsForRating` reviews | it is bad |
| `failureRate: null` | no runs in the window, so the ratio has no denominator | it never fails |
| `runs30d: 0` with `users30d > 0` | people installed it and did not run it | it is broken |
| `weak: false` | no signal fired on the data available | it is good |

`weak: false` is the one worth dwelling on. It means nothing tripped a threshold, not that
the Actor is well made. The signals are what the Store publishes; a well-marketed Actor
with a bad output has no field that says so.

### Questions

**How current is this?** Live at the moment you run it. The Store API is queried directly;
nothing is cached between runs.

**Why does the count change between runs?** The catalogue changes, and the Store's own
ordering is not stable across pages. Two runs minutes apart can return the same listings in
a different order and occasionally a different count.

**Can I get every Actor in the Store?** Not in one run. `limit` caps how many listings are
fetched before relevance filtering, and the filter typically discards most of them. Run
several narrower searches rather than one wide one.

**Does it need a proxy or an account?** Neither. One unauthenticated request to a
documented public endpoint.

**What if my search returns nothing?** You get an exhaustion row rather than an empty
dataset, and it costs you no `listing-analysed` events — you pay only the start event, as
every run does. See the shape above.

### Where this fits with other Actors

It reads the Store; it does not read the web. Tools that pair with it:

- [Amazon Review Defect Finder](https://apify.com/pradio/amazon-defect-ledger) — the same
  approach applied to product reviews: it tells you which complaints are corroborated
  rather than which are loudest.
- [Apify Store Scraper](https://apify.com/gio21/apify-store-scraper) — if you want the raw
  Store catalogue rather than an adoption-and-quality reading of it.
- [Website Content Crawler](https://apify.com/apify/website-content-crawler) — for reading
  the pages behind the listings once you know which ones matter.

### Integrations

This is an ordinary Apify Actor, so everything the platform offers works with it: schedule
it, call it from the [Apify API](https://docs.apify.com/api/v2) or the JavaScript and
Python clients, wire it into Zapier, Make, n8n, Slack or a webhook, or reach it from an AI
agent over MCP. Output goes to a dataset you can export as JSON, CSV or Excel.

A weekly schedule is the shape most people want: markets move slowly, and every row is
stamped with `retrievedAt` so two runs can be compared honestly.

### Found a problem?

Report it on the [Issues tab](https://apify.com/pradio/store-intel/issues). A bug report
with the search term you used and the row that looked wrong is enough — the run id helps
and is not required.

Two things worth reporting that people usually do not: a listing this scored `weak` that you
know is good, and a listing it scored fine that you know is not. Both are threshold problems
rather than bugs, and thresholds only move when somebody says so.

### Unofficial

Not affiliated with or endorsed by Apify. It reads the same public catalogue endpoint any
visitor can.

# Actor input Schema

## `search` (type: `string`):

Free-text query, e.g. "instagram". Results are relevance-filtered: every token must appear in the listing text, because the Store search parameter alone does not filter by relevance.

## `limit` (type: `integer`):

How many Store listings to fetch before relevance filtering. Paginated automatically in pages of 100 — the Store sorts by GLOBAL popularity rather than relevance, so a relevant but small Actor can sit beyond the first page.

## `minReviewsForRating` (type: `integer`):

The Store returns rating 0 for UNRATED Actors. Below this many reviews the rating is reported as null, not as a low score.

## `onlyWeak` (type: `boolean`):

Return only listings showing a genuine weakness signal: low rating over enough reviews, high failure rate, or UNDER\_MAINTENANCE.

## `weakRatingBelow` (type: `number`):

MEASURED: 4.2 is the 25th percentile of rated listings across a 1,617-listing sample (2026-08-19). Only applied to listings with enough reviews — see minReviewsForRating.

## `minRunsForHealth` (type: `integer`):

Below this many runs a failure ratio is noise, not a signal, and the failure rate is reported as null rather than as a number. ASSERTED, not measured.

## `weakFailureRateAbove` (type: `number`):

MEASURED: 0.167 across the same sample (2026-08-19). Only applied when the listing has at least minRunsForHealth runs.

## Actor input object example

```json
{
  "search": "instagram",
  "limit": 100,
  "minReviewsForRating": 3,
  "onlyWeak": false,
  "weakRatingBelow": 4.2,
  "minRunsForHealth": 100,
  "weakFailureRateAbove": 0.167
}
```

# Actor output Schema

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

The analysed Store listings for this run.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("pradio/store-intel").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("pradio/store-intel").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 '{}' |
apify call pradio/store-intel --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pradio/store-intel"
        }
    }
}

```

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/RSGJ5NFNJ9RJCSySJ/builds/Fnay249Wgt4CF2KaX/openapi.json
