# Reddit Subreddit Scraper - Posts by Community (`studioxl/reddit-subreddit-scraper`) Actor

Export posts from 1 to 100 subreddits as flat rows in Hot, New, Top, Rising or Controversial order, with optional comments, subreddit stats, flair filter and an only-new mode for daily feeds. Same columns as Reddit Search Scraper. $1.19 per 1,000 posts. No login.

- **URL**: https://apify.com/studioxl/reddit-subreddit-scraper.md
- **Developed by:** [Kamil Ertekin](https://apify.com/studioxl) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.89 / 1,000 post saveds

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

## Reddit Subreddit Scraper - Posts by Community

Give it a list of subreddits and get their posts as rows, in the order Reddit shows them: Hot, Newest, Top, Rising or Controversial. Each post row has the title, full text, author, score, upvote ratio, comment count, flair, media links and dates. Turn on comments to add the first comments of every post, add a row describing each subreddit, keep only certain flairs, or save only the posts that are new since your last run. No Reddit account needed.

Post rows have the same columns as our [Reddit Search Scraper](https://apify.com/studioxl/reddit-post-search-scraper) and comment rows the same columns as our [Reddit Comments Scraper](https://apify.com/studioxl/reddit-comments-replies-scraper), so the datasets combine without any mapping.

### What you get

Every row has a `recordType`: `post`, `comment` or `subreddit`.

**Post rows** (45 fields). Example values from a run on r/SaaS:

| Field | Example | Notes |
|---|---|---|
| `title` | Why do SaaS beginners fail? | |
| `body` | What is the main cause of begginers that fail... | Markdown. Empty for link and image posts |
| `permalink` | https://www.reddit.com/r/SaaS/comments/1xbdbdw/why_do_saas_beginners_fail/ | Link to the post |
| `url`, `domain` | the post itself, self.SaaS | Where a link post points |
| `author`, `authorFlair` | Comfortable_Wolf9434, null | |
| `subreddit`, `subredditSubscribers` | SaaS, 830637 | |
| `createdAt`, `editedAt` | 2026-10-21T04:12:41.042Z, null | UTC, ISO 8601 |
| `score`, `upvoteRatio`, `commentCount` | 24, 1, 34 | As shown on Reddit when collected |
| `flair`, `languageCode` | null, en | |
| `mediaType` | text | `image`, `video`, `gallery`, `link` or `text` |
| `imageUrl`, `thumbnailUrl`, `videoUrl`, `galleryImageUrls`, `mediaWidth`, `mediaHeight` | null | Media links and size. Video links expire after a while |
| `isNsfw`, `isSpoiler`, `isLocked`, `isArchived`, `isStickied`, `isSelfPost` | false | Post flags |
| `distinguished`, `crosspostCount`, `isQuarantined` | null, 1, false | |
| `feedSubreddit`, `feedSort` | SaaS, hot | The subreddit and the order that found the post (`top/week`, `controversial/month` and so on for ranges) |
| `query` | null | Always empty here. It holds the search phrase in Reddit Search Scraper rows |
| `id`, `recordKey` | t3_1xbdbdw | Stable, so you can merge runs on it |

**Comment rows** (31 fields, when comments are on): `postId`, `postTitle`, `postUrl`, `subreddit`, `parentId`, `depth`, `childCount`, `body`, `mediaUrls`, `author`, `authorId`, `createdAt`, `editedAt`, `score`, `permalink`, `languageCode`, `authorFlair`, `distinguished`, `isPostAuthor`, flags and `capturedAt`. `parentId` is the post for a top-level comment and the parent comment for a reply; `depth` is 0 for top-level comments.

**Subreddit rows** (one per subreddit, when turned on): `name`, `title`, `description`, `subscribers`, `weeklyActiveUsers`, `weeklyContributions`, `createdAt`, `isNsfw`, `type`, `url`. Measured on r/AskReddit: 59,941,373 subscribers and 12,207,663 weekly active users.

How often post fields are filled depends on the community. Across 2,000 posts from r/startups, r/SaaS, r/Entrepreneur, r/smallbusiness and r/marketing: `body` 98%, `flair` 59%, `crosspostCount` 15%, `imageUrl` 8%, `editedAt` 6%, `authorFlair` 2%, `videoUrl` 1%. Across 10,000 posts from r/technology, r/worldnews, r/gaming, r/movies and r/todayilearned, where most posts are links: `imageUrl` 81%, `flair` 47%, `body` 16%. Title, author, score, comment count, dates and the post flags were filled on every post.

### How to use it

1. Add your subreddits: `startups`, `r/SaaS` or a `reddit.com/r/...` link, one per line, or paste a whole list.
2. Pick an order and how many posts you want. Turn on comments, subreddit rows or "only new posts" if you need them.
3. Click **Start**, then download the results as CSV, Excel or JSON from the **Output** tab.

```json
{
  "subreddits": ["startups", "SaaS"],
  "sort": "new",
  "maxPosts": 200
}
```

Measured run times: 25 posts in 14 seconds, 1,000 posts in about 2.5 minutes, 10,000 posts from 5 subreddits in 31 minutes. With comments on, every post adds a few seconds: 50 posts and 675 comments took 5 minutes.

### Input

| Field | What it does | Example | Default |
|---|---|---|---|
| `subreddits` | Subreddits to read, 100 at most. Names, `r/name` or links, in any letter case; repeats are merged. A pasted list can use lines, commas or spaces. | `["startups", "r/SaaS"]` | `["startups"]` |
| `subredditsFileUrl` | Link to a plain text or CSV file with one subreddit per line, 1 MB at most. In a CSV the first column is used and a title row is skipped. | `https://example.com/subs.csv` | none |
| `sort` | `hot`, `new`, `top`, `rising` or `controversial`. | `new` | `hot` |
| `timeFilter` | Time range for Top and Controversial: `hour`, `day`, `week`, `month`, `year`, `all`. Every saved post was created inside it. | `week` | `all` |
| `maxPosts` | Posts to save in the run, 1 to 10,000, shared fairly between subreddits. Comments and subreddit rows come on top. | `500` | `100` |
| `maxPostsPerSubreddit` | Optional limit per subreddit. 0 means none. | `200` | `0` |
| `flair` | Keep only posts with one of these flairs, ignoring letter case. | `["Question"]` | none |
| `postedWithinHours` | Keep posts from the last N hours. With Newest, a subreddit stops being read once its posts are older. 0 means off. | `24` | `0` |
| `dateFrom`, `dateTo` | Keep posts created inside these dates: `2026-01-01` or a relative age such as `7 days`. | `7 days` | none |
| `includeNsfw` | Keep posts marked NSFW. When off, NSFW subreddits are skipped whole. | `true` | `false` |
| `includeComments` | Add the first comments of each saved post, replies included, in thread order. | `true` | `false` |
| `maxCommentsPerPost` | Comments per post, 0 to 500. | `50` | `20` |
| `commentSort` | Which comments come first: `top`, `best` or `new`. | `new` | `top` |
| `includeSubredditInfo` | Add one row describing each subreddit. | `true` | `false` |
| `onlyNewSinceLastRun` | Skip posts that an earlier run of the same feed saved. For scheduled runs. | `true` | `false` |
| `feedName` | Name of the memory used by the option above. Runs with the same name share it. Letters, digits and hyphens. | `startups-daily` | one per list of subreddits and order |

Calling it from code or an AI agent? Common field names work too: `subreddit`, `communities`, `startUrls` or `url` for the subreddits, `maxItems`, `limit` or `maxResults` for the post limit, `sortBy` and `time` for the order, `withComments` and `commentsPerPost` for comments. Fields the scraper doesn't know are ignored and listed in the run message.

### Output example

A post row (trimmed):

```json
{
  "recordType": "post",
  "id": "t3_1xbdbdw",
  "title": "Why do SaaS beginners fail?",
  "body": "What is the main cause of begginers that fail in starting or not getting good result from SaaS now a days ?...",
  "permalink": "https://www.reddit.com/r/SaaS/comments/1xbdbdw/why_do_saas_beginners_fail/",
  "subreddit": "SaaS",
  "subredditSubscribers": 830637,
  "author": "Comfortable_Wolf9434",
  "score": 24,
  "upvoteRatio": 1,
  "commentCount": 34,
  "createdAt": "2026-10-21T04:12:41.042Z",
  "mediaType": "text",
  "isNsfw": false,
  "feedSubreddit": "SaaS",
  "feedSort": "hot",
  "query": null,
  "capturedAt": "2026-10-21T09:24:13.215Z"
}
```

A comment row on that post (trimmed):

```json
{
  "recordType": "comment",
  "id": "t1_phz9j9m",
  "postId": "t3_1xbdbdw",
  "postTitle": "Why do SaaS beginners fail?",
  "subreddit": "SaaS",
  "parentId": "t3_1xbdbdw",
  "depth": 0,
  "childCount": 1,
  "body": "it's usually a mix of a few things but the main one i see is people thinking the product alone will carry everything...",
  "author": "Common_University322",
  "score": 9,
  "createdAt": "2026-10-21T04:23:01.385Z",
  "permalink": "https://www.reddit.com/r/SaaS/comments/1xbdbdw/why_do_saas_beginners_fail/phz9j9m/"
}
```

A subreddit row:

```json
{
  "recordType": "subreddit",
  "id": "t5_2qkq6",
  "name": "SaaS",
  "title": "Software as a Service",
  "description": "Discussions and useful links for SaaS owners, online business owners, and more.",
  "subscribers": 830638,
  "weeklyActiveUsers": 271616,
  "weeklyContributions": 11096,
  "createdAt": "2008-07-31T21:06:38.233Z",
  "isNsfw": false,
  "type": "public",
  "url": "https://www.reddit.com/r/SaaS/"
}
```

Each run also saves a summary (Output tab, "Run summary") with the posts and comments saved per subreddit, the subreddits skipped and why, how many posts your filters removed, and why the run stopped.

### Pricing

You pay per row saved. There is no start fee.

| Apify plan | Discount tier | Per 1,000 posts | Per 1,000 comments |
|---|---|---|---|
| Free | No discount | $1.19 | $0.99 |
| Starter | Bronze | $1.09 | $0.89 |
| Scale | Silver | $0.99 | $0.79 |
| Business plan and higher | Gold | $0.89 | $0.69 |

A subreddit row costs the same as one post.

Worked example, no discount: 200 posts with comments on at 20 per post. Posts with fewer than 20 comments give what they have. If the run saves 200 posts and 3,000 comments, it costs 200 x $0.00119 + 3,000 x $0.00099 = $0.24 + $2.97 = $3.21. The same 200 posts without comments cost $0.24.

Not charged:

- Duplicates, including pinned posts that show up on many pages.
- Posts removed by your filters (NSFW, flair, dates).
- Posts that an earlier run of the same feed already saved, when "only new posts" is on.
- Subreddits that are skipped (missing, private, banned, quarantined, or NSFW while NSFW is off).
- Deleted and removed comments.

Set "Maximum cost per run" in Run options for a hard cap. A run that reaches it stops cleanly and says so, and a row is never charged unless it was saved.

### FAQ

**How deep does a subreddit go?** Reddit does not show a whole community in one list. Newest ended at 984 and 993 posts on r/AskReddit, Hot at 987, each Top range at 398 to 453, Rising at 24. When the order you picked runs out before your limit, the run reads the other orders and time ranges of the same subreddit and keeps only posts it has not saved yet; `feedSort` names the order that found each post. Asked for 10,000 posts from r/AskReddit by Newest, a run saved 4,701 different posts, the oldest from 2009. About 4,700 is what one large subreddit gives. For more, add subreddits: 5 subreddits gave 10,000.

**Why did I get fewer posts than I asked for?** The subreddit ran out (see above), your filters removed posts, or the community is small. r/technology had 526 posts in one week; asked for 1,000 from its past week, the run returned all 526. The run message says which of these happened.

**What happens with private, banned or missing subreddits?** They are skipped, named in the run message with the reason, and cost nothing. For example: "Skipped, nothing charged: r/nosuchsub8x7q2z does not exist; r/lounge is private; r/fatpeoplehate is banned; r/TheRedPill is quarantined and not public."

**Are NSFW posts included?** Not by default. NSFW posts are skipped and not charged (339 of them in one 5,000-post r/AskReddit run), and a subreddit marked NSFW is skipped whole. Turn on "Include NSFW posts" to keep them.

**How do I get a daily feed of new posts?** Save the input as a task with Sort by Newest, turn on "Only posts not saved by an earlier run", give it a feed name, and add a schedule. Each run saves only posts the feed has not saved before and stops reading a subreddit once it reaches them: a second run of r/startups straight after the first read one page, saved nothing and cost nothing. Results go to Google Sheets, Slack, Make, Zapier or n8n through Apify integrations.

**How does this combine with Reddit Search Scraper and Reddit Comments Scraper?** Post rows match the [Reddit Search Scraper](https://apify.com/studioxl/reddit-post-search-scraper) columns, so a keyword search and a subreddit feed can go into one table, merged on `id`. Comment rows match the [Reddit Comments Scraper](https://apify.com/studioxl/reddit-comments-replies-scraper). This scraper saves the first comments of each post, 500 at most; for every comment of a big thread, paste the post's `permalink` into the Comments Scraper.

**Why did Rising return so few posts?** Rising lists only the posts gaining votes right now: 24 on r/AskReddit when we measured. Pick Hot or Newest for volume.

### Limits

- 100 subreddits and 10,000 posts per run. Comments and subreddit rows come on top of the post limit.
- One subreddit gives about 4,700 different posts (4,701 on r/AskReddit asked for 10,000). Newest and Hot end near 1,000 posts each, each Top range near 450, Rising near 25.
- 500 comments per post at most, starting from the top of the thread. For complete threads, use the Reddit Comments Scraper.
- "Only new posts" remembers the newest 50,000 post IDs per feed name.
- Several runs started at the same time in one account each take longer: three at once ran at about a third of the speed of one.
- Public content only. Scores and comment counts are a snapshot from the moment of collection. Media links can expire.

Questions or a missing field? Open an issue in the **Issues** tab with your run ID.

# Actor input Schema

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

One community per line, or paste a whole list separated by lines, commas or spaces (100 at most). Write it as startups, r/startups or a reddit.com/r/startups link. Private, banned, quarantined and missing communities are skipped and named in the run message, with nothing charged.

## `subredditsFileUrl` (type: `string`):

Optional. Link to a plain text or CSV file (1 MB at most) with one subreddit per line; in a CSV the first column is used and a title row is skipped. Added to the list above.

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

The order the subreddit shows its posts in. Newest suits monitoring; Top with a time range finds the highest-scoring posts.

## `timeFilter` (type: `string`):

Used with Top and Controversial only. Every saved post was created inside this range. For other orders, use the dates below.

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

How many posts to save in this run, across all subreddits (1 to 10,000). The limit is shared fairly: each subreddit gets an equal part, and what one cannot use goes to the others. You pay only for saved posts.

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

Optional. Stop each subreddit after this many posts, for example 200. 0 means no per-subreddit limit (the total is still shared fairly).

## `flair` (type: `array`):

Optional. Keep only posts whose flair matches one of these, ignoring letter case, for example "Question". Posts without a flair are skipped when this is set.

## `postedWithinHours` (type: `integer`):

Optional. Keep posts created in the last N hours, for example 24. With Newest, a subreddit stops being read once its posts are older. 0 means off.

## `dateFrom` (type: `string`):

Optional. Keep posts created on or after this date, for example 2026-01-01 or "7 days". With Newest, the run stops reading a subreddit once its posts are older than this date.

## `dateTo` (type: `string`):

Optional. Keep posts created on or before this date, for example 2026-03-31.

## `includeNsfw` (type: `boolean`):

Off by default: posts marked NSFW (18+) are skipped and not charged, and NSFW subreddits are skipped whole. Turn on to keep them.

## `includeComments` (type: `boolean`):

Off by default. Adds the first comments of every saved post as rows of their own (recordType "comment"), in thread order with replies. Deleted and removed comments are skipped and not charged.

## `maxCommentsPerPost` (type: `integer`):

How many comments to save per post when comments are on (0 to 500). A post with fewer comments gives what it has.

## `commentSort` (type: `string`):

Which comments come first when a post has more than your limit.

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

Off by default. Adds one row per subreddit (recordType "subreddit"): title, description, subscribers, weekly active users, creation date, NSFW flag and link. Charged as one post.

## `onlyNewSinceLastRun` (type: `boolean`):

Off by default. For scheduled runs: posts this feed saved in an earlier run are skipped and not charged. With Newest, a subreddit stops being read once it reaches posts saved before.

## `feedName` (type: `string`):

Optional, used with the option above. Runs with the same feed name share one memory of saved posts, for example "startups-daily". Leave empty to use one memory per list of subreddits and order.

## Actor input object example

```json
{
  "subreddits": [
    "startups",
    "SaaS"
  ],
  "sort": "hot",
  "timeFilter": "all",
  "maxPosts": 100,
  "maxPostsPerSubreddit": 0,
  "postedWithinHours": 0,
  "includeNsfw": false,
  "includeComments": false,
  "maxCommentsPerPost": 20,
  "commentSort": "top",
  "includeSubredditInfo": false,
  "onlyNewSinceLastRun": false
}
```

# Actor output Schema

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

Saved posts. Switch views for text and media, authors and communities, or dates and status.

## `completeJson` (type: `string`):

All fields for every saved row, without a view-specific field selection.

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

Saved-post counts per subreddit, skipped subreddits, filters applied and why the run stopped.

# 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": [
        "startups",
        "SaaS"
    ],
    "maxPosts": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("studioxl/reddit-subreddit-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": [
        "startups",
        "SaaS",
    ],
    "maxPosts": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("studioxl/reddit-subreddit-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": [
    "startups",
    "SaaS"
  ],
  "maxPosts": 100
}' |
apify call studioxl/reddit-subreddit-scraper --silent --output-dataset

```

## MCP server setup

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