# Medium Articles Scraper · Claps per Follower + Outlier Posts (`thequietstack/medium-scraper`) Actor

Scrape Medium articles by tag, keyword, author or publication and see which ones really work: claps, clappers, responses, claps per 1,000 author followers and claps vs. the author's own median. Reading time, member-only flag, author and publication profiles. No login.

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

## Pricing

from $4.00 / 1,000 scraped articles

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 · Claps per Follower + Outlier Posts

Scrape Medium articles by **tag**, **keyword**, **author** or **publication** — and see **which ones actually work**. Every article row carries its claps, the number of distinct people who clapped, responses, **claps per 1,000 author followers** and **how it compares with the author's own median**. Authors and publications get a profile row with followers, posting frequency and median engagement. No login, no API key, no cookies.

Built for content strategists, ghostwriters, newsletter and Medium writers researching what to write next, marketers looking for writers to partner with, and anyone who needs Medium data with engagement instead of a bare RSS list.

### Why this scraper

- **Reach is not resonance.** Big accounts get claps because they are big. `clapsPer1kFollowers` and `vsAuthorMedian` separate the articles that *outperformed their author* from the ones that just rode a large following. Measured on 24 Sep 2026: *Software 2.0* by Andrej Karpathy has **61,025 claps = 33.9× his own median** of 1,800.5; in the `ai agents` search, a post by a writer with **442 followers** got **572 claps — 71.5× that writer's median of 8**.
- **Claps vs. clappers.** One reader can clap up to 50 times. We return `claps` **and** `clappers` (distinct people) plus `clapsPerClapper`, so a handful of heavy clappers cannot pass as broad interest.
- **Real engagement numbers, not RSS.** RSS feeds carry titles and dates only — no claps, no responses, no reading time, no member-only flag. This Actor reads Medium's public web API, the same one medium.com uses for logged-out visitors.
- **Member-only flag without the paywall.** `isMemberOnly` shows which articles sit behind Medium's paywall; filter with `memberOnly: "free"` or `"memberOnly"`. We return metadata and counters only, never paywalled text.
- **Filters that save money.** `publishedWithinDays`, `minClaps`, `memberOnly`. Filtered-out articles are **never charged**. Hard limits `maxArticles` / `maxProfiles` stop the run cleanly — you are never charged beyond them.
- **Tag feeds by time window.** `TOP_WEEK`, `TOP_MONTH`, `TOP_YEAR`, `HOT` or `NEW` — plus the tag's total article and follower count in the run summary.

### Input example

```json
{
    "tags": ["product-management"],
    "tagFeedMode": "TOP_MONTH",
    "searchTerms": ["ai agents"],
    "authors": ["@karpathy"],
    "publications": ["netflixtechblog.com"],
    "maxArticlesPerSource": 50,
    "publishedWithinDays": 90,
    "minClaps": 10
}
```

### Output example (article row, measured 24 Sep 2026)

```json
{
    "type": "article",
    "title": "Software 2.0",
    "url": "https://karpathy.medium.com/software-2-0-a64152b37c35",
    "authorName": "Andrej Karpathy",
    "authorFollowers": 61927,
    "publishedAt": "2017-11-11T22:18:53.751Z",
    "readingTimeMinutes": 8.8,
    "wordCount": 2146,
    "isMemberOnly": false,
    "tags": ["machine-learning", "artificial-intelligence", "programming", "software-development", "future"],
    "claps": 61025,
    "clappers": 8884,
    "clapsPerClapper": 6.9,
    "responses": 194,
    "clapsPer1kFollowers": 985.43,
    "authorMedianClaps": 1800.5,
    "vsAuthorMedian": 33.89,
    "source": "author:karpathy"
}
```

| Field | Meaning |
|---|---|
| `claps` / `clappers` / `responses` | Exact counters as Medium reports them. `clappers` = distinct people who clapped. |
| `clapsPer1kFollowers` | Claps per 1,000 followers of the **author**. Articles in large publications can reach far beyond the author's followers — then this number gets very high; compare with `publicationFollowers`. |
| `authorMedianClaps` / `vsAuthorMedian` | Median claps over the author's latest 25 posts older than 48 hours, and this article's claps divided by it. `null` when the median is 0 (a ratio against 0 is not meaningful). |
| `isMemberOnly` | Medium's paywall flag. |
| `isFresh` | Published less than 48 hours ago — claps are still coming in. |
| `readingTimeMinutes` / `wordCount` | As computed by Medium. |

