Medium API

Get Medium article text and tag feeds as clean JSON

The Medium API returns author and article data as clean JSON.

no credit card1,000 free credits · instant API key · pay by card or crypto
Missing a Medium endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
M
/medium/v1

20 active endpoints. Every call is 1 credit.

  • POST/medium/v1/user
  • POST/medium/v1/user_id
  • POST/medium/v1/user_articles
  • POST/medium/v1/user_top_articles
  • POST/medium/v1/article
  • POST/medium/v1/article_content
  • POST/medium/v1/article_html
  • +13 more

What Medium endpoints does ReefAPI ship?

20 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

20 endpoints

user

1 cr

Public Medium user profile by username.

required
user
optional

user_id

1 cr

Resolve username to Medium userId.

required
user
optional

user_articles

1 cr

An author's published articles, newest first, with deep pagination.

required
user
optional
limit, cursor

user_top_articles

1 cr

User articles sorted by clap count from profile references.

required
user
optional
limit

article

1 cr

Article metadata by url or id.

required
optional
url, id

article_content

1 cr

Article plain-text body from bodyModel paragraphs.

required
optional
url, id

article_html

1 cr

Article HTML body from bodyModel paragraphs.

required
optional
url, id

article_markdown

1 cr

Article markdown body from bodyModel paragraphs.

required
optional
url, id

article_responses

1 cr

Public responses/comments for an article.

required
optional
url, id, limit, cursor

publication

1 cr

Publication/collection metadata by slug.

required
slug
optional

publication_id

1 cr

Resolve publication slug to collection id.

required
slug
optional

publication_articles

1 cr

A publication's articles, newest first, with deep pagination.

required
slug
optional
limit, cursor

tag

1 cr

Latest posts for a topic tag (the tag/topic feed).

required
tag
optional
limit

search_users

1 cr

Look up an author by exact username.

required
q
optional

search_publications

1 cr

Look up a publication by exact slug.

required
q
optional

search_tags

1 cr

Check whether a topic tag exists and is active on Medium (resolves q as a tag slug).

required
q
optional

followers

1 cr

An author's followers (paginated).

required
optional
user, user_id, limit, cursor

following

1 cr

The authors a user follows (paginated).

required
optional
user, user_id, limit, cursor

list

1 cr

Reading list metadata and articles from public list page HTML.

required
optional
id, url, user, username, slug, limit

search_articles

1 cr

Search Medium articles by keyword.

required
q
optional
limit, cursor

Every parameter, every allowed value →

Medium API

3 of 20 endpoints, ready to run

View docs ↗

The freshest surface on Medium: the latest posts under a topic tag, with the newest of them usually minutes old.

