# Substack Leaderboard Tracker — Rankings Over Time (`rowsmith/substack-leaderboard-tracker`) Actor

Track Substack category leaderboards over time — Top, Paid & Rising boards for all 32 categories with rank deltas, new entries, dropouts and bestseller tiers. Export to Excel, CSV, or JSON.

- **URL**: https://apify.com/rowsmith/substack-leaderboard-tracker.md
- **Developed by:** [Pratyush Sharma](https://apify.com/rowsmith) (community)
- **Categories:** News, Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## Substack Leaderboard Tracker — Rankings Over Time

Snapshot scrapers give you a photo. **This gives you the movie.**

Track Substack's category leaderboards — **Top, Paid (bestsellers), and Rising** — across **all 32 categories**, with built-in run-to-run history: every row carries `prevRank`, `rankChange`, and `isNew`, and you can optionally capture **dropouts** (publications that fell off a board) for churn analysis.

- 🏆 **Three boards per category**: Top (overall), Paid (bestseller ranking), Rising (trending)
- 🗂 **All 32 Substack categories** — Technology, Business, Finance, Culture, U.S. Politics, Health, Science, Crypto, and more
- 🔁 **Rank deltas built in**: `prevRank`, `rankChange`, `isNew` on every row from your second run
- 📉 **Dropout detection** (optional): see exactly which newsletters fell off a leaderboard and when
- 💰 **Bestseller tiers & subscriber signals**: bestseller badge tier (100/1,000/10,000), paid-subscriber magnitude ("Thousands of paid subscribers"), rounded free-subscriber counts ("311K+")
- 🗃 **One continuous history table**: optionally append every run to a named dataset
- ⚡ **Fast & lightweight** — pure JSON API, no browser, up to 525 ranks per board
- 📤 **Export to Excel, CSV, JSON, or Parquet**, or pull via API

### Who uses leaderboard history?

- **Newsletter operators & ghostwriting agencies** — spot which niches and formats are climbing before they peak; track your own (or a client's) rank daily.
- **Sponsorship & advertising buyers** — a newsletter's *trajectory* (climbing Rising board, new bestseller badge) is the buy signal a single snapshot can't show.
- **Creator-economy analysts & VCs** — category-level churn and turnover rates, tracked from real rankings.
- **Competitive intelligence** — get alerted when a competitor enters the Paid board or overtakes you.

### How it works

1. Pick categories (or `all`), boards, and depth (up to 525 ranks per board).
2. Run once — you get today's full ranking table with subscriber signals.
3. **Schedule it daily** (Apify → Schedules → this Actor → `@daily`). From the second run every row includes rank-change deltas, and history compounds from the day you start — it cannot be backfilled later.

Data comes from Substack's public, login-free category endpoints. Rankings, names, and badge tiers are public information; no personal data, no logins, no paywalled content.

### Output example

```json
{
    "category": "Technology",
    "board": "Paid",
    "snapshotDate": "2026-08-19",
    "rank": 1,
    "name": "SemiAnalysis",
    "authorName": "Dylan Patel",
    "url": "https://newsletter.semianalysis.com",
    "bestsellerTier": 10000,
    "paidSubscriberTier": "Tens of thousands of paid subscribers",
    "freeSubscriberCount": 311000,
    "freeSubscriberCountDisplay": "311K+",
    "prevRank": 2,
    "rankChange": 1,
    "isNew": false,
    "status": "ranked"
}
```

`rankChange` is positive when a publication climbed. `isNew: true` marks entries that weren't on the board in your previous snapshot. With **Report dropped publications** enabled, you also get `status: "dropped"` records with the publication's last known rank.

### Category slugs

`technology` · `business` · `finance` · `culture` · `us-politics` · `world-politics` · `health-politics` · `news` · `food` · `sports` · `art` · `music` · `faith` · `climate` · `science` · `literature` · `fiction` · `health` · `design` · `travel` · `parenting` · `philosophy` · `comics` · `international` · `crypto` · `history` · `humor` · `education` · `film-and-tv` · `home-garden` · `fashionandbeauty` · `podcast` — or just enter `all`.

### FAQ

**How is this different from other Substack scrapers?**
Every other Substack actor returns a one-time snapshot (posts or a single leaderboard pull). This one is built for *time series*: it maintains state between runs, computes rank deltas and dropouts automatically, and can maintain one ever-growing history dataset.

**Are exact paid-subscriber counts included?**
Substack never publishes exact paid counts. You get what Substack shows publicly: bestseller badge tiers and order-of-magnitude labels — plus rounded free-subscriber counts.

**How many rows per run?**
`categories × boards × maxRank`. 5 categories × 2 boards × 100 ranks = 1,000 rows. You are charged per row.

**Is this legal?**
The Actor reads Substack's public, unauthenticated category endpoints — the same data shown to any logged-out visitor. It collects no personal data and accesses no paywalled content.

***

Built by [rowsmith](https://apify.com/rowsmith). Also see: [App Store Rank Tracker](https://apify.com/rowsmith/app-rank-tracker) — the same rankings-over-time engine for Apple's App Store & Google Play top charts.

# Actor input Schema

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

Substack category slugs, e.g. technology, business, finance, culture, us-politics, health, science, crypto. Enter "all" to track every category.

## `sorts` (type: `array`):

Which leaderboards to track per category: Top (overall), Paid (bestsellers), Rising (trending).

## `maxRank` (type: `integer`):

How deep to capture each leaderboard (Substack caps public boards at 525). You are charged per row returned.

## `computeDeltas` (type: `boolean`):

Stores the previous snapshot in a small named key-value store in your account and adds prevRank / rankChange / isNew to every row. Schedule the Actor daily to build history.

## `includeDropped` (type: `boolean`):

Also emit a record (status: "dropped") for every publication that was on the board last run but fell off — useful for churn analysis.

## `historyDatasetName` (type: `string`):

If set, rows are ALSO appended to this named dataset in your account, building one continuous leaderboard-history table across runs (e.g. "substack-rank-history").

## `requestDelaySecs` (type: `integer`):

Polite delay between API pages. Keep at 1 unless you have a reason not to.

## Actor input object example

```json
{
  "categories": [
    "technology",
    "business",
    "finance",
    "culture",
    "us-politics"
  ],
  "sorts": [
    "all",
    "paid"
  ],
  "maxRank": 100,
  "computeDeltas": true,
  "includeDropped": false,
  "requestDelaySecs": 1
}
```

# Actor output Schema

## `rankings` (type: `string`):

The dataset of Substack leaderboard rankings with rank-change deltas.

# 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("rowsmith/substack-leaderboard-tracker").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("rowsmith/substack-leaderboard-tracker").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 rowsmith/substack-leaderboard-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rowsmith/substack-leaderboard-tracker"
        }
    }
}

```

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/4RGrSIDzoRcsEoBWB/builds/gMBcxwHWYbWgdzm9x/openapi.json
