# Substack Scraper & API: Posts, Subscribers & Full Text (`s_actors/substack-scraper`) Actor

Scrape Substack without login: newsletter posts (latest or top), keyword search, author or post links. Likes, comments, restacks, paid flag, newsletter subscriber count, author followers, full text as Markdown and top comments. Date and likes filters, new posts alerts.

- **URL**: https://apify.com/s_actors/substack-scraper.md
- **Developed by:** [Superior Actors](https://apify.com/s_actors) (community)
- **Categories:** Social media, News, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.59 / 1,000 posts

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

### Substack Scraper & API: Posts, Subscribers & Full Text

Export **Substack posts** with their real numbers: **likes, comments, restacks, word count, paid flag**, the newsletter's **subscriber count** and **leaderboard rank**, the author's **followers**, the **full text as Markdown** and the **top comments**. Get posts of any **newsletter** (the whole archive, latest or **top**), by **keyword search** across all of Substack, every post of an **author**, or by **post link**. No Substack account, no browser, no 20-post RSS limit.

```json
{ "publications": ["noahpinion", "www.lennysnewsletter.com"], "sort": "top", "publishedAfter": "2026-01-01" }
```

Filter by **date range**, **minimum likes** and **free / paid**; posts you filter out are free. Schedule it with **Only new posts** to get every new post of a newsletter, an author or a keyword as an alert.

#### What you get

Real example, 26 October 2026: newsletter **Noahpinion**, **Top**, published in 2026:

| published | title | subscribers | likes | comments | restacks | words | paid | leaderboard |
|---|---|---|---|---|---|---|---|---|
| 2026-01-11 | Why are federal agents gunning down Americans in the streets? | 461,000 | 1,111 | 457 | 215 | 3,122 | yes | #2 Business |
| 2026-06-26 | The Democrats have their own MAGA now | 461,000 | 755 | 315 | 129 | 3,617 | yes | #2 Business |
| 2026-02-05 | The Fall of the Nerds | 461,000 | 567 | 153 | 82 | 3,449 | yes | #2 Business |
| 2026-02-13 | You are no longer the smartest type of thing on Earth | 461,000 | 540 | 238 | 94 | 2,692 | yes | #2 Business |

Search **"personal finance"**, at least 50 likes, with the text:

| title | newsletter | subscribers | likes | comments | likes / 1k subscribers | full text |
|---|---|---|---|---|---|---|
| 10 Lessons from The Psychology of Money in Visuals | Sketchy Ideas | 12,000 | 10,733 | 335 | 894 | 1,112 words |
| you're too cool to not be financially literate | Financial Hot Girl | 30,000 | 11,634 | 93 | 388 | 2,002 words |
| 10 Micro Income Streams That Quietly Build Financial Freedom | WiFi Wealth by Tom Blake | 7,600 | 1,445 | 97 | 190 | 3,493 words |
| Hot Girls Guide to Saving Money | Hot Girls Save Money | 100,000 | 1,817 | 55 | 18 | 1,798 words |

| Field | Description |
|---|---|
| `id`, `title`, `subtitle`, `url`, `slug` | The post, its subtitle and link |
| `postType`, `audience`, `isPaid` | newsletter, podcast, thread or video; free, paid or founding members only |
| `publishedAt` | Publication time (UTC) |
| `authorName`, `authorHandle`, `authorUrl`, `authorBio`, `coAuthors` | The writer (guest authors too) and co-authors |
| `authorFollowers` | The author's followers on Substack |
| `publicationName`, `publicationSubdomain`, `publicationUrl`, `publicationId` | The newsletter it appeared in (custom domain if it has one) |
| `publicationSubscribers`, `publicationSubscribersText` | The newsletter's subscriber count as Substack shows it (`1.2M+ subscribers` = 1,200,000) |
| `leaderboardRank`, `leaderboardCategory` | Its place in the Substack bestseller leaderboard (e.g. #1 in Business) |
| `likes`, `comments`, `restacks` | Likes (hearts), comments and restacks of the post |
| `likesPer1kSubscribers` | Likes per 1,000 subscribers: finds posts that did far better than the newsletter's audience |
| `wordCount`, `readingTimeMinutes` | Number of words and reading time (265 words a minute) |
| `tags`, `language`, `imageUrl`, `description` | Post tags, language, the cover image, the teaser |
| `podcastUrl`, `podcastDurationSeconds` | The audio of podcast posts |
| `markdown`, `text`, `isFullText` | The post as Markdown (headings, links, lists, quotes, images, embeds) and plain text. `isFullText` = false: a paid post, you get the free preview Substack shows to visitors |
| `topComments` | With **Comments per post**: the top comments with replies (`author`, `text`, `date`, `likes`, `replyTo`) |
| `source`, `sourceType`, `rank` | The newsletter, query or author the row came from, and its place there |
| `scrapedAt` | Run time |

#### How it works

1. Add one or more sources: **Newsletters** (`noahpinion`, `noahpinion.substack.com` or a custom domain like `www.lennysnewsletter.com`), **Search queries**, **Authors** (`@handle` or a substack.com/@... link) or **Post links** (`/p/...` on any domain, open.substack.com, substack.com/home/post/p-...)
2. For newsletters, choose the **order**: **Latest** (newest first, the whole archive) or **Top** (most liked first)
3. Optionally set **Published after / before** (`2026-01-01` or `30 days`, `6 months`), **Minimum likes** and **Free or paid posts**
4. Set **Max posts per source** and run. Download as CSV, Excel, JSON or HTML. Three tabs: **Posts**, **Engagement**, **Text**

The text and the subscriber counts are on by default; turn them off for faster runs when you need only the post numbers. **Comments per post** (0 by default) adds the top comments to each row at no extra cost.

#### Why this Actor

| | |
|---|---|
| 📚 **The whole archive** | Substack's RSS feed gives only the 20 latest posts. Here a newsletter gives every post back to its first issue, an author every post they wrote, a search as deep as you want |
| 📈 **Subscriber counts and leaderboard rank** | The subscriber count of each newsletter and its bestseller rank on every row, plus likes per 1,000 subscribers to spot outliers |
| 📝 **Full text as Markdown** | Clean Markdown of free posts, ready for RAG, LLM training sets, summaries or archives; paid posts are flagged |
| 💬 **Comments included** | Top comments with replies in the same row, not a separate charge |
| 🎯 **Filters that cost nothing** | Dates, minimum likes, free / paid: filtered-out posts are not charged |
| 🔔 **New-post alerts** | **Only new posts** returns just what appeared since the previous run of the same source |
| 💰 **$0.99 per 1,000 posts** | Text, comments and subscriber counts included, no subscription |

#### Get new Substack posts every day

1. Add your newsletters, authors or keywords and turn on **Only new posts**
2. Save as a task and add a schedule, e.g. every morning
3. The **first run** returns the latest posts as a baseline. **Every later run** returns only posts not seen before: send them to [Google Sheets](https://apify.com/s_actors/google-sheets-import-export), Slack or email with an integration

The memory is kept in your account (key-value store `substack-scraper-state`). Use a different **Monitor name** for each task.

#### Pricing

Pay per post in the results, no subscription needed. Apify Scale and Business plans pay less:

| Event | Free and Starter plans | Scale plan | Business plan |
|---|---|---|---|
| Run start | $0.001 | $0.001 | $0.001 |
| Post (one row, text, comments and subscriber count included) | $0.00099 | $0.00077 | $0.00059 |

| Task | Cost |
|---|---|
| 20 latest posts of a newsletter | ~$0.02 |
| The whole archive of a newsletter (~1,000 posts), with text | ~$1.00 |
| 500 search results for one keyword | ~$0.50 |
| Daily alert of new posts of 10 newsletters (~5 a day) | ~$0.18 per month |

Posts left out by your filters or by **Only new posts** are not charged.

#### Ready-made tasks

Open it, change the newsletter, and run:

| Task | What you get |
|---|---|
| [Export a Substack Newsletter Archive](https://apify.com/s_actors/substack-scraper/examples/export-substack-newsletter-archive) | Every post of a newsletter with likes, comments, subscribers and the text as Markdown |

#### FAQ

**Where does the data come from?** From Substack itself, the same data any visitor sees, without logging in. Likes, comments, restacks and followers are Substack's own counts at the time of the run.

**How exact is the subscriber count?** It is the number Substack shows on the newsletter and the author's profile (`1.2M+`, `Over 324,000 subscribers`): a rounded floor, not the exact list size, which only the writer sees. Some newsletters hide their count: then the field is empty.

**Do I get the text of paid posts?** No. Paid (subscriber-only) posts give the free preview Substack shows to visitors, and `isFullText` is false. All their numbers (likes, comments, words) are complete. Use **Free or paid posts = Free posts only** when you need the full text of every row.

**Why are comments empty on some posts?** Paid posts hide their comments from visitors; the `comments` count is still there.

**How many posts can I get?** A newsletter or an author: the whole history. A search: as deep as Substack returns results (hundreds per query).

**What date formats work?** `2026-01-31`, `2026-01-31T10:00:00Z`, or relative: `7 days`, `2 weeks`, `3 months`, `1 year`.

**Do I need a Substack account or an API key?** No.

#### Use with the API and AI agents

Run it via the [Apify API](https://docs.apify.com/api/v2) from Python, Node.js or any HTTP client as your Substack API, or connect it to Claude, ChatGPT and other AI agents through the [Apify MCP server](https://mcp.apify.com): "Find the most liked Substack posts about AI agents from the last 3 months, from newsletters under 50,000 subscribers, and summarize what they have in common."

#### Other blog & content tools

| Tool | What it does |
|---|---|
| [Medium Scraper](https://apify.com/s_actors/medium-scraper) | Medium articles by tag, search, author or publication, with claps and full text |
| [YouTube Transcript Scraper](https://apify.com/s_actors/youtube-transcript-scraper) | Transcripts of YouTube videos and channels as text |
| [Audio & Video Transcriber](https://apify.com/s_actors/audio-video-transcriber) | Podcasts and any audio or video file to text |
| [Threads Scraper](https://apify.com/s_actors/threads-scraper) | Threads posts and profiles with likes and replies |
| [Google Sheets Import & Export](https://apify.com/s_actors/google-sheets-import-export) | Send the posts to a Google Sheet |

#### Is it legal?

The Actor reads only public pages and data that Substack shows to any visitor, without logging in, and does not get around the paywall. Posts belong to their authors: respect copyright when you reuse the text, and follow data protection rules (such as GDPR) for the author names, bios and comments in the results.

# Actor input Schema

## `publications` (type: `array`):

Substack newsletters: a name like "noahpinion", a link (noahpinion.substack.com) or a custom domain (www.lennysnewsletter.com). The whole archive, in the order set below.

## `searchQueries` (type: `array`):

Keywords, like the Substack search box: "ai agents", "personal finance". Posts of all newsletters, most relevant first.

## `authors` (type: `array`):

Substack handles (with or without @) or profile links (substack.com/@name). All posts the author wrote, in every newsletter, newest first.

## `postUrls` (type: `array`):

Links to Substack posts: <newsletter>/p/<slug> (custom domains too), open.substack.com/pub/... or substack.com/home/post/p-<id>. One row each.

## `sort` (type: `string`):

Latest: newest first, as deep as the archive goes. Top: the most liked posts of the newsletter first (the "Top" tab of its archive).

## `publishedAfter` (type: `string`):

Only posts published on or after this date: 2026-01-01, or relative: "7 days", "3 months", "1 year".

## `publishedBefore` (type: `string`):

Only posts published before this date (same formats).

## `minLikes` (type: `integer`):

Only posts with at least this many likes (hearts). Left-out posts are free.

## `audience` (type: `string`):

All posts, only free ones (full text available), or only paid (subscriber-only) ones.

## `maxPostsPerSource` (type: `integer`):

For each newsletter, query and author.

## `maxPosts` (type: `integer`):

The run stops at this many posts.

## `includeContent` (type: `boolean`):

Full text of free posts as Markdown (headings, links, lists, images) and plain text. Paid posts: the free preview Substack shows to visitors (isFullText = false).

## `includeSubscriberCounts` (type: `boolean`):

Subscriber count of the newsletter (as Substack shows it, like 1.2M+), its leaderboard rank and the author's followers. One extra request per author.

## `commentsPerPost` (type: `integer`):

Top comments of each post (with replies) in the row, 0 = none. Paid posts hide their comments from visitors.

## `onlyNew` (type: `boolean`):

Output only posts not seen in the previous runs of the same source (and monitor name). Schedule it daily to get new posts of a newsletter, author or keyword.

## `monitorName` (type: `string`):

Keeps the memory of seen posts apart for different schedules.

## `debugLog` (type: `boolean`):

Log every request retry.

## Actor input object example

```json
{
  "publications": [
    "https://www.lennysnewsletter.com"
  ],
  "sort": "latest",
  "audience": "all",
  "maxPostsPerSource": 20,
  "maxPosts": 1000,
  "includeContent": true,
  "includeSubscriberCounts": true,
  "commentsPerPost": 0,
  "onlyNew": false,
  "debugLog": false
}
```

# Actor output Schema

## `overview` (type: `string`):

Every post: title, link, author, newsletter, date, likes, comments, restacks.

## `all` (type: `string`):

Every field, with the Markdown and plain text and the top comments of each post.

# 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 = {
    "publications": [
        "https://www.lennysnewsletter.com"
    ],
    "maxPostsPerSource": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("s_actors/substack-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 = {
    "publications": ["https://www.lennysnewsletter.com"],
    "maxPostsPerSource": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("s_actors/substack-scraper").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 '{
  "publications": [
    "https://www.lennysnewsletter.com"
  ],
  "maxPostsPerSource": 20
}' |
apify call s_actors/substack-scraper --silent --output-dataset

```

## MCP server setup

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

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/MH0HA7MgxpIe0nsrA/builds/cPBiOkML5pCdLSBY6/openapi.json
