# Medium Articles Scraper (Tags, Authors, No Login) (`locaihost/medium-scraper`) Actor

Scrape Medium articles by tag, author, publication or link: title, publish date, claps, responses, reading time, word count, member-only flag, author and tags, plus the full text of free posts. Tag feeds in latest, recommended or top order. Only-new mode. No login. $0.50 per 1,000 posts.

- **URL**: https://apify.com/locaihost/medium-scraper.md
- **Developed by:** [locaihost data](https://apify.com/locaihost) (community)
- **Categories:** News, Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.28 / 1,000 posts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Medium Articles Scraper (Tags, Authors, No Login)

Scrape Medium posts by tag, author, publication or link: one row per post with title, publish date, claps, responses, reading time, word count, member-only flag, author and tags, plus the full text of free posts when you want it, as JSON, CSV or Excel. No login, no cookies, no API key.

- **Monitor a topic:** the newest or most clapped posts on any tag, every day.
- **Follow writers and publications:** a scheduled run returns only their new posts.
- **Research content that works:** compare claps, responses and reading time across a tag's top posts of the week, month, year or all time.
- **Feed a reading list or newsletter:** titles, links and the text of free posts in one table.

### Quick start

Paste this into the **JSON** tab of the input and click **Start**:

```json
{"tags": ["programming"], "maxPostsPerSource": 25}
```

You get the 25 newest posts tagged programming in under 10 seconds. More examples:

```json
{"tags": ["startup", "product-management", "data-science"], "tagSort": "top-year", "maxPostsPerSource": 50}
```

```json
{"authors": ["@username"], "publications": ["https://medium.com/some-publication"], "maxPostsPerSource": 20, "includeBody": true, "onlyNew": true}
```

The first returns the most clapped posts of the year on three topics; the second is a daily watch on a writer and a publication that returns only new posts, with the text of the free ones.

### What data can I get?

| Group | Fields |
|---|---|
| Post | `postId`, `title`, `subtitle`, `url`, `publishedAt`, `updatedAt`, `tags`, `previewImage`, `isMemberOnly` |
| Numbers | `claps`, `responses` (counted, not collected), `readingTimeMinutes`, `wordCount` |
| Author | `authorName`, `authorUsername`, `authorUrl` |
| Publication | `publicationName`, `publicationSlug`, `publicationUrl` |
| Text | `bodyText`: plain text of free posts with `includeBody` (headings, paragraphs, lists and quotes kept; image captions and link cards dropped). Always null for member-only posts |
| Source | `type`, `sourceType` (`tag`, `author`, `publication`, `post`), `source`, `scrapedAt` |

Sources can be tags (names or tag links, read in the order you pick with `tagSort`: latest, recommended, or top of the week, month, year or all time), authors (`@username`, profile links or username.medium.com), publications (medium.com links, their own domains or slugs) and single post links.

One real row (tag "programming", run on 2026-10-18, shortened):

```json
{
  "type": "post",
  "postId": "03b92da9da9f",
  "title": "9 Things Senior Developers Never Ignore",
  "url": "https://medium.com/skillstuff/9-things-senior-developers-never-ignore-03b92da9da9f",
  "publishedAt": "2026-10-18T03:41:28.046Z",
  "claps": 5,
  "responses": 0,
  "readingTimeMinutes": 15.1,
  "wordCount": 3956,
  "isMemberOnly": true,
  "authorName": "CodeByUmar",
  "authorUsername": "codebyumar",
  "publicationName": "Skill Stuff",
  "publicationUrl": "https://medium.com/skillstuff",
  "tags": ["programming", "software-development", "coding", "software-engineering", "web-development"],
  "bodyText": null,
  "sourceType": "tag",
  "source": "programming"
}
```

The dataset has two views (**Posts** and **Not found (free)**) and exports to JSON, CSV, Excel or HTML. The run's `SUMMARY` record counts posts per source.

### How much does it cost?

You pay per post returned. There is no charge for Apify platform usage on top, and post text is included.

| Row | Free and Starter | Scale | Business |
|---|---|---|---|
| Post | $0.50 per 1,000 | $0.375 per 1,000 | $0.275 per 1,000 |

Plus $0.00005 per run start. **Apify's free $5 monthly credit covers about 10,000 posts.** Free-plan runs stop at 500 posts each; any paid Apify plan removes the cap.

**What's free:** tags, authors, publications or links that can't be found (a free row says so), posts skipped by `onlyNew`, and a post that turns up in two of your sources (one row per post per run). To cap a run's spend, set `maxResults` or **Maximum cost per run** in the run options: the run stops cleanly at that amount.

### Limits, stated up front

- **Member-only posts:** you get the title, date, claps, responses, reading time and link, never the text. Members-only content stays members-only.
- **How deep each source goes:** Medium shows about 100 posts per tag list (per order), so a tag returns at most about 100 latest and 100 top posts each run; schedule it daily with `onlyNew` to build up more. Author and publication pages go back years: `maxPostsPerSource: 0` reads up to 5,000 posts per source, and `postedAfter` keeps it to what's new.
- **Order:** publication home pages list featured posts first, then the rest by date. Author pages and the `latest` tag order are newest first.
- **Search is not offered:** Medium asks crawlers to stay off its search pages, so use tags instead.
- **Responses are counted, not collected.** No commenter names or response text.
- **Post text can occasionally be missing.** If a free post's text can't be read, the row still comes back with `bodyText: null` and the run's status message counts it.
- Data comes from the pages and data medium.com loads for any logged-out reader.

### Only new since last run, and schedules

Turn on `onlyNew`, save the input as a task and add a schedule under **Schedules** in Apify Console. Each run returns, and charges for, only posts that earlier runs with the same sources and tag order did not return; skipped posts cost nothing. Use `postedAfter` (a date such as `2026-10-01`, or `24 hours`, `7 days`, `2 weeks`, `3 months`) to limit any run to recent posts, and `memberOnly` (`free` or `member`) to keep one kind.

### Integrations: API, n8n, Make and AI agents

**API.** Run it and get the rows back in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/locaihost~medium-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tags": ["data-science"], "tagSort": "top-week", "maxPostsPerSource": 20}'
```

Apify's API clients for Python and JavaScript work the same way.

**n8n, Make, Zapier, Google Sheets, Slack, webhooks.** Apify's built-in integrations send each run's dataset wherever you need it, for example a daily Slack message with new posts from the writers you follow.

**AI agents (MCP).** Add this Actor to Claude, Cursor or any MCP client with `https://mcp.apify.com/?tools=locaihost/medium-scraper`, then ask something like *"What were the most clapped Medium posts about product management this month?"*

### FAQ

#### How much does it cost to scrape Medium?

$0.50 per 1,000 posts on the Free and Starter plans, less on Scale and Business, with post text included. Apify's free $5 monthly credit covers about 10,000 posts.

#### Can I use it through the API or from Python?

Yes. Use the `run-sync-get-dataset-items` call above, or Apify's Python and JavaScript clients. Every run's data is also available as JSON, CSV or Excel from its dataset.

#### Can I use it from an AI agent?

Yes. Through the Apify MCP server (`https://mcp.apify.com/?tools=locaihost/medium-scraper`) any MCP client can call it with tags, authors or publications and read the rows back.

#### Is it legal to scrape Medium?

The Actor reads the public pages and data medium.com loads for any logged-out reader. It never logs in, never reads member-only text and never collects responses or commenters. Posts belong to their writers: use the data for research, media monitoring and content discovery, and respect copyright, Medium's terms and the laws that apply to you. Medium's published licence file does not allow its content to be used to train models. You are responsible for how you use the results. If you are a writer or Medium and want something changed, open an issue and we will act on it promptly.

#### Why are some fields empty?

`bodyText` is null unless `includeBody` is on, and always null for member-only posts. `subtitle`, `publicationName` and `previewImage` are empty when the post has none, and new posts often show 0 claps.

### More from locaihost data

- [YouTube Transcript Scraper](https://apify.com/locaihost/youtube-transcripts): transcripts from videos, channels and playlists for the same topic research.
- [Google Trends Scraper](https://apify.com/locaihost/google-trends): see whether the topics you track are rising in search.
- [People Also Ask Scraper](https://apify.com/locaihost/people-also-ask): the questions people search about a topic, for your next post.
- [Doc to Markdown](https://apify.com/locaihost/doc-to-markdown): turn PDFs and office documents into clean Markdown.

### Did it help?

If this saved you time, a quick rating on the Store helps other people find it.

### Support

Something not working, or a field you need? Open an issue on the **Issues** tab: we answer issues within 24 hours.

# Changelog

This Actor's version history is a separate document: https://apify.com/locaihost/medium-scraper/changelog.md

# Actor input Schema

## `tags` (type: `array`):

Medium tags, e.g. programming, data-science, startup, or a tag link (https://medium.com/tag/programming).

## `tagSort` (type: `string`):

Which of a tag's lists to read: the newest posts, Medium's recommended ones, or the most clapped this week, month, year or ever.

## `authors` (type: `array`):

Medium writers: @username, a profile link (https://medium.com/@username) or a username.medium.com address. Returns their newest posts.

## `publications` (type: `array`):

Medium publications: a link (https://medium.com/better-programming), its own domain (https://betterprogramming.pub) or its slug.

## `posts` (type: `array`):

Links to single posts, on medium.com, a username.medium.com address or a publication's own domain.

## `maxPostsPerSource` (type: `integer`):

Most posts to return from each tag, author or publication. 0 = as many as Medium lists: about 100 per tag list, up to 5,000 for an author or publication.

## `postedAfter` (type: `string`):

Only posts published after this: a date (2026-10-01) or a span back from now (24 hours, 7 days, 2 weeks, 3 months). Empty = no date limit.

## `memberOnly` (type: `string`):

Member-only posts are for paying Medium members: you get their title, date, claps, responses, reading time and link, never their text.

## `includeBody` (type: `boolean`):

Add the full text of each free post as plain text. Member-only posts never include text.

## `onlyNew` (type: `boolean`):

Skip posts this same setup returned before, so a scheduled run returns (and charges for) new posts only.

## `maxResults` (type: `integer`):

Stop after this many posts. 0 = no limit.

## Actor input object example

```json
{
  "tags": [
    "programming",
    "data-science",
    "startup"
  ],
  "tagSort": "latest",
  "authors": [
    "@username",
    "https://medium.com/@username"
  ],
  "publications": [
    "https://medium.com/better-programming",
    "https://betterprogramming.pub"
  ],
  "posts": [
    "https://medium.com/better-programming/5-engineering-lessons-from-early-stage-startups-3f6657d11af"
  ],
  "maxPostsPerSource": 25,
  "postedAfter": "7 days",
  "memberOnly": "all",
  "includeBody": false,
  "onlyNew": false,
  "maxResults": 0
}
```

# Actor output Schema

## `posts` (type: `string`):

One row per post: title, date, claps, responses, reading time, member-only flag, author, publication, tags, link.

## `full` (type: `string`):

Every field of every row, including free text when asked and free not-found rows.

## `summary` (type: `string`):

Counts, free rows, anything that failed, and cost.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "tags": [
        "programming"
    ],
    "maxPostsPerSource": 25
};

// Run the Actor and wait for it to finish
const run = await client.actor("locaihost/medium-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "tags": ["programming"],
    "maxPostsPerSource": 25,
}

# Run the Actor and wait for it to finish
run = client.actor("locaihost/medium-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "tags": [
    "programming"
  ],
  "maxPostsPerSource": 25
}' |
apify call locaihost/medium-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,locaihost/medium-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/WamG1NBswDdY0HgBB/builds/GTMW3zOpAstPYLuwq/openapi.json
