# pub.dev Package Rankings & Score Change Monitor (`automa-flow/pub-dev-package-rankings-monitor`) Actor

Export and monitor pub.dev package rankings for Dart and Flutter. Track downloads, likes and pub points with top-N snapshots and saved change history.

- **URL**: https://apify.com/automa-flow/pub-dev-package-rankings-monitor.md
- **Developed by:** [Vadim Bezrukov](https://apify.com/automa-flow) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 package 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?

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

## pub.dev Package Rankings & Score Change Monitor

Export pub.dev package rankings and track changes in Dart and Flutter package
downloads, likes and pub points. Compare libraries you maintain, follow competing
packages, or refresh a dashboard in Sheets, n8n or Make.

Start with the top 20 packages or supply a watchlist. A snapshot returns one
observation per checked package, a query status and a run summary. Monitor mode
stores and emits a baseline on the first successful run, then identifies rank,
score and composition changes on later runs.

The source is the [documented pub.dev JSON API](https://pub.dev/help/api).
Rank is the package's position in pub.dev's completion list, not a local sort by
downloads. Ranking data is cached for eight hours; this is not real-time data.

### Get your first result

```json
{"mode": "snapshot", "topN": 20}
```

With a healthy source containing at least 20 packages, this returns 20 package
observations marked `BASELINE`, one `query_status` and one `run_summary`.
Open the **Packages** Dataset view or export JSON/CSV. At FREE/BRONZE prices,
the example costs **$0.02005**. Set a maximum-charge budget of at least **$0.021**.

### Choose a workflow

| Workflow | Input | Result |
| --- | --- | --- |
| Export top pub.dev packages | `snapshot`, `topN: 20` | Official rank, 30-day downloads, likes and pub points |
| Monitor rank and score changes | `monitor`, `changesOnly`, stable namespace | Baseline first; changed, exited and returning packages later |
| Compare named Dart or Flutter packages | `watchlist: ["http", "uuid", "dio"]` | Only the selected packages, with their full-list ranks |

Prepared saved examples cover these workflows with distinct inputs, Dataset
views and spending limits. When available in the Actor's **Examples** section,
copy an example and replace its sample values.

#### Monitor daily or weekly

```json
{
  "mode": "monitor",
  "outputMode": "changesOnly",
  "stateNamespace": "top20",
  "topN": 20
}
```

Keep the same namespace and query on repeat runs. First-run `BASELINE` rows
are included with `changesOnly`. Later `UNCHANGED` packages are omitted; query
status and summary remain available. Snapshot mode does not read or write
monitoring history. Switching to monitor creates a new baseline.

#### Compare a watchlist

```json
{
  "mode": "snapshot",
  "watchlist": ["http", "uuid", "dio"],
  "includePackageMetadata": false
}
```

Use up to 50 Dart package names or `https://pub.dev/packages/{name}` URLs.
Duplicate names are checked once. A watchlist ignores `topN` for filtering:
a package may rank above that number. An existing package outside the ranking
list has `rank: null`; the score endpoint determines `NOT_FOUND` separately.
To monitor this watchlist, choose `monitor`, `changesOnly` and a stable namespace.
Optional metadata adds description, homepage and latest version; those fields
do not trigger change alerts.

### Output and change events

| Field | Meaning |
| --- | --- |
| `package`, `source_id`, `source_url` | Package name, stable identity and source link |
| `rank` | Official 1-based completion-list position; null when unranked or exited |
| `download_count_30d` | Source-reported 30-day downloads; null when not calculated |
| `like_count`, `granted_points`, `max_points` | Source-reported likes and pub points |
| `status`, `error` | Verification status and structured failure code/message |
| `change_type`, `changed_fields`, `previous_values` | Change relative to last-successful state |
| `scraped_at` | UTC time of this check |
| `ranking_observed_at`, `ranking_cache_hit` | Ranking fetch time and whether its cached list was reused |
| `schema_version`, `fingerprint`, `event_id` | Schema version, semantic fingerprint and monitor event ID |

pub.dev does not provide native ranking history through these endpoints.
Your history begins with your first successful monitor. `BASELINE` does not
mean that the package was published that day. Rows are append-only observations.

- `NEW`: first entry into the monitored composition after the baseline.
- `UPDATED`: downloads, likes, pub points or multiple tracked fields changed.
- `RANK_UP` / `RANK_DOWN`: only the rank changed.
- `EXITED`: a previously ranked package was absent in two successfully checked,
  separately fetched ranking lists. Reusing the same cache does not advance
  confirmation. This does not mean the package was unpublished.
- `REAPPEARED`: a previously exited package returned to the ranking window.
- `UNCHANGED`: no tracked field changed; omitted in `changesOnly`.

Dataset views are **Packages**, **Changes**, **Query checks** and **Run summary**.
The raw Dataset includes package, query-status and run-summary records; filter
by `record_type` in integrations. `RUN_SUMMARY` is also stored in the default KVS.

### Freshness and failures

The completion list is cached in an account-local Actor key-value store for
at least eight hours, as requested by pub.dev. Snapshots and monitors share
this cache. Scores are fetched on each check, so downloads or likes may change
while ranks are reused. Prefer daily or weekly ranking monitoring.

An expired cache is not used to hide a failed refresh. Failed checks never
replace good monitoring state or advance pending exits. Invalid score fields,
malformed ranking lists, HTML challenges and exhausted retries are failures.

| Status | Meaning and next action |
| --- | --- |
| `SUCCESS` | Consume the verified observation |
| `NOT_FOUND` | Score endpoint returned a non-HTML 404; check the package name |
| `NO_RESULTS` | Verified empty ranking for a top-N query; never a source failure |
| `PARTIAL` | Inspect query diagnostics and per-package failures; state is unchanged |
| `FAILED` | Inspect the source/protocol error; a fully failed query fails the run |
| `INVALID_INPUT` | Correct input before retrying; no source request was made |
| `NOT_PROCESSED` | Increase the run budget or request a smaller window |

An empty completion list does not skip watchlist score checks. Each failing
score request receives its own package status while other successful results
remain usable. `snapshot` plus `changesOnly` is rejected before fetching.

`maxPackageRows` bounds output. A window that does not fit is
`PARTIAL / OUTPUT_LIMIT`, never silently truncated. If a top-N window retains
under half its previous active packages, `PARTIAL / MASS_REMOVAL` keeps the
old state. Watchlists and top-1 are exempt from this guard.

### Pricing and spending limits

The **Pricing** tab is authoritative. Platform usage is included, not added
to the buyer's bill.

| Event | Charged for | FREE / BRONZE |
| --- | --- | ---: |
| `apify-actor-start` | One start event at supported 256-1024 MB memory settings | $0.00005 |
| `package-result` | Each successful snapshot package; in monitor, each delivered `NEW`, `UPDATED`, `RANK_*`, `EXITED` or `REAPPEARED` | $0.001 |
| `window-check` | One complete monitor check, including baseline, no changes or verified empty ranking | $0.01 |

Package results cost **$0.0008 on SILVER** and **$0.0006 on GOLD, PLATINUM
and DIAMOND**. Start and window-check prices are the same across tiers.
Monitor `BASELINE`/`UNCHANGED` rows, `NOT_FOUND`, retries and failed or partial
windows do not incur package-result fees. Failed/partial windows do not incur
window-check fees. The platform start event still applies. There is no
additional automatic Dataset-item fee.

| Example at FREE/BRONZE prices | Expected bill | Suggested run budget |
| --- | ---: | ---: |
| Snapshot of 3 successful watchlist packages | $0.00305 | $0.021 |
| Snapshot top-20 | $0.02005 | $0.021 or more |
| Snapshot top-200 | $0.20005 | $0.21 |
| First or unchanged top-20 monitor | $0.01005 | $0.05 |
| Top-20 monitor with 20 changed rows | $0.03005 | $0.05 |
| 30 daily unchanged monitor checks | $0.30150 | Budget applies separately to each run |

The minimum **budget** is $0.021, not a minimum charge. A $0.05 snapshot budget
fits 49 successful packages, not 50, because the start event also counts.
Saved examples allow $0.21 for top-N snapshots, $0.06 for watchlists and $0.50
for monitors. These ceilings cover their supported input ranges and are not
automatically charged. A top-200 monitor may include up to 400 billable package
rows with confirmed exits, for a maximum $0.41005 at FREE/BRONZE prices.

If the entire window cannot be delivered and charged within the remaining
budget, monitoring state stays unchanged. After interrupted delivery,
resurrection does not replay charges. Inspect the previous run's partial
output and start a new run for a fresh observation.

### Automate with n8n, Make or the Apify API

1. Schedule the monitor input daily or weekly in Apify.
2. Add an `ACTOR.RUN.SUCCEEDED` webhook for your n8n or Make endpoint.
3. Read `resource.defaultDatasetId` from its payload, then retrieve
   `GET https://api.apify.com/v2/datasets/{datasetId}/items` with your own
   authorization header.
4. Check `query_status` and `run_summary` before alerting on successful
   `package_observation` rows with the desired `change_type` values.
5. Handle `ACTOR.RUN.FAILED` separately so source outages reach your error path.

Schedules and webhooks are configured in your account. To run directly, send
input JSON to `POST https://api.apify.com/v2/acts/automa-flow~pub-dev-package-rankings-monitor/runs`
with your own authorization header. Never put tokens in shared inputs or URLs.

For authenticated agents, the direct MCP endpoint is
`https://mcp.apify.com?tools=automa-flow/pub-dev-package-rankings-monitor`.
Example: "Check my pub.dev top-20 monitor and return changed packages plus the
query status." Access depends on the Actor's publication/access state and your
account. MCP discovery and autonomous payment are separate; agentic payment
readiness is not claimed.

### Scope and limitations

- Top-N is limited to 200; watchlists to 50. Completion-list membership is
  source-controlled and does not include every published Dart package.
- Use sequential runs per namespace. Concurrent monitor writers are unsupported.
- EXITED tombstones are retained for 180 days, at most 20,000 per query.
  Returns after pruning may be `NEW`.
- Optional metadata does not trigger changes. Downloads do not establish package
  quality, security, unique users or production adoption.
- The public pub.dev API is free to call directly. This Actor adds Apify delivery,
  bounded batches, explicit statuses and saved monitoring state.
- This Actor is independent of pub.dev, Dart and Flutter. It uses public APIs,
  collects no publisher emails and bypasses no access controls. HTML
  `packages?q=` and undocumented `/api/search` are not used.

For support, provide the run ID, package/query and error code, never your token.

# Actor input Schema

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

Get current rankings returns every selected package and writes no history. Monitor changes compares this successful run with the last successful run of the same query in the same state namespace. Ranking lists are cached for eight hours; scores are fetched on each check. Prefer daily or weekly monitors.

## `outputMode` (type: `string`):

All packages returns every current row. Changes only omits UNCHANGED rows. Snapshot plus changesOnly is rejected before any pub.dev request.

## `stateNamespace` (type: `string`):

Isolates monitor history. Use a stable name per watch, for example top20. Letters, numbers, '\_' and '-', 1-64 characters. Snapshot mode ignores it.

## `topN` (type: `integer`):

How many ranked packages to keep when watchlist is empty. 1-200, default 20. Prefix of official completion-data order. Ignored for filtering when watchlist is set; rank still comes from the full list. At FREE/BRONZE prices, snapshot top-200 needs a budget of at least $0.20005 including start.

## `watchlist` (type: `array`):

Optional Dart package names or https://pub.dev/packages/{name} URLs, 0-50. Empty means use topN. A name missing from completion-data is unranked, not NOT\_FOUND. A non-HTML HTTP 404 on the score endpoint is item-level NOT\_FOUND. Duplicates keep the first name. A 50-package snapshot needs a FREE/BRONZE budget of at least $0.05005 including start.

## `includePackageMetadata` (type: `boolean`):

If true, fetch each selected package's /api/packages/{name} for description, homepage and latest version. Default off. Never dumps all 20 000 names. Never collects publisher emails.

## `maxPackageRows` (type: `integer`):

Cap on delivered package\_observation rows. Default 2000 so a topN of 200 plus EXITED extras can fit. Status rows are free. If the window does not fit, the run is PARTIAL/OUTPUT\_LIMIT and previous state is kept.

## Actor input object example

```json
{
  "mode": "snapshot",
  "outputMode": "all",
  "stateNamespace": "default",
  "topN": 20,
  "includePackageMetadata": false,
  "maxPackageRows": 2000
}
```

# Actor output Schema

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

No description

## `runSummary` (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 = {
    "mode": "snapshot",
    "topN": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automa-flow/pub-dev-package-rankings-monitor").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": "snapshot",
    "topN": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automa-flow/pub-dev-package-rankings-monitor").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": "snapshot",
  "topN": 20
}' |
apify call automa-flow/pub-dev-package-rankings-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automa-flow/pub-dev-package-rankings-monitor"
        }
    }
}
```

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/69gTAUcUXASU1anca/builds/N9jfAQ5qjtUO605et/openapi.json
