๐ŸŽ‰ Premium Proxies ยท 24-Hour Free TrialClaim Now
Guides

How to Scrape Medium Articles: RSS, JSON, and Claps

Scrape Medium articles cleanly: pull stories from RSS feeds, read the ?format=json payload past its XSSI prefix, and collect tags, authors, and clap counts.

S SparkProxy 0 18 min read
Share
How to Scrape Medium Articles: RSS, JSON, and Claps

To scrape Medium articles you almost never need to fight Medium's React front end or its Cloudflare edge. Medium hands you three quieter interfaces: an RSS feed for every profile, publication, and tag; a ?format=json payload sitting behind almost every URL; and a block of JSON-LD baked into each article page. This guide shows how to read all three, how to pull the fields that only exist in one of them (clap counts, the member-only flag, per-tag post counts), how to get past the RSS 10-item cap, and the one parsing gotcha that makes json.loads fail on Medium every single time. Every request routes through SparkProxy's Scraping API, so IP rotation and geo-targeting are one parameter instead of an infrastructure project.

Key Takeaways

  • Medium exposes RSS feeds at medium.com/feed/@user, /feed/tag/, and /feed/, and each returns the full HTML body of public posts in content:encoded. No browser needed.
  • The ?format=json endpoint carries the fields RSS omits: virtuals.totalClapCount for claps, virtuals.tags with per-tag post counts, and isLocked for the paywall. Its response is prefixed with ])}while(1);, which you must strip before parsing.
  • Member-only stories return isLocked: true and only a preview in RSS. Scrape public content, skip the locked bodies, and never republish full article text.

What you can pull: stories, tags, authors, claps

Medium spreads its data across the three interfaces unevenly. Some fields live in every one, some in exactly one. This table is the map, and it is the thing most tutorials never lay out.

DataBest sourceField or pathNotes
Story titleRSS or JSON`title` / `payload.value.title`Present everywhere
Story URLRSS`link` (strip `?source=`)The canonical post URL
Full HTML bodyRSS`content:encoded`Public posts only
Author nameRSS or JSON`dc:creator` / `references.User[id].name`JSON adds username, bio
TagsRSS or JSON`category` / `virtuals.tags[].slug`RSS caps at 5 tags
ClapsJSON only`virtuals.totalClapCount`Absent from RSS and JSON-LD
ResponsesJSON only`virtuals.responsesCreatedCount`Comment count
Reading timeJSON only`virtuals.readingTime`Minutes, as a float
Member-only flagJSON`value.isLocked`Respect the paywall
Publish dateRSS or JSON-LD`pubDate` / `datePublished`RFC 822 vs ISO 8601

The headline takeaway: if you want claps, tags with post counts, or the paywall flag, RSS alone will not get you there. You need the JSON endpoint. If you want the full body of a public story, RSS is the cheapest path because it ships the HTML in content:encoded.

Free trial

Scraping at scale? Skip the blocks.

Fast, unblockable datacentre proxies with unlimited bandwidth.

The Medium RSS feeds

Every Medium profile, publication, and tag has an RSS feed. The feeds return clean RSS 2.0 XML, they include the full post body for public stories, and they never require rendering. This is the same feed-first approach that makes an aggregator like Google News scriptable, covered in How to Scrape Google News.

FeedURL pattern
User profile`https://medium.com/feed/@username`
Publication (on medium.com)`https://medium.com/feed/publication-slug`
Publication (custom domain)`https://blog.example.com/feed`
Tag`https://medium.com/feed/tag/python`
Sitewide latest`https://medium.com/feed/latest`

Each carries title, link, a guid of the form https://medium.com/p/, one per tag, for the author, pubDate, and with the body HTML. The @ in a profile feed is required; medium.com/feed/username without it will not resolve.

One hard limit shapes everything downstream: a Medium RSS feed returns only the latest 10 items and does not paginate. For a low-frequency monitor that is fine. For a backfill you need the archive pages in the pagination section below.

The ?format=json endpoint and the )}while(1) prefix

Append ?format=json to almost any Medium URL and you get that page's underlying data as JSON: a profile, a single post, a tag page, a publication. This is where claps, the isLocked paywall flag, reading time, and richly-typed tags live. It is the same "hidden JSON behind the HTML" technique described in How to Scrape Hidden JSON API Endpoints, with one Medium-specific twist that trips up everyone the first time.

Medium does not return clean JSON. It prefixes every response with an anti-hijacking guard:

])}while(1);</x>{"success":true,"payload":{ ... }}

That leading ])}while(1); is deliberate. It is XSSI (cross-site script inclusion) protection: if some other site tries to load the URL as a