Medium Scraper — Articles, Full Text, Authors, Claps & Comments avatar

Medium Scraper — Articles, Full Text, Authors, Claps & Comments

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Medium Scraper — Articles, Full Text, Authors, Claps & Comments

Medium Scraper — Articles, Full Text, Authors, Claps & Comments

Scrape Medium by tag, search, author, publication or URL: posts with claps, responses, reading time, tags, author and publication stats, plus optional full article text as Markdown and comments. Whole tag archives, thousands of posts per run, no login. Not affiliated with Medium.

Pricing

from $1.00 / 1,000 results

Rating

0.0

(0)

Developer

Logiover

Logiover

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

3 days ago

Last modified

Share

Medium Scraper

Medium Scraper is a fast Medium article scraper and a practical Medium API alternative. Scrape Medium posts, claps, responses (comments), reading time, tags, authors and publications without login, cookies or a Medium account — by tag, by keyword search, by author, by publication or from any Medium URL — and export the Medium data to CSV, Excel, JSON, XML or Google Sheets. Turn on one switch and every story also comes with its full article text as clean Markdown and plain text, ready for AI, RAG and LLM pipelines.

Use it as a Medium tag scraper (the complete newest-first archive of any tag, not just the 10 stories an RSS feed shows), a Medium author scraper (every story a writer has published, plus their follower count and bio), a Medium publication scraper (any publication, custom domains such as levelup.gitconnected.com included), a Medium search scraper (posts, people, publications or tags for any keyword) and a Medium comments scraper (responses and reply threads with full text). Measured on 2026-10-13: 10,000 posts in 40 seconds, the entire history of a tag (4,840 posts back to 2018) in 34 seconds, and 1,000 posts in under 10 seconds.

Medium Scraper is an independent tool. It is not affiliated with, endorsed by or sponsored by Medium (A Medium Corporation). See the disclaimer.


What you get

One run can mix several sources. Every row has a rowType, so posts, responses and profiles can live in one dataset and be filtered or exported separately (the Dataset tab has a ready-made view for each).

Row typeOne row perMain fields
postMedium storytitle, subtitle, URL, canonical URL, published / updated date, reading time, word count, claps, clappers, responses count, tags, member-only flag, language, preview image, author (name, username, followers, bio, member status, X/Twitter), publication (name, slug, URL, followers), rank, source
post + full textMedium story with includeContenteverything above plus article text (plain), Markdown (headings, lists, quotes, code blocks with language, links, images), image URLs, outbound links, code-block and paragraph counts, preview flag
responseresponse (comment) or replyfull text, claps, clappers, replies count, depth (1 = response, 2 = reply …), parent and root post IDs, root post URL, author name / username / followers, date
authorwritername, username, profile URL, bio, followers, following, photo, member since, membership tier, Partner Program, book-author badge, X/Twitter, custom domain
publicationpublicationname, slug, URL, custom domain, description, followers, logo, X/Twitter, topics, owner, editors and editor count
tagtag / topicname, slug, URL, total posts in the tag, followers

71 documented fields, typed in the dataset schema, with consistent empty values (null, never 0 for "unknown").


Why this Medium scraper

  • No login, no cookies, no browser. It reads the same data Medium's own web app loads for signed-out visitors. Nothing to configure, nothing to get banned.
  • Real depth. Tags are read from Medium's complete chronological tag archive — every story ever tagged, newest first — not from a ranked list that stops at ~100. Authors and publications are read back to their first story.
  • Fast. Big sources are read in parallel time slices and delivered strictly newest-first: 1,000 posts in 6–10 s, 10,000 in 40 s.
  • Full article text as Markdown and plain text with one switch, at no extra request cost (the text rides along with each page of posts).
  • Comments too. Responses and reply threads, with full text, claps and authors.
  • Exact limits. maxItems is honoured to the row — you never get (or pay for) more rows than you asked for. Duplicates are removed across all sources in a run.
  • Honest run status. A tag, author or publication that does not exist ends the run as Succeeded with a clear message ("tag … does not exist on Medium"), not as a mysterious failure. A run fails only when Medium could not be reached at all.
  • Built-in reliability. Fresh connection per request, automatic retries and hedged requests, automatic fallback to Apify Proxy if Medium ever refuses direct requests, and a time budget that always leaves room to save your data before the run's timeout.
  • Fresh data. Everything is fetched live at run time — claps, follower counts and responses are as of the minute you run it.