1 credit1 required · 1 optional
POST/medium/v1/tag
ok390 ms · 10 records · sample
{
  "ok": true,
  "meta": {
    "api": "medium",
    "endpoint": "tag",
    "mode": "live",
    "latency_ms": 390,
    "record_count": 10,
    "cache_hit": false
  },
  "data": {
    "tag": "machine-learning",
    "posts": [
      {
        "id": "165b29e5df7e",
        "title": "Building a Grounded Shopping Assistant on Algolia Agent Studio",
        "url": "https://levelup.gitconnected.com/building-a-grounded-shopping-assistant-on-algolia-agent-studio-165b29e5df7e?source=rss------machine_learning-5",
        "published_at": "Fri, 28 Aug 2026 17:21:58 GMT",
        "description": "<div class=\"medium-feed-item\"><p class=\"medium-feed-image\"><a href=\"https://levelup.gitconnected.com/building-a-grounded-shopping-assistant-on-algolia-agent-studio-165b29e5df7e?source=rss------machine_learning-5\"><img src=\"https://cdn-images-1.medium.com/max/2048/1*Zyv-8XQYnhlya5_QGfMjGA.png\" width=\"2048\"></a></p><p class=\"medium-feed-snippet\">Shoppers have mostly stopped typing keywords. They write out a full sentence now, like &#x201C;a lightweight camera under $300 for travel.&#x201D;</p><p class=\"medium-feed-link\"><a href=\"https://levelup.gitconnected.com/building-a-grounded-shopping-assistant-on-algolia-agent-studio-165b29e5df7e?source=rss------machine_learning-5\">Continue reading on Level Up Coding »</a></p></div>"
      },
      {
        "id": "da98f986e22d",
        "title": "The Internet Is Slowly Poisoning the AI Models Being Trained on It",
        "url": "https://levelup.gitconnected.com/the-internet-is-slowly-poisoning-the-ai-models-being-trained-on-it-da98f986e22d?source=rss------machine_learning-5",
        "published_at": "Fri, 28 Aug 2026 17:21:19 GMT",
        "description": "<div class=\"medium-feed-item\"><p class=\"medium-feed-image\"><a href=\"https://levelup.gitconnected.com/the-internet-is-slowly-poisoning-the-ai-models-being-trained-on-it-da98f986e22d?source=rss------machine_learning-5\"><img src=\"https://cdn-images-1.medium.com/max/2600/0*BMlxQjlmgd7FSW6R\" width=\"3840\"></a></p><p class=\"medium-feed-snippet\">Every piece of AI-generated content that goes online becomes training data for the next model. Researchers have a name for what happens&#x2026;</p><p class=\"medium-feed-link\"><a href=\"https://levelup.gitconnected.com/the-internet-is-slowly-poisoning-the-ai-models-being-trained-on-it-da98f986e22d?source=rss------machine_learning-5\">Continue reading on Level Up Coding »</a></p></div>"
      },
      {
        "id": "4f09b8e4168b",
        "title": "Scientists Opened the AI Black Box. What They Found Was Surprising.",
        "url": "https://medium.com/data-science-collective/scientists-opened-the-ai-black-box-what-they-found-was-surprising-4f09b8e4168b?source=rss------machine_learning-5",
        "published_at": "Fri, 28 Aug 2026 17:19:01 GMT",
        "description": "<div class=\"medium-feed-item\"><p class=\"medium-feed-image\"><a href=\"https://medium.com/data-science-collective/scientists-opened-the-ai-black-box-what-they-found-was-surprising-4f09b8e4168b?source=rss------machine_learning-5\"><img src=\"https://cdn-images-1.medium.com/max/2000/0*11zIZN5ycfLosYMt.jpg\" width=\"2000\"></a></p><p class=\"medium-feed-snippet\">We&#x2060; bui&#x2060;l&#x200C;t AI system&#x2060;s that&#x200D; work a&#x200D;s&#x200B;tonishin&#x2060;gly wel&#x200B;l, and for years, no&#x200D;body&#x200D; could say how. I&#x200B;nside was a &#x201C;black box&#x201D;:&#x200D; billions of&#x2026;</p><p class=\"medium-feed-link\"><a href=\"https://medium.com/data-science-collective/scientists-opened-the-ai-black-box-what-they-found-was-surprising-4f09b8e4168b?source=rss------machine_learning-5\">Continue reading on Data Science Collective »</a></p></div>"
      }
    ]
  }
}
Real response, fetched from the live endpoint with the parameters on the left — trimmed to the first few rows, with seller names left out. Press Try it for the untrimmed response.

How the Medium API works

Medium is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 184 engines.

02
Call
POST /medium/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
1 credit per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

A tag feed into full article text, two calls

The tag feed is where new writing appears first; the body actions turn any row of it into text you can index. Neither one asks you to be signed in.

01tag
POST/medium/v1/tag
{"tag": "machine-learning", "limit": 10}

Ten of the newest posts under the topic in 0.4 seconds — the fastest call in this batch — each with a title, a URL and an RFC-2822 publication date.

02article_markdown
POST/medium/v1/article_markdown
{"url": "<the url from any row>"}

The body as markdown with a paragraph_count beside it. A freely readable story returned 67 paragraphs and 16,306 characters in 1.4 seconds.

A topic feed and the full text under it, refreshed as often as you like, with no Medium account and no membership on your side. The one hard limit is measured below.

request
curl -X POST https://api.reefapi.com/medium/v1/tag \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"tag":"python"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "medium",
    "endpoint": "tag",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

Medium ids, timestamps and the paywall you cannot see

Medium has no paywall flag in this response, two different date formats depending on which action you call, and two different pagination cursor shapes. Measured 2026-08-27 against @dhh, the Signal v. Noise publication and the python and machine-learning tag feeds.