**Author / publication rows** (`type: "author"` / `"publication"`): `followers`, `lastPostDate`, `daysSinceLastPost`, `postsLast30Days`, `postsLast90Days` (exact, or `null` with `postsLast90DaysAtLeast` when the window was not fully read), `medianClaps`, `medianClappers`, `medianResponses`, `medianClapsPer1kFollowers`, `medianReadingTimeMinutes`, `memberOnlyShare`, top post, top tags, X/Twitter link.

A run summary (`SUMMARY` in the key-value store) lists articles found per source, tag sizes, how many articles each filter dropped, failed or unknown inputs and HTTP status counts.

### Honest limits

- **Public data only.** No login, no paywalled text. Member-only articles are returned as metadata and counters.
- **Tag feeds end after about 100 articles** per tag and mode (measured 24 Sep 2026 on `artificial-intelligence`: NEW 100, HOT 97, TOP\_WEEK 99, TOP\_MONTH 100). For more, use several modes, several tags, or search terms — search returns up to ~1,000 articles per term.
- `TOP_WEEK` / `TOP_MONTH` are Medium's own rankings; they can include articles older than the window that are clapped a lot right now.
- Publications that have left Medium (for example Towards Data Science, now on its own site) are listed as "not found" in the summary.
- Author followers and publication followers are Medium's public counts at scrape time.

### Pricing (pay per event)

- Actor start: small flat fee per run
- Per scraped article: only articles that pass your filters and are written to the dataset
- Per scraped profile: one per requested author or publication

The author comparison (`compareWithAuthor`) costs extra requests on our side but is not charged separately.

# Actor input Schema

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

Medium tags, e.g. product-management, artificial-intelligence, or a medium.com/tag/... URL.

## `tagFeedMode` (type: `string`):

Which of Medium's tag feeds to read. TOP\_\* = most-clapped recently, NEW = latest, HOT = trending mix.

## `searchTerms` (type: `array`):

Keywords, searched with Medium's own article search.

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

@username, medium.com/@username or username.medium.com. Returns one author profile row (followers, activity, median claps) plus their articles.

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

Publication slug, medium.com/<slug> URL or custom domain (netflixtechblog.com). Returns one publication profile row plus its articles.

## `articleUrls` (type: `array`):

Individual Medium article URLs (custom domains work — the article id at the end of the URL is used).

## `maxArticlesPerSource` (type: `integer`):

Articles taken from each source before filtering.

## `includeProfileArticles` (type: `boolean`):

Off = only the profile row for each author / publication.

## `publishedWithinDays` (type: `integer`):

Older articles are dropped before output and not charged.

## `minClaps` (type: `integer`):

Articles with fewer claps are dropped before output and not charged.

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

Filter by Medium's member-only (paywall) flag. Only metadata is returned either way — never the paywalled text.

## `compareWithAuthor` (type: `boolean`):

Reads each author's latest 25 posts to add authorMedianClaps and vsAuthorMedian (e.g. 4.2 = four times the author's usual claps). Adds a few requests per run, no extra charge.

## `postsToAnalyze` (type: `integer`):

Median claps/responses of authors and publications are computed over this many latest posts older than 48 hours.

## `maxArticles` (type: `integer`):

The run stops cleanly at this number. You are never charged for more.

## `maxProfiles` (type: `integer`):

The run stops cleanly at this number. You are never charged for more.

## `proxyConfiguration` (type: `object`):

Default: Apify datacenter proxy, fresh IP on every retry.

## Actor input object example

```json
{
  "tags": [
    "product-management",
    "artificial-intelligence"
  ],
  "tagFeedMode": "TOP_MONTH",
  "searchTerms": [
    "ai agents"
  ],
  "authors": [
    "@karpathy",
    "https://medium.com/@netflixtechblog"
  ],
  "publications": [
    "netflix-techblog",
    "towardsdatascience.com"
  ],
  "maxArticlesPerSource": 50,
  "includeProfileArticles": true,
  "memberOnly": "all",
  "compareWithAuthor": true,
  "postsToAnalyze": 25,
  "maxArticles": 500,
  "maxProfiles": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `articles` (type: `string`):

One row per article (type=article) plus one row per requested author or publication (type=author / publication).

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

Articles found per source, how many each filter dropped, tag sizes, failed inputs, HTTP status counts.

# 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": [
        "product-management"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("thequietstack/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": ["product-management"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("thequietstack/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": [
    "product-management"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call thequietstack/medium-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,thequietstack/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/AhpcWAx4rbsffgljx/builds/mm6K6RhEvMS9Cq8YI/openapi.json
