Substack Posts Scraper — full articles as Markdown & text
Pricing
$0.80 / 1,000 substack posts
Substack Posts Scraper — full articles as Markdown & text
Pricing
$0.80 / 1,000 substack posts
Rating
0.0
(0)
Developer
Arthur
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Substack Posts Scraper — full articles as Markdown & plain text
Turn any Substack publication into a clean dataset: every post with title, subtitle, date, authors, paywall status, likes, comments, restacks, tags, cover image, podcast/video info and — optionally — the full article body as Markdown and plain text. Works with name.substack.com and with custom domains (e.g. www.lennysnewsletter.com). Uses Substack's public JSON endpoints: no login, no proxies, no browser.
Typical uses: newsletter monitoring and research, competitive analysis of writers, content archives, LLM/RAG corpora, sentiment/engagement tracking, Make/Zapier/Sheets automations.
What you get
One row per post (type: "post"):
| field | description |
|---|---|
publication, publication_url | Substack handle and site |
post_id, slug, url | Stable ID, slug and canonical URL |
title, subtitle, description | Headline, dek and SEO description |
date | ISO 8601 publish time |
authors, author_handles | Bylines |
post_type | newsletter, podcast, thread, video… |
audience, is_paywalled | everyone, only_paid, founding |
wordcount, reaction_count, comment_count, restacks | Length and engagement |
tags, section | Post tags and section |
cover_image, podcast_url, podcast_duration, video_upload_id | Media |
preview | Short teaser text |
body_markdown, body_text, body_words, body_complete | With Include full article body (default on). body_complete is false when only the free preview of a paywalled post was available. body_html optional. |
With Include publication info (default on) you get one type: "publication" row: name, author_name, hero_text, description, subdomain, custom_domain, logo_url, cover_photo_url, language, created_at, copyright, twitter, paid_subscriptions, monthly_price_cents, currency, pinned_post_ids.
Unknown or unreachable publications produce a type: "error" row (free) and the run continues.
Export as JSON, CSV or Excel, or push rows to Google Sheets, Make, Zapier, webhooks or your code via the Apify API.
Input
| field | default | meaning |
|---|---|---|
publications | — | Handles or URLs: astralcodexten, lenny.substack.com, https://www.lennysnewsletter.com |
maxPosts | 50 | Per publication, newest first |
since | — | Only posts on/after YYYY-MM-DD |
includeBody | true | Fetch each post's full body (Markdown + text) |
includeHtml | false | Also keep the original HTML |
freeOnly | false | Skip paywalled posts |
includePublicationInfo | true | Add the publication row |
Example:
{"publications": ["astralcodexten", "https://www.lennysnewsletter.com"],"maxPosts": 100,"since": "2026-01-01","includeBody": true}
Schedule the actor and deduplicate on post_id to keep an always-current archive.
Pricing
Pay per event: $0.0008 per stored row ($0.80 per 1,000 posts). Each post row and each publication-info row counts as one event. Only rows actually written to the dataset are charged; error rows and filtered-out posts are free. Apify platform usage (roughly 1 second of compute per post with bodies) is billed separately by Apify.
Limitations — please read
- Paywalled posts: Substack only exposes the free preview of paid posts;
body_complete: falsemarks them andbody_wordsvswordcountshows how much you got. Subscriber-only content is not accessible. - Comments and subscriber counts are not included (Substack does not expose them publicly per publication).
- Markdown conversion covers headings, paragraphs, bold/italic, links, images, lists, quotes, code and tables; embedded widgets (subscribe buttons, polls, embedded posts) are removed.
- Runs at about 2 requests per second per publication to stay polite; 1,000 posts with bodies take roughly 8–10 minutes.
Not affiliated with Substack. Uses only publicly accessible endpoints.