FieldWhat it holdsMeasured 2026-08-27
Article id12 lowercase hex characters, the tail of the URL slug41adf356857f, from .../reconsider-41adf356857f
user_id and collection_idThe same 12-hex shape as an article iddhh is 54bcbf647830; Signal v. Noise is 668e14b18fb1
published_at and created_atUnix epoch MILLISECONDS, not seconds1446644507775 is 2015-11-04
published_at from the tag actionAn RFC-822 date string instead, because that surface is the topic feed"Wed, 26 Aug 2026 22:02:12 GMT"
reading_timeFractional minutes, not a rounded integer11.599056603773585 on a 2,822-word post
word_count against the returned bodyword_count is Medium's full count; a member-only post returns only a free previewOne tagged post: word_count 1,338 against 160 body words. Five siblings returned 98 to 101%
next_cursor on user_articles and publication_articlesAn epoch-milliseconds string"1545257107680"
next_cursor on article_responsesoffset:id, a different shape entirely"45:ade9442ee53d"
collection_idNon-null means the post was published in a publication, and its URL sits under the publication pathRECONSIDER lives at /signal-v-noise/..., not /@dhh/...
Publication slugFollows renames, so the returned slug can differ from the one you sentslug "towards-data-science" came back as slug "data-science", name "TDS Archive"
Body formatsarticle_content, article_html and article_markdown return the same paragraphs in three encodingsSame post, 67 paragraphs: 16,272 chars plain, 16,689 HTML, 16,306 markdown

publication.created_at came back null on all three publications measured, and publication.url is inconsistent: a custom-domain publication returned "betterprogramming.pub" with no scheme while medium.com-hosted ones returned a full https URL. Normalize it before using it as a link.

How much of an article you actually get, and where the paywall stops it

Measured on 2026-08-28 across one tag feed, two articles, an author archive and a publication. Two of these lines go against us.

No Medium account and no membership on your side

You send a ReefAPI key and a tag, a URL or a slug. There is no Medium login of yours, no membership of yours and no cookie of yours in the path, so nothing of yours can be rate-limited or restricted. This is also the fastest engine in the batch — the tag feed answered in 0.4 seconds and the body actions in about 1.5.

🔴 A member-only story returns its public preview, not the whole thing

Against us, and the number to check is paragraph_count. A freely readable story returned 67 paragraphs and 16,306 characters of markdown. A member-only story from a large publication, through the identical call, returned 8 paragraphs and 1,213 characters — the preview Medium shows a signed-out reader. Same shape, same latency, a twelfth of the text. Nothing you can pass changes that: what sits behind the paywall stays behind it, and we would rather you learn that here than after you have indexed a corpus of previews.

The body comes in three renderings of the same call

Plain text, HTML and markdown are three separate actions over the same paragraph model, so you can take whichever your pipeline wants without post-processing ours. Each returns the article's metadata block alongside the body and a paragraph count you can assert on.

The tag feed is the freshest surface, and it serves ten

Asking for 25 returned 10, twice, on two different tags — that is the feed's own size rather than a clamp of ours. In exchange it is genuinely live: the newest row on one pull was timestamped minutes before the call. Every row carries an RFC-2822 publication date and the author's name.

Archives page with a cursor, in small pages

An author's archive returned 4 articles with next_cursor and has_more true; the next cursor returned 4 more. A large publication returned 11. The rows are rich where the feed rows are thin — claps, reading time, word count, created_at and published_at as separate epoch milliseconds, the full tag list and the response count.

🔴 Article search is a discovery hop, not a corpus

Against us. Search returned exactly 20 rows for two different queries whatever limit we asked for, with next_cursor null and has_more false — and each row carried only an id, a title, a slug and a URL. No date, no author, no claps. Use it to find URLs and hydrate them with the article actions; do not plan a dataset on it.

People, publication and tag search resolve exact names only

Medium gates fuzzy search behind its signed-in app, and these actions say so rather than faking it: they take the query as a username, a publication slug or a tag slug and return that one thing. Renamed slugs still resolve — one well-known publication slug came back as the archive it now points at, with its 828,219 subscribers.

Responses are a thread, and they carry claps

Twenty-five responses to one article in 1.5 seconds, each with its own title, text, clap count, timestamp and URL, plus a cursor for the rest. It is the discussion layer, returned in the same shape as the articles above it.

What comes back, and what does not

Published articles and their text, public author and publication metadata, public reading lists and public responses. Not drafts, not a reader's history, not the paywalled remainder of a member-only story — the row above says exactly how much of one you get.

What people build with Medium

The jobs this data is most often used for.

20

endpoints

1

credit per call

01

Content research calls user_articles to study an author's output.

