# Medium Scraper: Articles by Tag, Author and Publication (`dedicated_crest/medium-articles-scraper`) Actor

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

## Pricing

$1.00 / 1,000 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 Scraper: Articles by Tag, Author and Publication

**Scrape Medium articles by tag, author, publication or article URL, with no login.** For each article you get the title, URL, author, publication, publish and update dates, tags, a summary or the **full text**, **claps, responses**, reading time and a **member-only flag**. It reads Medium's public RSS feeds and public article data, so you don't need an account, cookies or a browser.

**Try it now:** the input is pre-filled with the `artificial-intelligence` tag. Click **Start**.

### What can you do with this Medium scraper?

- **Track topics**: get the latest Medium articles for tags like `programming`, `ai` or `startup` every day.
- **Monitor writers and competitors**: export the newest stories from any Medium author (`@username`).
- **Follow publications**: pull new posts from Towards Data Science, Better Programming, The Startup and more.
- **Content research and SEO**: see which titles, tags and topics get claps and responses.
- **AI and NLP datasets**: collect clean article text with tags and dates.
- **Lead and creator discovery**: build lists of active writers in a niche.

### Input

| Field | Example | Notes |
|---|---|---|
| `tags` | `programming` | Tag slug or `medium.com/tag/...` URL. Latest articles in the tag. |
| `usernames` | `@ev` | Username with or without `@`, or a profile URL. |
| `publications` | `better-programming` | The slug after `medium.com/`. |
| `articleUrls` | `https://medium.com/p/...` | Individual articles. |
| `maxItems` | `100` | Total cap for the run. |
| `includeFullText` | `true` | Adds `text` when the article is publicly readable. |
| `fetchArticleStats` | `false` | Off by default. Best effort: claps, responses and member-only status from public article data. Uses the residential proxy, billed to your Apify account. |
| `proxyConfiguration` | Apify Proxy | Used for article data only. |

### Output

One record per article:

```json
{
  "type": "article", "sourceType": "author", "source": "@ev",
  "id": "795206e75020", "title": "Simple or Easy?", "url": "https://ev.medium.com/simple-or-easy-795206e75020",
  "author": "Ev Williams", "authorUsername": "ev", "publication": null,
  "publishedAt": "2021-09-22T00:47:36.000Z", "tags": ["product-design", "simplicity"],
  "summary": "Say you need to move a pile of small rocks...", "text": "Say you need to move a pile of small rocks...",
  "claps": null, "responses": null, "readingTimeMinutes": 1, "isMemberOnly": null, "wordCount": 256,
  "fullTextAvailable": true, "dataSource": "rss", "scrapedAt": "2026-10-31T20:39:36.676Z"
}
```

You can download the dataset as JSON, CSV, Excel, XML or HTML, or read it through the Apify API.

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

The price is **$0.001 per article** ($1 per 1,000 articles), pay per result. You only pay for articles saved to the dataset. Set a maximum cost per run in the Console and the scraper stops when it is reached.

### Tips and limits

- **Medium RSS feeds return the 10 most recent articles** per tag, author or publication. For more, add more tags, authors or publications, or schedule the scraper to run daily and build up a history.
- **Member-only (paywalled) articles**: you get the title, summary, tags and metadata, but not the full text. `isMemberOnly` marks them where Medium exposes it.
- **Tag feeds contain only a snippet.** Full text comes from author and publication feeds or from public article data.
- **Claps, responses and the member-only flag are best effort.** They come from Medium's public article data, which sits behind Cloudflare bot protection and is often blocked. When it's blocked, those fields are `null`, `dataSource` is `rss`, and the scraper carries on with feed data. For author and publication feeds, articles that come without full text are flagged `isMemberOnly: true`.
- Requests are rate-limited and retried with backoff to be polite to Medium.

### FAQ

**Do I need a Medium account?** No. Only public data is used.

**Can I get articles older than the feed?** Add their URLs to `articleUrls`.

**Is scraping Medium legal?** This scraper only collects publicly available data. Don't collect personal data without a lawful basis, and respect Medium's terms and authors' copyright when reusing text.

**Something missing?** Open an issue on the Issues tab. We usually reply within a day.

### ⭐ Enjoying it?

If this Actor saved you time, a quick rating on its Apify Store page helps a lot, and it helps other people find it. Feedback or a missing feature? Open an issue on the Actor's Issues tab. Thank you!

# Actor input Schema

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

Medium tags, e.g. programming or artificial-intelligence (a medium.com/tag/... URL also works). Returns the latest articles in each tag.

## `usernames` (type: `array`):

Medium usernames with or without @, e.g. @ev, or a profile URL.

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

Medium publication slugs, e.g. better-programming or towards-data-science (the part after medium.com/).

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

Individual Medium article URLs to scrape, e.g. https://medium.com/@user/some-article-1a2b3c4d5e6f.

## `maxItems` (type: `integer`):

Maximum number of articles saved in total.

## `includeFullText` (type: `boolean`):

Add the article text (when publicly readable). Member-only articles return the summary only.

## `fetchArticleStats` (type: `boolean`):

Read each article's public page data for claps, responses, reading time and member-only status. Off by default. Best effort: Medium often blocks this data. Uses the residential proxy (billed to your Apify account).

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

Proxy used for article pages (Medium blocks datacenter IPs; residential works best). RSS feeds don't need it.

## Actor input object example

```json
{
  "tags": [
    "artificial-intelligence"
  ],
  "maxItems": 30,
  "includeFullText": true,
  "fetchArticleStats": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Medium articles

# 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": [
        "artificial-intelligence"
    ],
    "maxItems": 30,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("dedicated_crest/medium-articles-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": ["artificial-intelligence"],
    "maxItems": 30,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("dedicated_crest/medium-articles-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": [
    "artificial-intelligence"
  ],
  "maxItems": 30,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call dedicated_crest/medium-articles-scraper --silent --output-dataset

```

## MCP server setup

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