Substack Scraper: Free-Post Full Text, Likes & Comments
Pricing
Pay per event
Substack Scraper: Free-Post Full Text, Likes & Comments
Get the full text of every free Substack post, along with likes, comment counts, and dates, so newsletters are ready for analysis or sponsor scouting. A test run returned 60 posts.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Almandine Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Security
Limited permissionsShare
Substack Scraper: Posts, Likes, Comments & Free Post Text
Scrape any Substack newsletter archive: post title, date, authors, likes, comments, restacks, word count, paywall flag, and free post text. Export JSON/CSV.
What it does
Reads each publication's public archive and returns posts newest-first with engagement metrics. Optional plain text of free posts. Export clean, deduplicated data as JSON, CSV, Excel, XML, or RSS, or connect directly via the Apify REST API, Python/JavaScript SDKs, CLI, MCP Server, n8n, Make, or Zapier — with no login, cookies, or browser overhead.
Use cases
- Newsletter Sponsorship & Media Buying: Rank Substack publications by average likes, comments, restacks, posting frequency, and free vs. paywalled ratio.
- Creator & Journalist Research: Export complete post archives across multiple Substack subdomains or custom domains in seconds without login.
- AI / RAG Content Datasets: Extract clean plain-text bodies (
includeContent: true) from free public Substack articles for research and LLM pipelines. - Scheduled Topic Monitoring: Run daily with
onlyNew: trueto ingest new newsletter issues as soon as they publish.
Why use this scraper?
| Feature | This Actor | Generic Browser / HTML Scrapers |
|---|---|---|
| Architecture | Direct structured API / JSON / feed requests (curl_cffi) | Heavy headless browser automation |
| Speed & reliability | 2–25 seconds for 50–200 items | Minutes of high compute burn |
| Pricing model | Pay per result ($0.00 actor-start fee) | Monthly rental or high CU overhead |
| Error handling | Failed inputs logged in ERRORS key-value record and never charged | Bills compute time even on failures |
Input parameters
- Publications (
publications,array): Substack subdomains (e.g. 'astralcodexten'), *.substack.com URLs or custom-domain Substack URLs. - Max posts per publication (
maxPostsPerPublication,integer): Newest posts first. You are charged per post returned. - Published after (YYYY-MM-DD) (
publishedAfter,string): Optional. Stop at posts older than this date. - Include free post text (
includeContent,boolean): Adds the plain-text body of free posts (higher per-post price). Paywalled bodies are never returned. - Only new posts (
onlyNew,boolean): On scheduled runs, return only posts not seen in earlier runs. - Delay between requests (
delaySeconds,number): Polite pause between requests (default0.7).
Example input
{"publications": ["astralcodexten","https://www.lennysnewsletter.com"],"maxPostsPerPublication": 30}
Output & example output
One dataset row per result. Default table view columns: coverImage, publicationUrl, title, postDate, authors, likes, comments, restacks, wordcount, isPaywalled, url. Full structured JSON is stored in the run's default dataset.
Example output item
{"publicationUrl": "https://astralcodexten.substack.com","publicationId": 89120,"postId": 212349428,"url": "https://www.astralcodexten.com/p/your-book-review-the-ghost-in-my","title": "Your Book Review: The Ghost In My Brain","subtitle": "Finalist #13 in the Book Review Contest","type": "newsletter","postDate": "2026-10-23T23:45:42.358Z","audience": "everyone","isPaywalled": false,"authors": ["Scott Alexander"],"likes": 130,"comments": 101,"restacks": 1,"wordcount": 4187,"tags": [],"coverImage": "https://substackcdn.com/image/fetch/$s_!wVWo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F621384df-793b-4ff7-b...","description": "Finalist #13 in the Book Review Contest","podcastUrl": null,"scrapedAt": "2026-10-25T04:27:04+00:00"}
Pricing (Pay-Per-Result)
This Actor uses transparent Pay-Per-Event pricing with a $0.00 actor-start fee:
| Event | What is charged | Price |
|---|---|---|
post-result | Post scraped (One post with metadata and engagement) | $0.002 / result ($2.00 / 1,000 results) |
post-with-content | Post scraped with text (One post with metadata plus free-post body text) | $0.003 / result ($3.00 / 1,000 results) |
apify-actor-start | Actor start fee | $0.00 |
Concrete pricing math
post-result(Post scraped):1,000 results = $2.00(50 results = $0.10,10,000 results = $20.00). Apify's $5.00/month Free Tier covers up to 2,500 results/month at $0.00 out-of-pocket.post-with-content(Post scraped with text):1,000 results = $3.00(50 results = $0.15,10,000 results = $30.00). Apify's $5.00/month Free Tier covers up to 1,666 results/month at $0.00 out-of-pocket.- Empty runs (
0results) & skipped duplicates (onlyNew/onlyChanged): $0.00.
Data and compliance
Free content only: paywalled post bodies are never returned. No subscriber data. Requests are rate-limited and routed through Apify Proxy. Per-input errors are recorded in the run's ERRORS key-value record and are never charged.
FAQ
Do I need an account, login, or API key?
No. This Actor queries public endpoints directly and requires zero credentials.
What happens if I start a run with empty {} input via API or CLI?
Every required input defines both prefill and default values in .actor/input_schema.json, so an empty {} run automatically returns 50+ live records out of the box.