02

Author-intelligence uses user and user_top_articles to profile a writer.

03

RAG pipelines use article_content to ingest a post as clean text.

What Medium data costs

The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 184 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/medium/v1/tag \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"tag":"python"}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/medium/v1/tag",
    headers={"x-api-key": REEF_KEY},
    json={
  "tag": "python"
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up Medium.

Get a free key →
What is a Medium post id and where do I find it?

It is the 12-character lowercase hex string at the end of every article URL. In https://medium.com/signal-v-noise/reconsider-41adf356857f the id is 41adf356857f. The article action takes either id or url, and on 2026-08-27 both returned identical objects. User ids and publication (collection) ids use the same 12-hex format, so a bare id on its own does not tell you what kind of object it points at.

Are Medium timestamps in seconds or milliseconds?

Milliseconds, on every action except one. created_at and published_at come back as epoch milliseconds, so 1446644507775 is 2015-11-04, and dividing by 1000 first is the usual fix for a date that lands in 1970. The exception is the tag action, which reads the topic feed and returns published_at as an RFC-822 string like "Wed, 26 Aug 2026 22:02:12 GMT". If you merge tag results with article results, normalize the dates first.

Is there a member-only or paywall flag on an article?

No. The article object has fourteen keys and none of them marks a post as member-only. What you can do is compare word_count against the body you actually got. On 2026-08-27, five of six posts pulled from the machine-learning feed returned 98 to 101% of their stated word_count, and the sixth returned 160 words against a word_count of 1,338. That twelve-percent ratio is the free preview of a locked post. paragraph_count in meta is a useful second signal: the truncated post had 9 paragraphs, the full ones had 54 and more.

Why is reading_time a decimal?

It is Medium's raw estimate in minutes and it is not rounded: a 2,822-word post returned 11.599056603773585 and a 564-word post returned 2.128301886792453. Round it yourself for display. The underlying arithmetic is roughly 265 words a minute plus image time, which is why it never lands on a whole number.

Why did user_articles return four articles when I asked for ten?

Because limit is an upper bound on one page of the profile stream, not a guarantee. Asking for 10 from @dhh returned 4 articles with has_more true and a next_cursor, even though that profile's posts_published_count is 191. Keep passing the previous response's next_cursor until has_more goes false. Ordering on page one is not strictly newest-first either: the first item returned was from 2015 and the second from 2019, because the profile's featured post leads the stream.

Does user_top_articles give me an author's all-time most-clapped posts?

No, and the difference matters. It sorts the same profile-stream page by clap count rather than asking Medium for a global ranking. Measured on @dhh, both actions returned the same four articles, with user_top_articles reordering them to 31,648 / 4,322 / 3,479 / 1,424 claps. For a genuine all-time top you need to page through user_articles with next_cursor and sort the full set yourself.

How do I tell an author's own post from one published in a publication?

Read collection_id. When it is null the post sits on the author's profile at medium.com/@handle. When it is set, the post was published in that publication and its URL uses the publication path: RECONSIDER carries creator_id 54bcbf647830 (dhh) and collection_id 668e14b18fb1, and lives at medium.com/signal-v-noise/reconsider-41adf356857f. The publication action turns a slug into that same id, so you can join the two.

What does a Medium response look like in the data?

A response is itself a post, not a comment record. Each one has its own 12-hex id, its own URL under the responder's handle, a clap count and a created_at in milliseconds. The title field is an auto-generated truncation of the opening line, so it often repeats the start of text. Responses page with a cursor shaped offset:id, for example "45:ade9442ee53d", which is a different format from the epoch cursor used by user_articles.

What is the Medium API?

Medium API is a ReefAPI endpoint group for medium It returns live JSON through POST requests under /medium/v1.

Is the Medium API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. Medium calls use the same shared credit balance as every other ReefAPI engine.

Do I need a Medium login or account?

No login to Medium is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the Medium data?

The page example is captured from a live user call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the Medium API use?

Medium actions currently cost 1 credit per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call Medium from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call medium actions with the same key, credit pool and JSON envelope used by normal REST requests.

10 Social Media APIs on the same key

One key, one credit pool, one response envelope. If you are pulling Medium, you are one call away from the rest of the category — no second contract, no second integration.

Already paying for something else?Medium vs Apify

Need something this API does not do?

Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.

0/4000

No account needed · we reply from [email protected]

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 183 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-28.