Use cases

Content research and topic discovery

Pull the newest 5,000 stories of artificial-intelligence, product-management or web3 and see what people write about, which angles get claps, which subtitles work, how long successful posts are (wordCount, readingTimeMinutes) and which tags travel together.

Competitor and blog monitoring

Track a competitor's engineering blog or a publication in your niche. Schedule the Actor daily with publishedAfter: "1 day" and get only the new stories, with claps and responses, in your inbox, Slack or Google Sheet.

Writer and influencer discovery

Search people for "data engineering" or scrape the top lists of a tag to find the writers your audience reads — with follower counts, bios, X/Twitter handles, Partner Program status and their full story history. Great for outreach lists, guest-post sourcing and creator marketing.

AI, RAG and LLM datasets

Collect clean article text and Markdown (code blocks keep their language) with authors, dates, tags and canonical URLs for retrieval-augmented generation, semantic search, summarisation or classification. Use skipMemberOnly to keep only stories whose complete text is public, and language: "en" to keep one language.

Trend analysis and market intelligence

Measure how a topic grows: posts per day in a tag, average claps, share of member-only stories, top publications, top authors. Because the tag archive is chronological and complete, publishedAfter / publishedBefore give exact time windows (a whole month of a busy tag is cheap).

SEO and content-gap analysis

Search Medium for your keywords, export titles, subtitles and tags, and find the questions your blog has not answered yet.


How it works

  1. Inputs are normalised. Tag names, @usernames, profile URLs, publication slugs, custom domains, story URLs and search URLs are all recognised automatically.
  2. Medium's own data endpoint is queried — the GraphQL API medium.com's web app uses: exact clap counts, IDs and timestamps, not HTML that changes with every redesign.
  3. Chronological sources are read in parallel time slices. The first page measures how many stories per hour a tag, author or publication produces; the time range that should hold your maxItems is then cut into small slices that up to 16 lanes read at once. Rows are released strictly newest-first, so when the run reaches maxItems you still have exactly the newest N stories, and rank 1 is the newest.
  4. Ranked lists and search are paged in parallel and delivered in Medium's own order (rank = position).
  5. Responses are fetched for many posts per request, best first, with optional reply threads.
  6. Every row is checked against the dataset schema, de-duplicated across sources and counted before it is written, so maxItems is exact even with 20 requests in flight.
  7. A SUMMARY record (key-value store) lists rows per type, notes such as "author @x not found", and why the run stopped (stoppedBy: MAX_ITEMS, MAX_COST, TIMEOUT or none).

Quick start

  1. Open the Actor and type a tag into Tags, e.g. artificial-intelligence (that is the prefilled example).
  2. Set Max rows (100 for a test, 10,000+ for a real export).
  3. Click Start. Rows appear in the Dataset tab within a few seconds. Export as CSV, Excel, JSON, XML or HTML, or connect the run to Google Sheets, Make, Zapier or n8n.

Prefilled example (finishes in about 4 seconds):

{
"tags": ["artificial-intelligence"],
"tagSort": "newest",
"maxItems": 100,
"proxyConfiguration": { "useApifyProxy": true }
}

Input reference

