# Reddit Subreddit Posts Scraper — New, Hot, Top with Velocity (`foxlabs/reddit-subreddit-posts-scraper`) Actor

Posts of public subreddits — new, hot, top, rising or controversial — page by page: title, text, link, kind, score, upvote ratio, comment count, exact time, flair, image, gallery and video, score and comments per hour, the subreddit's size; author karma on request. Only-new mode. No login.

- **URL**: https://apify.com/foxlabs/reddit-subreddit-posts-scraper.md
- **Developed by:** [Berkan Kaplan](https://apify.com/foxlabs) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 monthly users, 78.6% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 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.

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

## Reddit Subreddit Posts Scraper — New, Hot, Top with Velocity 🚀

**foXLabs Reddit series:** [Search](https://apify.com/foxlabs/reddit-search-scraper) · [Post Details](https://apify.com/foxlabs/reddit-post-details-scraper) · [Post Comments](https://apify.com/foxlabs/reddit-post-comments-scraper) · [User](https://apify.com/foxlabs/reddit-user-scraper)

🎉 Posts of any public subreddits, page by page, as Reddit shows them to a signed-out visitor: **new, hot, top, rising or controversial**, up to Reddit's own end of the listing. Every row carries the post's texts, numbers, exact times and media — and what other Reddit scrapers leave out: **score and comments per hour**, the upvote ratio, the subreddit's size, and **each author's karma and account age** when you ask for it. Only-new mode for recurring runs. No login, no cookies of yours, no CAPTCHA solving.

### 🔍 What is the Reddit Subreddit Posts Scraper — and when should you use it?

Give this Actor one or more public subreddits and it returns their posts as clean rows — in the order you pick, enriched with velocity, the upvote ratio and the subreddit's size (and each author's karma when `includeAuthorInfo` is on).

**Use it when you need:** a subreddit's feed (new/hot/top) as data; community monitoring with engagement signals; or a scheduled only-new feed.

**Use something else when:** you're searching by keyword → [Search](https://apify.com/foxlabs/reddit-search-scraper); you want a single post's comments → [Post Comments](https://apify.com/foxlabs/reddit-post-comments-scraper); one user's history → [User](https://apify.com/foxlabs/reddit-user-scraper).

### 🤖 Use with AI agents

**Already on the Apify MCP server?** Ask for this Actor by name: `foxlabs/reddit-subreddit-posts-scraper`. An agent can discover it, run it and read the dataset over MCP.

**Real-time Standby API.** The same code answers HTTP requests on demand — `GET /posts?subreddit=python&sort=new&maxPosts=25`. Parameters: `subreddit`, `sort`, `time`, `maxPosts` (1–100), `postKinds`, `info` (0/1, default 1), `authors` (0/1, default 0 — each author costs one extra page read); billed with the same `post` event.

Otherwise paste this into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```
I want a subreddit's posts using the Apify Actor
`foxlabs/reddit-subreddit-posts-scraper`.

Input: `subreddits` is a list of subreddits; `sort` is new/hot/top/rising/controversial;
`time` applies to top/controversial. Each row has title, text, score, upvoteRatio, commentCount,
scorePerHour, author and subredditInfo; add `includeAuthorInfo: true` for each author's karma.

Start with:
{ "subreddits": ["python"], "sort": "new", "maxPostsPerSubreddit": 50 }

Ask me which subreddits to track, run the Actor, then summarise the posts as a table.
```

The machine-readable API, MCP config and OpenAPI definition live at `apify.com/foxlabs/reddit-subreddit-posts-scraper.md`.

### 📋 Overview

Everything you need to turn a public subreddit into clean, structured data — posts with velocity, the upvote ratio and the subreddit's size — in one Actor, with no login, cookies or CAPTCHA solving.

**Why teams pick this Actor:**

- ✅ **Five orders** — new, hot, top, rising, controversial (with a time window for top/controversial).
- ⚡ **Velocity + upvote ratio** — score/comments per hour and the ratio most Reddit scrapers leave out; the subreddit's size on every row; each author's karma and age on request.
- 🎯 **Honest nulls & status rows** — a line that brings nothing says why; a run never ends empty silently.
- 🔁 **Only-new monitoring** — schedule the same subreddits and get only what's new.
- 💰 **Pay only for results** — one `post` event per row (~$0.04 per 1,000 posts measured, author karma off); filtered-out and status rows free.
- 🤖 **Agent-ready** — MCP + a real-time Standby API.

### ✨ Features

- 🔍 **Any public subreddit** — by name, `r/name` or URL.
- 📄 **Full post** — ids, title, text, link, domain, kind (text/link/image/gallery/video/poll/crosspost), author, flair, image, gallery and video addresses.
- 📊 **Engagement** — score, upvote ratio, comments, awards, crossposts, and per-hour velocity.
- 🏷️ **Subreddit record** — subscribers and display name on every row with `includeSubredditInfo` (one page read per subreddit).
- 👤 **Author karma** — link/comment karma and the account's cake day with `includeAuthorInfo` (one page read per author, so it is off unless you ask).
- 🧾 **What Reddit no longer shows a signed-out visitor** — the edit time, the spoiler/locked/archived flags, a poll's votes and a crosspost's origin are `null`; see *Fields* below.
- 🔁 **Only-new lists** for recurring runs.

### 🎬 Quick Start

```bash
curl -X POST "https://api.apify.com/v2/acts/foxlabs~reddit-subreddit-posts-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"subreddits": ["python"], "sort": "new", "maxPostsPerSubreddit": 50}'
```

### 🚀 Getting Started (3 steps)

1. **Enter your subreddits** — one per line: `python`, `r/python` or a URL.
2. **Pick order & period** — `sort`, and `time` for top/controversial.
3. **Run and export** — get a clean dataset as JSON, CSV or Excel.

### 📥 Input

| Field | Meaning |
|---|---|
| `subreddits` | one per line: `python`, `r/python` or a URL; a subreddit named twice is read once. |
| `sort` | `new` (default), `hot`, `top`, `rising`, `controversial`. |
| `time` | for `top`/`controversial`: `hour`…`all` (default). |
| `maxPostsPerSubreddit` | posts per subreddit (default 100). Reddit ends a listing after ~1,000. |
| `maxPosts` | rows in the whole run (default 100,000). |
| `postKinds`, `minScore`, `minComments` | keep only these; the rest are skipped and not charged. |
| `includeSubredditInfo` | subreddit record on every row (default on). |
| `includeAuthorInfo` | the author's karma and cake day — one profile-page read per author, so the run takes longer (default off). |
| `onlyNewPosts`, `listName` | remember delivered posts and skip them next time. |
| `proxyConfiguration` | nothing to change for normal use. |

```json
{ "subreddits": ["python", "r/learnpython"], "sort": "new", "maxPostsPerSubreddit": 200, "postKinds": ["text", "link"], "minComments": 5 }
```

### 📤 Output

One row per post. A line that brings nothing gets a **free status row** saying why (not a subreddit, no such name, private, quarantined, Premium-only, empty, named twice).

| Field | What it is |
|---|---|
| `postId`, `fullname`, `url`, `subreddit`, `subredditId` | ids and address |
| `title`, `text`, `link`, `domain`, `kind` | title, text, linked address, domain, kind |
| `author`, `authorFlair`, `authorPremium`, `authorDeleted` | who posted it |
| `score`, `upvoteRatio`, `commentCount`, `awardCount`, `crosspostCount` | the numbers |
| `createdAt`, `editedAt`, `hoursSincePost`, `scorePerHour`, `commentsPerHour` | times and velocity |
| flags | `nsfw`, `spoiler`, `locked`, `stickied`, `archived`, `distinguished`, `originalContent`, `removedBy` |
| `crosspostOf`, `thumbnailUrl`, `imageUrl`, `video`, `galleryImages`, `poll` | crosspost origin and media |
| `subredditSubscribers`, `subredditInfo` | the subreddit's size and record (`includeSubredditInfo`, one page read per subreddit) |
| `authorInfo` | the author's karma and cake day (`includeAuthorInfo`, one page read per author) plus the avatar |

**Always `null` since 16 October 2026** — Reddit closed the JSON API this Actor used to read as a signed-out
visitor, and its web pages do not carry these: `editedAt`, `spoiler`, `locked`, `archived`, `originalContent`,
`removedBy`, `distinguished`, `crosspostOf`, `crosspostCount`, `poll` (the kind is still `poll`, the votes are not
shown), `thumbnailUrl`, `authorPremium`. `nsfw` and `stickied` arrive on media posts only. Everything else above is
measured filled — see the Changelog.
| `position`, `input`, `scrapedAt`, `type`, `error` | place; input line; row type / free status row |

```json
{
  "type": "post",
  "postId": "1x2jj5d",
  "url": "https://www.reddit.com/r/Python/comments/1x2jj5d/…/",
  "subreddit": "Python",
  "title": "A Jev-style regex, use meaning instead of rules",
  "kind": "text",
  "author": "iohans",
  "score": 42,
  "upvoteRatio": 0.95,
  "commentCount": 11,
  "createdAt": "2026-10-10T16:29:58.000Z",
  "scorePerHour": 24.7,
  "flair": "Showcase",
  "subredditSubscribers": 1516618,
  "authorInfo": { "linkKarma": 853, "commentKarma": 2, "createdAt": "2020-05-24T00:00:00.000Z", "avatarUrl": "https://styles.redditmedia.com/…" }
}
```

### 💼 Use cases

**1. Community monitoring** — watch a subreddit's new posts and what's rising.
*Input:* your subreddits, `sort: new`, `onlyNewPosts` scheduled. *Output:* new posts + velocity. *Use:* a live community feed.

**2. Trend & content research** — the top posts of a window.
*Input:* subreddits, `sort: top`, `time: month`, `includeAuthorInfo: true`. *Output:* top posts + author karma. *Use:* learn what wins in a community.

**3. Dataset building** — a subreddit's recent history for analysis.
*Input:* subreddits, high `maxPostsPerSubreddit`. *Output:* up to ~1,000 posts each. *Use:* feed analysis or ML.

### 🔗 Integration

**JavaScript / Node.js**

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('foxlabs/reddit-subreddit-posts-scraper').call({
  subreddits: ['python'], sort: 'new', maxPostsPerSubreddit: 50,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

**Python**

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('foxlabs/reddit-subreddit-posts-scraper').call(
    run_input={'subreddits': ['python'], 'sort': 'new', 'maxPostsPerSubreddit': 50}
)
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)
```

Written for `apify-client` 3 for Python, where `call()` returns a run object; with version 1 or 2 it returns a dict — write `run['defaultDatasetId']` there.

**Automation (n8n / Zapier / Make):** schedule → HTTP request to the Actor API with your `subreddits` → handle the JSON dataset → push to a sheet, CRM or dashboard.

### 📊 Pricing

Pay per event, one event per delivered row: **`post`** — whatever it carries (the subreddit's and author's records ride along free). Measured ~**$0.02 per 1,000 posts**. Status rows are free; filtered-out posts aren't written or charged; a run Reddit doesn't answer ends FAILED and charges nothing; no start fee. [View current pricing.](https://apify.com/foxlabs/reddit-subreddit-posts-scraper)

### ❓ FAQ

**Do I need a Reddit account, login or API key?** No. It reads the pages Reddit's own site renders for a signed-out visitor — no account, no cookies of yours, no CAPTCHA solving.

**How many posts per subreddit?** Reddit ends a listing after ~1,000, whatever you ask for. For the whole history, use `top` across several `time` windows, or run `new` on a schedule with only-new.

**Can I filter by kind/score/comments?** Yes — `postKinds`, `minScore`, `minComments`; filtered-out posts aren't charged.

**Why is `subredditInfo.activeUsers` null?** Reddit doesn't give that number to a signed-out visitor.

**Can I export to CSV / Excel / JSON?** Yes — directly from the Apify dataset.

### 🐛 Troubleshooting

- **~1,000 posts max per subreddit** — Reddit's own cap; use `top`+`time` windows or scheduled only-new for more.
- **A line returns a status row** — private, quarantined, Premium-only, no such subreddit, or named twice (free).
- **Share links (`/r/x/s/…`)** aren't accepted — this Actor reads listings, not single posts.
- **Scores look slightly off** — Reddit fuzzes scores by design.

**How it reads Reddit:** opens the listing page as a signed-out visitor for its cookies, then reads the feed fragments Reddit's own web client asks for — 24 posts and a cursor at a time, page after page. Reddit answers these for residential addresses only (measured 2026-10-17: residential 200, datacenter 403), so Apify Proxy residential is used by default; four addresses rotate and a refused or used-up one is replaced.

### ⚠️ Trademark

Independent, third-party tool. Reddit is a trademark of Reddit, Inc.; this Actor is not affiliated with, endorsed by or connected to Reddit. The mark is used here for identification only.

### ⚖️ Is it legal to scrape this data?

It reads only what Reddit shows anyone who is not signed in. Rows carry user names (public pseudonyms) and publicly posted text; you are responsible for using them lawfully (GDPR, CCPA, Reddit's User Agreement). Nothing is stored outside your own Apify datasets. See Apify's blog post on the legality of web scraping.

### 🤝 Support & contact

- 🌐 **Website:** [data.foxlabs.com.tr](https://data.foxlabs.com.tr)
- 📧 **Email:** info@foxlabs.com.tr
- 🐛 **Issues:** open a ticket in the Actor's **Issues** tab — the run's `SOURCE_REPORT` record holds what was seen, read, delivered and why the run stopped.
- 🧰 **More clean data actors:** [Fox Labs on Apify](https://apify.com/foxlabs)

### Changelog

#### 0.2.1 — 2026-10-17

An address Reddit turns away answers with a page of the right size and nothing in it; the Actor now notices that,
lets that address go and tries another, so a refusal is never reported as "this subreddit has no posts". A line
that still comes back empty is free and retryable. The subreddit's record is retried on a second post, and the
authors' karma is read only for the posts the run hands on.

#### 0.2.0 — 2026-10-17

Reddit closed its JSON API to signed-out visitors on 16 October 2026 (HTTP 403 for a guest token, from any
address), so this Actor now reads the pages Reddit's own web client renders. Field names, the dataset shape, the
`post` event and its price are unchanged. What changed: Reddit's pages give 24 posts a request instead of 100
(long single-subreddit runs take longer); `editedAt`, `spoiler`, `locked`, `archived`, `originalContent`,
`removedBy`, `distinguished`, `crosspostOf`, `crosspostCount`, `thumbnailUrl`, `authorPremium` and a poll's votes
are `null`, and `nsfw`/`stickied` arrive on media posts only; `includeAuthorInfo` is off by default because the
karma is now one profile-page read per author; `subredditInfo` carries the subscriber count, display name and
description (age/type/language `null`). Status rows still say why a subreddit brought nothing — from its RSS when
Reddit's pages do not say — and charge nothing. Measured cost: ~$0.04 per 1,000 posts with karma off.

#### 0.1.0 — 2026-10-10

- First release: new/hot/top/rising/controversial listings of public subreddits with velocity fields, subreddit record and author karma on every row; kind/score/comment filters; only-new lists; free status rows for lines that bring nothing; Standby API prepared.

# Changelog

This Actor's version history is a separate document: https://apify.com/foxlabs/reddit-subreddit-posts-scraper/changelog.md

# Actor input Schema

## `subreddits` (type: `array`):

One subreddit per line: a name (python), r/python, or an address (https://www.reddit.com/r/python/). The forms can be mixed; a subreddit written twice is read once. Only public subreddits can be read — a private, quarantined or Premium-only one gets a free status row that says so.

## `sort` (type: `string`):

Which of the subreddit's listings to read, in its own order: new (newest first), hot, top (by score, within the period below), rising, controversial (within the period).

## `time` (type: `string`):

The period the top and controversial listings cover. Ignored for new, hot and rising.

## `maxPostsPerSubreddit` (type: `integer`):

How many posts to deliver for each subreddit, from the top of the listing. Reddit's pages give 24 posts a request and it shows at most about 1,000 posts of any listing: a number above that stops where Reddit stops.

## `maxPosts` (type: `integer`):

The run stops when this many rows have been delivered. You are charged only for delivered rows.

## `postKinds` (type: `array`):

Leave empty for every kind. Choose some to get only those; a post of another kind is skipped and not charged.

## `minScore` (type: `integer`):

Deliver only posts whose score is at least this. Leave empty for every post.

## `minComments` (type: `integer`):

Deliver only posts with at least this many comments. Leave empty for every post.

## `includeSubredditInfo` (type: `boolean`):

One request per subreddit adds its subscribers, active users, creation date, type and description to every row of it (subredditInfo). Off: the rows carry the subscriber count alone.

## `includeAuthorInfo` (type: `boolean`):

Adds each post's author record (link and comment karma, the account's cake day, avatar) as authorInfo. Reddit shows these only on the author's own profile page, so this reads one page per author: it makes the run slower and uses more proxy traffic. Off: the rows still carry the author, the author's id and the avatar. A deleted author gets null.

## `onlyNewPosts` (type: `boolean`):

Remember delivered posts under the list name below and skip them in later runs. Schedule the same subreddits hourly or daily and each run brings only the posts it has not delivered before. With this on, "Maximum posts per subreddit" is how far down each listing the Actor looks.

## `listName` (type: `string`):

Name of the memory used by "Only posts not delivered before" (looked at only when that is on). Use a different name for each project. Letters, digits and hyphens (a hyphen not first or last), up to 40 characters; capitals are read as lower case.

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

Nothing to change for normal use: the Actor reads Reddit through Apify Proxy residential addresses, the only kind Reddit answers for a signed-out visitor (measured 2026-10-17: residential 200, shared datacenter and dedicated datacenter 403 on every try). Set a proxy here to send every request through it instead; a setting the platform refuses ends the run before anything is read.

## Actor input object example

```json
{
  "subreddits": [
    "python"
  ],
  "sort": "new",
  "time": "all",
  "maxPostsPerSubreddit": 50,
  "maxPosts": 100000,
  "includeSubredditInfo": true,
  "includeAuthorInfo": false,
  "onlyNewPosts": false,
  "listName": "default",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# 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 = {
    "subreddits": [
        "python"
    ],
    "maxPostsPerSubreddit": 50,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("foxlabs/reddit-subreddit-posts-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 = {
    "subreddits": ["python"],
    "maxPostsPerSubreddit": 50,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("foxlabs/reddit-subreddit-posts-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 '{
  "subreddits": [
    "python"
  ],
  "maxPostsPerSubreddit": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call foxlabs/reddit-subreddit-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,foxlabs/reddit-subreddit-posts-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/WiCFPetYqvdWuiGkU/builds/e54vWG9oMUmrUnSER/openapi.json
