Substack Scraper (Posts, Likes, Comments, Full Text)
Pricing
from $0.70 / 1,000 post scrapeds
Substack Scraper (Posts, Likes, Comments, Full Text)
Export every post of any Substack newsletter (substack.com or custom domain): title, subtitle, date, authors, likes, comments, restacks, word count, paid or free, tags, podcast link and, optionally, the full text. Export to Excel, CSV or JSON.
Pricing
from $0.70 / 1,000 post scrapeds
Rating
0.0
(0)
Developer
Julio Barcellos Rangel
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
22 days ago
Last modified
Security
Limited permissionsShare
Substack Scraper exports the posts of any Substack newsletter, on substack.com or on a custom domain: title, subtitle, date, authors, likes, comments, restacks, word count, free or paid, tags, podcast link and, if you want, the full text. It is built for content marketers, newsletter writers, sponsors, researchers and AI teams who want to scrape a Substack archive or export Substack posts to Excel, CSV or JSON. No login is needed.
What does Substack Scraper do?
You give it one or more newsletters and it reads each newsletter's public archive, newest posts first, until it reaches your limit or the end of the archive. Each post becomes one row with its numbers and links.
You can enter a newsletter in any of these forms:
- A Substack name:
platformer(read asplatformer.substack.com) - A Substack address:
astralcodexten.substack.com - A full URL or custom domain:
https://www.lennysnewsletter.com
If you paste a link to a single post, the scraper uses the newsletter's main address and reads the whole archive.
Optional settings let you:
- Add the full text of each post as plain text (for paid posts, only the free preview part).
- Only get posts newer than a date, for example the last month, so scheduled runs only pick up new posts.
What data can you extract?
| Field | What it means | Example |
|---|---|---|
publication | Newsletter address the post comes from | https://www.lennysnewsletter.com |
postId | Substack post ID | 215694124 |
title | Post title | All of the Lenny & Friends Summit talks are now online! |
subtitle | Post subtitle | Plus, some reflections and takeaways from the day |
url | Link to the post | https://www.lennysnewsletter.com/p/all-of-the-lenny-and-friends-summit |
postDate | Publication date (ISO 8601) | 2026-09-29T13:15:57.512Z |
type | Post type as Substack reports it | newsletter, podcast |
audience | Who can read the post, as Substack reports it | everyone, only_paid |
isPaid | true when the post is for paid (or founding) subscribers only | false |
authors | Author names on the byline | ["Hamel Husain", "Shreya Shankar"] |
likes | Number of likes (reactions) | 283 |
comments | Number of comments | 6 |
restacks | Number of restacks | 5 |
wordCount | Length of the post in words | 1276 |
coverImage | Cover image URL | https://substack-post-media.s3.amazonaws.com/public/images/… |
tags | Post tags | ["AI"] |
podcastUrl | Audio file link for podcast posts | null |
podcastDurationSeconds | Podcast length in seconds | null |
preview | Short preview text of the post | 👋 Hey there, I’m Lenny. Each week, I share… |
content | Full post text as plain text (only when Include full text is on) | I’m excited to share that every main-stage talk… |
contentIsPreview | true when content is only the free preview of a paid post (only with full text) | false |
scrapedAt | When the post was scraped (ISO 8601) | 2026-10-10T20:36:47.536Z |
input | Only on error rows: the newsletter you entered | platformer |
error | Only on error rows: why no posts came back | Publication not found or has no posts |
How to use Substack Scraper
- Open Substack Scraper in Apify Console.
- Add newsletters to Newsletters, one per line: a name such as
platformer, an address such asname.substack.com, or a custom domain URL. - Set Max posts per newsletter (default 50). Use a high number to export the whole archive.
- Optional: pick a date in Only posts newer than to skip older posts.
- Optional: turn on Include full text to add the post body.
- Click Start and wait for the run to finish.
- Open the Output tab and export the posts as JSON, CSV, Excel or HTML.
Input
| Field | Type | Default | What it does |
|---|---|---|---|
publications | list of text (required) | ["https://www.lennysnewsletter.com"] | Substack names, URLs or custom domains, for example platformer, https://www.lennysnewsletter.com, astralcodexten.substack.com. |
maxPostsPerPublication | integer | 50 | Maximum posts per newsletter, newest first. From 1 to 10,000. |
includeContent | true/false | false | Adds content (post text as plain text) and contentIsPreview. For paid posts you only get the free preview. |
onlyPostsNewerThan | date (YYYY-MM-DD) | empty | Only returns posts published on or after this date. The scraper stops reading the archive when it reaches an older post. |
proxy | object | { "useApifyProxy": true } | Apify Proxy settings. The default works for most runs. |
Example input:
{"publications": ["https://www.lennysnewsletter.com", "platformer"],"maxPostsPerPublication": 200,"includeContent": true,"onlyPostsNewerThan": "2026-01-01","proxy": { "useApifyProxy": true }}
Output example
One real post from a recent run:
{"publication": "https://www.lennysnewsletter.com","postId": 215694124,"title": "All of the Lenny & Friends Summit talks are now online!","subtitle": "Plus, some reflections and takeaways from the day","url": "https://www.lennysnewsletter.com/p/all-of-the-lenny-and-friends-summit","postDate": "2026-09-29T13:15:57.512Z","type": "newsletter","audience": "everyone","isPaid": false,"authors": ["Lenny Rachitsky"],"likes": 283,"comments": 6,"restacks": 5,"wordCount": 1276,"coverImage": "https://substack-post-media.s3.amazonaws.com/public/images/9fed347c-0e02-4190-a590-1236719b99de_9213x6142.jpeg","tags": [],"podcastUrl": null,"podcastDurationSeconds": null,"preview": "👋 Hey there, I’m Lenny. Each week, I share deeply researched product, growth, and career advice. For more: Lenny’s Jobs | Lennybot | Become an AI-Native Builder and other favorite AI/PM courses","scrapedAt": "2026-10-10T20:36:47.536Z"}
With Include full text on, the same post also gets these two fields (text trimmed):
{"content": "👋 Hey there, I’m Lenny. Each week, I share deeply researched product, growth, and career advice…\n\nI’m excited to share that every main-stage talk from the recent Lenny & Friends Summit is now online…","contentIsPreview": false}
How much does it cost?
Substack Scraper uses pay-per-event pricing. You pay $1.00 per 1,000 posts ($0.001 per post) on the Free plan. Apify platform usage is included in the price, and the full text does not cost extra.
| Plan | Price per 1,000 posts |
|---|---|
| Free | $1.00 |
| Bronze (-10%) | $0.90 |
| Silver (-20%) | $0.80 |
| Gold and higher (-30%) | $0.70 |
Worked examples on the Free plan:
- The latest 50 posts of one newsletter = $0.05
- A full archive of 1,000 posts with full text = $1.00
- 20 newsletters, 500 posts each = 10,000 posts = $10.00
What you are not charged for:
- Error rows: newsletters that could not be found, have no posts, or were not a valid address.
- Posts skipped by the Only posts newer than date.
- Duplicate posts: a post that shows up twice in the archive is returned once.
Use cases
- Content research: find the most liked, commented and restacked posts of a newsletter and see which topics work.
- Competitor analysis: compare posting frequency, post length and paid versus free posts across newsletters in your niche.
- Sponsorship research: check engagement before you buy a sponsored slot in a newsletter.
- AI and RAG datasets: export full post text to build a searchable knowledge base, summaries or training data (respect the authors' rights).
- Monitoring: schedule a daily run with Only posts newer than to get new posts from the newsletters you follow.
- Podcast catalogs: list podcast episodes with audio links and durations.
- Academic and media research: study what writers publish on Substack over time.
Tips and limits
- Paid posts: without a subscription you only get the free preview part.
isPaidandcontentIsPreviewtell you when the text is incomplete.wordCountis still the length of the full post. - Full text is slower: with Include full text on, the scraper may load each post separately to get its body, so large archives take longer.
- Empty text: if one post's text cannot be loaded, its
contentis an empty string and the run continues. - Date filter: the archive is read newest first and the scraper stops at the first post older than your date. If no post is newer than the date, you get an error row (
Publication not found or has no posts), which is free. - Numbers are a snapshot: likes, comments and restacks are the counts at the time of the run. Schedule runs to track them over time.
- Custom domains: newsletters on their own domain work the same as
name.substack.com. - Enter each newsletter once: duplicates are not merged, so
platformerandplatformer.substack.comin the same run scrape (and charge) the newsletter twice. - Error rows:
Invalid publication URLmeans the text could not be read as an address;Publication not found or has no postsmeans the archive was empty, not found or did not answer after four tries.
Use it from the API, Python or JavaScript
You can run the scraper and read the posts with the official Apify clients. Replace YOUR_TOKEN with your Apify API token.
JavaScript (Node.js):
const { ApifyClient } = require('apify-client');const client = new ApifyClient({ token: 'YOUR_TOKEN' });const input = { publications: ['https://www.lennysnewsletter.com'], maxPostsPerPublication: 100 };const run = await client.actor('juliob.rangel/substack-scraper-fast').call(input);const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Python:
from apify_client import ApifyClientclient = ApifyClient('YOUR_TOKEN')input = {'publications': ['https://www.lennysnewsletter.com'], 'maxPostsPerPublication': 100}run = client.actor('juliob.rangel/substack-scraper-fast').call(run_input=input)items = client.dataset(run['defaultDatasetId']).list_items().itemsprint(items)
The scraper also works with Make, Zapier and n8n, can export results to Google Sheets, can call your webhook when a run finishes, and can be used by AI agents through the Apify MCP server.
FAQ
Do I need a Substack account or login? No. The scraper reads the public archive of each newsletter. It does not log in, so paid posts only include their free preview.
Can I export Substack posts to Excel or CSV? Yes. Open the Output tab after the run and download the dataset as Excel, CSV, JSON or HTML, or send it to Google Sheets.
How many posts can I get? Up to 10,000 per newsletter in one run, limited by how many posts the newsletter has published.
Does it work with custom domains?
Yes. Enter the domain (for example https://www.lennysnewsletter.com) and the scraper reads it like any substack.com newsletter.
Can I get the comments themselves?
No. You get the number of comments per post (comments), not the comment text.
Is it legal to scrape Substack? The scraper only collects publicly available data. You are responsible for complying with Substack's terms, copyright and privacy laws such as GDPR and LGPD. Post text belongs to its authors, and author names are personal data, so you need a legitimate reason to collect and use them.
Why did I get an error row? The newsletter address was not valid, the newsletter has no posts, or Substack did not answer. If you used Only posts newer than, it can also mean there are no posts after that date. Error rows are not charged.
Related scrapers
- Website to Markdown Crawler
- Google News Scraper (Real Article URLs)
- Telegram Channel Scraper (Posts, Views, Reactions)
- Threads Scraper (Profiles, Posts, Search)
- YouTube Transcript Scraper (Fast & Cheap)
Extrator do Substack (PT-BR)
Exporte todos os posts de qualquer newsletter do Substack: título, data, autores, curtidas, comentários, restacks, se é pago e, se quiser, o texto completo. Funciona com substack.com e domínios próprios. Você paga só por post retornado.