FieldTypeDefaultWhat it does
tagslist—Tags as slugs, names or URLs: artificial-intelligence, Machine Learning, https://medium.com/tag/python.
tagSortselectnewestnewest = complete chronological archive (unlimited depth). trending, top-week, top-month, top-year, top-all-time = Medium's ranked lists (~100 each). all-top = all ranked lists combined.
searchQuerieslist—Keywords for Medium search, one per line.
searchTypeselectpostsWhat the queries search: posts, people, publications or tags.
authorslist—@username, username, https://medium.com/@name or https://name.medium.com. Returns the profile and all stories, newest first.
publicationslist—Slug (better-programming), URL (https://medium.com/swlh) or custom domain (levelup.gitconnected.com). Returns the publication and all its stories.
startUrlslist—Any Medium URL: story (also on custom domains), tag page, profile, publication, or search page (https://medium.com/search?q=rust). Story IDs work too.
maxItemsnumber1000Total rows for the run (posts + responses + profile rows). 0 = no limit.
maxPostsPerSourcenumber0Cap per tag / author / publication / query, so one big source cannot use up the run. 0 = no cap.
publishedAftertext—Only stories published on/after this date: 2025-01-01, 2025-01-01T12:00:00Z, or relative 30 days, 6 months, 1 year. Chronological sources stop reading here.
publishedBeforetext—Only stories published before this date (same formats). Chronological sources start reading here.
minClapsnumber0Skip stories with fewer claps.
languagetext—Keep only these languages, ISO codes comma-separated: en or en, es, pt.
skipMemberOnlyyes/nonoLeave out member-only (paywalled) stories.
includeContentyes/nonoAdd article text (plain + Markdown), image URLs, links, code-block count.
includeResponsesyes/nonoAdd responses (comments) of every collected story as response rows.
maxResponsesPerPostnumber50Responses (and replies) per story, best first. 0 = all.
includeRepliesyes/nonoFollow reply threads under responses (depth 2, 3 …).
includeProfilesyes/noyesAdd one profile row for each tag, author and publication you list.
maxConcurrencynumber20Requests in flight (1–50).
proxyConfigurationproxyApify ProxyDefault: direct connection (fastest) with automatic switch to Apify Proxy if Medium refuses. Pick a proxy group or your own proxies to force them.

Examples for every mode

Newest stories of several tags (complete archive):

{ "tags": ["artificial-intelligence", "startup", "javascript"], "maxItems": 5000 }

A precise time window — every English story in a tag during January 2025 with at least 50 claps:

{
"tags": ["machine-learning"],
"publishedAfter": "2025-01-01",
"publishedBefore": "2025-02-01",
"minClaps": 50,
"language": "en",
"maxItems": 0
}

Medium's best stories of a topic (trending + top week / month / year / all time):

{ "tags": ["productivity"], "tagSort": "all-top", "maxItems": 500 }

Keyword search for posts:

{ "searchQueries": ["rust async", "vector database"], "searchType": "posts", "maxItems": 2000 }

Find writers (people search):

{ "searchQueries": ["data engineering", "growth marketing"], "searchType": "people", "maxItems": 1000 }

Every story of some authors, with their profiles:

{ "authors": ["@ev", "https://medium.com/@devrimozcay"], "maxItems": 0 }

A whole publication (custom domains work):

{ "publications": ["levelup.gitconnected.com", "better-programming"], "maxPostsPerSource": 2000, "maxItems": 4000 }

Specific stories with full text and comments:

{
"startUrls": [
"https://medium.com/ai-engineering-simplified/5-claude-tricks-that-give-you-an-unfair-advantage-most-people-still-use-the-old-way-0385a58057c7",
"https://levelup.gitconnected.com/macos-never-got-the-file-manager-developers-deserved-so-i-built-it-e8ac81480578"
],
"includeContent": true,
"includeResponses": true,
"includeReplies": true,
"maxResponsesPerPost": 0
}

An AI / RAG corpus — free stories only, full text, one language:

{
"tags": ["llm", "retrieval-augmented-gen", "prompt-engineering"],
"includeContent": true,
"skipMemberOnly": true,
"language": "en",
"maxItems": 10000
}

Daily monitoring (schedule this every morning):

{ "tags": ["your-niche-tag"], "publications": ["competitor-publication"], "publishedAfter": "1 day", "maxItems": 0 }

Output data dictionary

Post rows (rowType: "post")

FieldTypeDescription
idstringMedium story ID (12 hex characters). Stable — use it to de-duplicate across runs.
title, subtitlestringHeadline and the subtitle / preview line Medium shows in feeds.
urlstringStory URL (the publication's custom domain when it has one).
canonicalUrlstringCanonical link; differs from url when the story was first published elsewhere.
publishedAt, updatedAtISO dateFirst publication and latest published edit (UTC).
readingTimeMinutesnumberMedium's reading-time estimate.
wordCountnumberWords in the full story (also for member-only stories).
claps, votersnumberTotal claps and number of distinct readers who clapped.
responsesCountnumberNumber of responses (comments).
tagsstringTag slugs, pipe-separated (ai | startup | productivity).
isMemberOnly, visibilityboolean, stringPaywall flag; PUBLIC, LOCKED or UNLISTED.
languagestringDetected language (ISO 639-1).
previewImageUrlstringFeature image, 1200 px wide.
isShortformbooleanMedium short-form post.
authorId, authorName, authorUsername, authorUrlstringThe writer.
authorBio, authorFollowers, authorFollowing, authorImageUrlmixedWriter's bio, followers, following, photo.
authorIsMember, authorTwitterboolean, stringPaying Medium member; X/Twitter handle.
publicationId, publicationName, publicationSlug, publicationUrl, publicationFollowersmixedPublication the story appeared in (empty for personal-profile stories).
contentText, contentMarkdownstringArticle body (with includeContent). Member-only stories: the public preview.
contentIsPreviewbooleantrue when the body is the paywall preview, false when it is the complete story.
contentImageUrls, contentLinksstringImages and outbound links / embeds inside the article, pipe-separated.
codeBlockCount, paragraphCountnumberCode blocks and paragraphs in the body.
sourcestringWhich input produced the row: tag:<slug>, tag:<slug>/top-week, search:<query>, author:<username>, publication:<slug>, url.
ranknumberPosition in its source: search rank, position in a ranked list, or 1 = newest for chronological sources.
scrapedAtISO dateCollection time.

Response rows (rowType: "response")

FieldTypeDescription
id, urlstringResponse ID and URL (responses are small Medium stories).
textstringFull response text.
publishedAt, updatedAtISO dateWhen it was written / edited.
claps, voters, repliesCountnumberClaps, clappers, replies under it.
depthnumber1 = response to the story, 2 = reply to a response, …
parentPostId, rootPostId, rootPostUrlstringWhat it answers, and the story the thread belongs to.
authorId, authorName, authorUsername, authorUrl, authorFollowersmixedWho wrote it.

Author rows (rowType: "author")

id, name, username, url, bio, followers, following, imageUrl, isMember, memberSince, membershipTier (MEMBER / FRIEND), isPartnerProgram, isBookAuthor, twitter, customDomain, source, rank (search results only), scrapedAt.

Publication rows (rowType: "publication")

id, name, slug, url, domain, description, followers, imageUrl, twitter, tags, creatorName, creatorUsername, editors, editorsCount, source, rank (search results only), scrapedAt.

Tag rows (rowType: "tag")

id (slug), name, url, postCount (total stories in the tag), followers, source, rank (search results only), scrapedAt.


Example output

Real rows from test runs on 2026-10-13 (article text shortened here).

Post with full text (tags: ["productivity"], tagSort: "top-all-time", includeContent: true):

{
"rowType": "post",
"id": "5f26de35b84c",
"title": "You Shouldn’t Be Prompting AI Anymore. You Should Be Designing Loops.",
"subtitle": "Peter Steinberger built one of the fastest-growing open-source projects in history by doing something most developers were too busy to…",
"url": "https://aiadvances.org/you-shouldnt-be-prompting-ai-anymore-you-should-be-designing-loops-5f26de35b84c",
"canonicalUrl": "https://aiadvances.org/you-shouldnt-be-prompting-ai-anymore-you-should-be-designing-loops-5f26de35b84c",
"publishedAt": "2026-06-09T14:14:08.695Z",
"updatedAt": "2026-06-09T14:14:08.695Z",
"readingTimeMinutes": 11,
"wordCount": 2853,
"claps": 379,
"voters": 87,
"responsesCount": 9,
"tags": "software-development | artificial-intelligence | programming | productivity | technology",
"isMemberOnly": false,
"visibility": "PUBLIC",
"language": "en",
"previewImageUrl": "https://miro.medium.com/v2/resize:fit:1200/1*FpjCUf87cdd6H5sedbi0bg.png",
"isShortform": false,
"authorId": "106212946ead",
"authorName": "Aftab",
"authorUsername": "aftab001x",
"authorUrl": "https://medium.com/@aftab001x",
"authorBio": "AI",
"authorFollowers": 381,
"authorFollowing": 2,
"authorImageUrl": "https://miro.medium.com/v2/resize:fit:400/1*6EU4UFLYSEtZqDugnds7tQ.jpeg",
"authorIsMember": false,
"authorTwitter": null,
"publicationId": "3fe99b2acc4",
"publicationName": "AI Advances",
"publicationSlug": "ai-advances",
"publicationUrl": "https://aiadvances.org",
"publicationFollowers": 113201,
"contentText": "You Shouldn’t Be Prompting AI Anymore. You Should Be Designing Loops.\n\nPeter Steinberger built one of the fastest-growing open-source projects in history by doing something most developers were too busy to notice: he stopped talki …",
"contentMarkdown": "### You Shouldn’t Be Prompting AI Anymore. You Should Be Designing Loops.\n\n![](https://miro.medium.com/v2/resize:fit:1400/1*FpjCUf87cdd6H5sedbi0bg.png)\n\nPeter Steinberger built one of the fastest-growing open-source projects in hi …",
"contentIsPreview": false,
"contentImageUrls": "https://miro.medium.com/v2/resize:fit:1400/1*FpjCUf87cdd6H5sedbi0bg.png",
"contentLinks": null,
"codeBlockCount": 0,
"paragraphCount": 72,
"source": "tag:productivity/top-all-time",
"rank": 50,
"scrapedAt": "2026-10-13T10:37:17.858Z"
}

Response (comment):

{
"rowType": "response",
"id": "ad76cb0bf1bf",
"url": "https://medium.com/@libbyswinkler/there-are-good-recommendations-here-many-i-have-not-yet-consumed-ad76cb0bf1bf",
"text": "There are good recommendations here—many I have not yet consumed. I am saving this as a reading list. Thanks!",
"publishedAt": "2026-06-14T16:00:37.474Z",
"updatedAt": "2026-06-14T16:00:37.474Z",
"claps": 96,
"voters": 37,
"repliesCount": 1,
"depth": 1,
"parentPostId": "eed8d14f3bee",
"rootPostId": "eed8d14f3bee",
"rootPostUrl": "https://medium.com/the-useful-life/8-books-you-should-definitely-read-at-least-once-in-your-life-eed8d14f3bee",
"authorId": "af03698341e7",
"authorName": "Healthy Me Happy Me",
"authorUsername": "libbyswinkler",
"authorUrl": "https://medium.com/@libbyswinkler",
"authorFollowers": 727,
"source": "tag:productivity/top-all-time",
"scrapedAt": "2026-10-13T10:37:18.225Z"
}

Author profile (authors: ["@ev"]):

{
"rowType": "author",
"id": "268314bb7e7e",
"name": "Ev Williams",
"username": "ev",
"url": "https://medium.com/@ev",
"bio": "Curious human, cofounder @ Mozi, chairman @ Medium, partner @ Obvious Ventures",
"followers": 213261,
"following": 2699,
"imageUrl": "https://miro.medium.com/v2/resize:fit:400/1*Oa7aZoW8TPZrQjlKYzH5dg.jpeg",
"isMember": true,
"memberSince": "2017-02-13T19:37:08.000Z",
"membershipTier": "FRIEND",
"isPartnerProgram": true,
"isBookAuthor": false,
"twitter": null,
"customDomain": "ev.medium.com",
"source": "author:ev",
"scrapedAt": "2026-10-13T10:27:19.303Z"
}

Publication profile (publications: ["levelup.gitconnected.com"]):

{
"rowType": "publication",
"id": "5517fd7b58a6",
"name": "Level Up Coding",
"slug": "gitconnected",
"url": "https://levelup.gitconnected.com",
"domain": "levelup.gitconnected.com",
"description": "Coding tutorials and news. The developer homepage gitconnected.com && skilled.dev && levelup.dev",
"followers": 365226,
"imageUrl": "https://miro.medium.com/v2/resize:fit:400/1*5D9oYBd58pyjMkV_5-zXXQ.jpeg",
"twitter": "gitconnected",
"tags": "programming | artificial intelligence | software engineering",
"creatorName": "Trey Huffine",
"creatorUsername": "treyhuffine",
"editors": "treyhuffine | warlyware",
"editorsCount": 2,
"source": "publication:levelup.gitconnected.com",
"scrapedAt": "2026-10-13T10:27:18.690Z"
}

How much data can I get?

Measured on the Apify platform on 2026-10-13:

SourceHow deep it goesMeasured
Tag, newestThe whole tag history. Medium keeps a complete chronological archive per tag.rust-programming-language: 4,840 posts — every story back to Nov 2018 (Medium's own count: 4,830) in 34 s. programming: 10,000 posts in 40 s (the newest 15 days of a tag that gets ~330 posts a day).
Tag, ranked lists~100 posts per list (Medium's limit); all-top combines five lists.startup, all-top: 287 unique top posts in 4.5 s.
Search, posts~1,000 results per query (Medium's limit). Add more queries for more."rust" + "product management": 1,000 posts in 6.1 s.
Search, people / tags~1,000 per query."data science" people: 300 writers in 4.8 s.
Search, publications~500 per query.—
AuthorEvery story since the account started.Ev Williams: all 121 stories back to Aug 2012 in 3.5 s; two authors, 1,000 rows in 9.7 s.
PublicationEvery story in the publication.Level Up Coding: 1,000 posts in 8.2 s.
ResponsesAll responses and replies of a story (maxResponsesPerPost: 0).100 top stories + 1,899 responses and replies in 8.2 s.

Need tens of thousands of rows? Add more tags (each tag's archive is complete and independent), widen the date window, combine tags with searches, authors and publications, and set maxItems to 0 or a large number. Duplicates across sources are removed automatically. A 10,000-row run is routine.

Big runs and "Maximum cost per run". Every pay-per-event run on Apify has a maximum cost — the one you set in the run options, or the platform's default. Medium Scraper reads it at the start and plans for exactly the number of results it covers. If you ask for 20,000 rows but the run's maximum cost covers 11,000, it saves 11,000, ends as Succeeded and says so in the status message ("Saved 11000 results — this run's maximum cost ($…) covers 11000 results at the current price. Raise "Maximum cost per run" to get more."). It never fails or gets aborted for this. For 10,000+ rows, set "Maximum cost per run" to at least rows × price per result (Pricing tab).


Speed and resources per 1,000 rows

All measured on 2026-10-13, default settings:

RunRowsTimePeak memory
Prefilled example (tag, 100 rows)1004.2 s54 MB
Tag artificial-intelligence, newest1,0008.7 s60 MB
Tag programming, newest10,00039.8 s111 MB
Two tags with full article text10,000103 s216 MB
Search, 2 queries1,0006.1 s53 MB
Publication1,0008.2 s60 MB
Responses + replies2,0008.2 s60 MB
  • Metadata-only runs: about 4 s per 1,000 posts at scale.
  • With full article text: about 10 s per 1,000 posts; the text comes in the same requests, so it costs time and memory, not extra requests.
  • Memory: 1 GB default (it gives the run more CPU for article text); 512 MB is plenty for metadata-only runs.
  • No residential proxy needed. No browser.
  • What you pay: a fixed price per result — see the Pricing tab (on 2026-10-13: $1.50 per 1,000 results on the Free plan, down to $1.00 per 1,000 from the Gold plan up). Compute, storage and proxies are included; there is no separate proxy bill and no subscription.

Integrations

Run it from the API (cURL)

curl -X POST "https://api.apify.com/v2/acts/logiover~medium-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"tags":["artificial-intelligence"],"maxItems":100}'

Returns the rows as a JSON array. For long runs use the asynchronous /runs endpoint.

Node.js

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('logiover/medium-scraper').call({
tags: ['startup'],
includeContent: true,
maxItems: 500,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((r) => r.rowType === 'post').map((r) => `${r.claps}\t${r.title}`).join('\n'));

Python

from apify_client import ApifyClient
client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("logiover/medium-scraper").call(run_input={
"authors": ["@ev"],
"includeResponses": True,
"maxItems": 1000,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row["rowType"] == "post":
print(row["publishedAt"], row["claps"], row["title"])

Make, Zapier, n8n

Use the Apify app in Make, Zapier or n8n ("Run an Actor" → logiover/medium-scraper, then "Get dataset items"), e.g. new stories in a tag → Slack; a competitor publication → Notion or Airtable; scheduled daily with publishedAfter: "1 day".

Google Sheets

Export the dataset as CSV, or use Apify's Google Sheets integration to append every run's rows to a sheet automatically — ideal for a living content-research tracker.

Webhooks

Add a "Run succeeded" webhook and fetch https://api.apify.com/v2/datasets/{datasetId}/items?format=csv (or json, xlsx).

AI agents and MCP

Through Apify's MCP server, AI agents (Claude, ChatGPT, Cursor and other MCP clients) can call logiover/medium-scraper as a tool: "find the 50 most-clapped posts about RAG this month and summarise them". The Markdown output is ready for LLM context windows and RAG chunking.


Medium Scraper vs other ways to get Medium data

Medium ScraperMedium RSS feedsCopy-paste by handGeneric browser scrapers
Stories per tagComplete archive (thousands)Latest ~10As many as you can standUsually the first screen
Claps, clappers, responses countYesNoManuallySometimes
Search (posts / people / publications / tags)YesNoYes, slowlyRarely
Comments (responses + replies)Yes, full textNoManuallyRarely
Author & publication stats (followers, bio, editors)YesPartialManuallySometimes
Full article text as MarkdownYes (free stories complete)Partial HTMLYesHTML only
Speed10,000 posts in ~40 s—HoursSeconds per page
Login / cookies neededNoNoNoOften
ExportCSV, Excel, JSON, XML, Sheets, APIXML—Varies

Limits and tips

  • Member-only stories: Medium shows signed-out readers only the beginning of a paywalled story, and that is what you get (contentIsPreview: true). Titles, claps, word count and all metadata are complete. Use skipMemberOnly when you need complete text only. This Actor does not bypass the paywall.
  • Ranked lists and search have Medium's own ceilings (~100 per ranked list, ~1,000 per search query, ~500 per publication search). For more, use tagSort: "newest" (unlimited) or add queries.
  • Order: chronological sources are numbered newest-first in rank; rows can land in the dataset slightly out of order because they are written in parallel — sort by rank or publishedAt if order matters.
  • Exact limits: maxItems counts every row (posts, responses and profile rows). Turn off includeProfiles if you want posts only.
  • Fewer rows than maxItems means the sources ran out (e.g. an author with 120 stories), your filters excluded the rest, or duplicates across sources were removed. The run's status message and SUMMARY say which.
  • Date filters are cheap on chronological sources — the scraper starts and stops reading at your dates instead of filtering afterwards.

FAQ

Do I need a Medium account, login or cookies?

No. The Actor only reads what Medium shows to signed-out visitors. You never share credentials.

Is there an official Medium API for this?

Medium's official API was built for publishing stories and does not offer tag archives, search, claps or responses. This Actor is the practical Medium API alternative for reading public data, with a stable JSON output.

How many posts can I scrape from one tag?

All of them. tagSort: "newest" walks the complete tag archive back in time — measured 4,840 of 4,830 counted posts for rust-programming-language (the whole history since 2018) and 10,000 posts of programming in 40 seconds.

Can I get the full text of member-only (paywalled) stories?

You get the public preview Medium shows to signed-out readers, flagged with contentIsPreview: true. Free stories come complete (contentIsPreview: false). The Actor does not bypass the paywall.

How do I scrape all stories of a Medium author?

Put their @username or profile URL into Authors and set maxItems to 0. You get one profile row and every story, newest first. Custom subdomains like name.medium.com work too.

How do I scrape a Medium publication?

Put the slug (swlh for The Startup), URL or custom domain (levelup.gitconnected.com) into Publications. You get the publication's profile (followers, editors, description) and its stories, newest first.

Can I scrape Medium comments?

Yes — enable Include responses. Each response is a row with full text, claps, author and reply count; Include replies follows the threads below them. maxResponsesPerPost limits per story (0 = all).

How do I get only new stories since my last run?

Schedule the Actor with publishedAfter: "1 day" (or "6 hours", "1 week"). Use id to de-duplicate across runs.

How do I export Medium data to CSV, Excel or Google Sheets?

Open the run's Dataset tab and choose CSV, Excel, JSON, XML or HTML — or use the Google Sheets integration or the API URL with format=csv / format=xlsx. Pick a view (Posts, Article text, Responses, Authors, Publications, Tags) to export only those columns.

Why did I get fewer rows than maxItems?

The sources were exhausted (a small tag, an author with few stories, a search limit), your filters removed stories, the same story came from two sources and was kept once, or the run's Maximum cost per run covered fewer results. The run is still Succeeded; its status message and SUMMARY (stoppedBy) explain.

My big run stopped with a "maximum cost" message — what do I do?

Pay-per-event runs have a maximum cost per run (yours or the platform default). The scraper stops cleanly at the number of results that budget covers instead of being aborted. Raise Maximum cost per run in the run options (or maxTotalChargeUsd in the API) to at least rows × price per result and run again.

What happens if a tag, author or publication does not exist?

The run finishes as Succeeded with a message such as tag "xyz" does not exist on Medium, so your automation does not break. Other valid sources in the same run are scraped normally.

Do I need a proxy?

No setup needed. By default the Actor connects directly (fastest) and switches to Apify Proxy automatically if Medium ever refuses direct requests. You can force a specific proxy group in the input.

What does rank mean?

For search and ranked lists it is Medium's position; for chronological sources (tag archive, author, publication) it numbers stories newest-first, so rank: 1 is the newest story of that source.

Can I use the data to train AI models or build a RAG app?

The text of every story belongs to its author. Analysis, search indexes, summaries and internal research are common uses; republishing or training on copyrighted text may need permission depending on your jurisdiction and purpose. See the legality section below.

How fast is it really?

Measured 2026-10-13: 100 rows in 4 s, 1,000 posts in 6–10 s, 10,000 posts in 40 s, 10,000 posts with full article text in 103 s.

What if Medium changes something?

The Actor reads structured data from Medium's own web app endpoint, which changes far less often than page layouts. Runs report problems clearly instead of silently returning nothing, and issues are fixed fast — see support below.


This Actor collects only publicly available data that Medium shows to any signed-out visitor; it does not log in, does not bypass the paywall and does not collect private information. Web scraping of public data is generally lawful, but you are responsible for how you use the results:

  • Personal data (names, bios, social handles) may be protected by GDPR, CCPA and similar laws. Have a legitimate purpose and store only what you need.
  • Copyright: stories and responses belong to their authors. Quote, analyse and link responsibly; do not republish full articles without permission.
  • Respect Medium's terms and reasonable request volumes.

If in doubt, consult a lawyer about your specific use case.


Changelog

  • 2026-10-13 — first release. Tag archive (complete history), ranked tag lists, search (posts / people / publications / tags), authors, publications, story URLs, full article text as Markdown + plain text, responses with reply threads, author / publication / tag profile rows, date / claps / language / paywall filters, parallel time-sliced reading (10,000 posts in 40 s), exact maxItems, honest run outcomes, automatic proxy fallback.

Full history in the Changelog tab.


Support

Found a bug, need a field or a new source? Open an issue on the Issues tab — we answer within 24 hours. Please include the run ID so we can look at the exact run.


Disclaimer

Medium Scraper is an independent tool and is not affiliated with, endorsed by or sponsored by Medium or A Medium Corporation. "Medium" is a trademark of A Medium Corporation and is used here only to describe the website this tool works with. Use the data in line with applicable laws and Medium's terms.