# Reddit Scraper: Posts, Comments, Search & Subreddits (`makework36/reddit-scraper`) Actor

Reddit scraper with upvotes and engagement metrics. Posts, comments and subreddits from any subreddit or a global search, no Reddit API key and no login. 29 post fields and 10 comment fields, AI ready JSON for LLM and RAG pipelines, lead generation and market research. Export as JSON, CSV or Excel.

- **URL**: https://apify.com/makework36/reddit-scraper.md
- **Developed by:** [deusex machine](https://apify.com/makework36) (community)
- **Categories:** Social media, AI, Lead generation
- **Features:** Limited permissions
- **Stats:** 176 total users, 10 monthly users, 97.0% runs succeeded, 2 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.05 / 1,000 results

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 Scraper for AI & Lead Generation: Posts, Comments, Subreddits & Users API

**Reddit Scraper** gives you posts, comments, subreddits and users from any subreddit or Reddit search query, without a Reddit API key and without login. You get structured JSON ready for LLM pipelines, AI training, sentiment analysis, lead generation, market research and brand monitoring.

No OAuth setup and no app registration, which since 2026 Reddit only grants for moderation use cases. Give it a list of subreddits or a search query and you get clean, normalized Reddit data in JSON, CSV or Excel.

> **Posts · Comments · Nested threads · Image galleries · Search any query · Pagination beyond 100 · Export to JSON/CSV/Excel**

### ✨ What you get

- ✅ **No Reddit API key needed.** No app registration, no OAuth, no credentials to manage.
- ✅ **No login.** Public Reddit data, anonymously.
- ✅ **Up to 500 posts per subreddit or query**, past the usual 100-result ceiling.
- ✅ **Post engagement metrics on every run**: `score`, `upvoteRatio`, `numComments`, `flair` and `awards` always come back. Per-comment `score`, `depth`, `created`, `isSubmitter` and `parentId` are included by default on most runs. See [Engagement metrics](#-engagement-metrics) for exactly when.
- ✅ **Nested comment threads**, with each comment's parent so you can rebuild the discussion.
- ✅ **Organic results only.** Promoted and sponsored posts never arrive as results.
- ✅ **Same results wherever the run executes.** Text comes back in English and the posts and their order do not change with the run's location. Verified on September 2, 2026 against the same subreddit collected from Mexico and from the United States: identical posts, identical order.
- ✅ **AI-ready JSON.** Straight into an embedding pipeline, a RAG system or a sentiment model.
- ✅ **Lead generation fields on every post.** `author`, `subreddit`, `url` (the permalink to the thread), `flair` and `created` tell you who asked, where they asked, the exact thread to reply in and how recent the request is, so a prospect list comes straight out of the dataset.
- ✅ **JSON, CSV, Excel (XLSX)**, or the Apify Dataset API.
- ✅ **Unknown is never reported as zero.** Anything Reddit does not publish comes back as `null`, never `0`, so a filter or a sort on `score` cannot mistake a missing value for a real one.
- ✅ **An incomplete run says so.** If a run runs out of time, you still get every post it collected, the ones it could not finish carry `isPartialResult: true` with the reason, comments it never fetched are not charged, and the status message says how many posts were cut short.

### 📊 Engagement metrics

Post `score`, `upvoteRatio` and `numComments` always come back. The per-comment numbers are included automatically whenever they are worth the extra wait. You do not have to set anything.

| What you ask for | Post metrics | Comment metrics |
|---|---|---|
| Posts only (`includeComments: false`) | ✅ always included | (no comments requested) |
| Posts plus up to 25 comments each | ✅ always included | ✅ included |
| Posts plus more than 25 comments each | ✅ always included | not included, ask for them with `useRichData: true` |
| `useRichData: true` | ✅ always included | ✅ always included |
| `useRichData: false` | ✅ always included | never included, the run finishes sooner |

**Post metrics** (`score`, `upvoteRatio`, `numComments`, `flair`, `awards`, `postLanguage` and `subredditWeeklyActiveUsers`) come back on every run, whatever `useRichData` is set to.

**When comment metrics are included**, comments carry `score`, `depth`, `created`, `isSubmitter` and `parentId`, and you can ask for up to **1000 comments per post** instead of 100.

**When comment metrics are not included**, you get every other field exactly as always, with those per-comment ones `null`.

**Reliability.** The metrics arrive on every run that includes them, per the table above. Between September 17 and September 18, 2026 they came back `null` on runs that should have carried them; that cause has been fixed and verified, and the metrics are arriving normally again.

`null` is the exception, not the normal path. If the metrics still cannot be collected on some run, you keep every post and comment you asked for, with those fields `null` and a line in the log saying so. It never costs you results you would otherwise have had, and comments that arrive without their metrics are never billed.

**What this costs.** From **September 17, 2026**, a comment that arrives with its metrics costs **$0.70 per 1,000 comments**. A comment that arrives without them is free, so the rows above that say "not included" cost exactly what they cost today. If a run starts with the metrics and loses them halfway, only the comments that actually carried them are billed, and the run log gives you the count both ways.

Some fields come back `null` either way, because Reddit does not publish them at all: `subredditSubscribers`, `isNSFW`, `isSpoiler`, `isPinned`, `numCrossposts` and `controversiality`.

### 📤 Output fields

Every Reddit post comes back with 29 normalized fields covering text, media, engagement, flairs, subreddit metadata and timestamps. When you ask for comments, each post also carries its comment thread as structured JSON.

#### Post fields (29)

| Field | Description |
|-------|-------------|
| `id` | Reddit post ID (e.g. `t3_1s6e3dp`) |
| `subreddit` | Subreddit name (e.g. `technology`) |
| `title` | Post title |
| `author` | Reddit username of the post author |
| `score` | Net upvotes. ✅ with engagement metrics |
| `upvoteRatio` | Share of votes that were upvotes. ✅ with engagement metrics |
| `numComments` | Total comments on the post. ✅ with engagement metrics |
| `url` | Reddit permalink to the post |
| `selftext` | Post body for text posts (up to 5,000 chars) |
| `thumbnail` | Thumbnail preview URL |
| `imageUrls` | All image URLs from galleries and image posts |
| `media` | Video URL + duration, or image URL |
| `created` | Post creation time (ISO 8601) |
| `edited` | Last edit timestamp, or `false` |
| `isVideo` | Video post flag |
| `isSelf` | Text post (`true`) vs link post (`false`) |
| `isGallery` | Multi-image gallery post |
| `domain` | Source domain (e.g. `youtube.com`, `self.technology`) |
| `linkUrl` | External URL for link posts |
| `flair` | Post flair. ✅ with engagement metrics |
| `awards` | Awards on the post. ✅ with engagement metrics |
| `postLanguage` | Language Reddit assigns to the post. ✅ with engagement metrics |
| `subredditWeeklyActiveUsers` | Reddit's own community-size number. ✅ with engagement metrics. It is **not** a subscriber count and must not be read as one |
| `isNSFW` | ⚠️ Always `null`. Reddit does not publish it |
| `isSpoiler` | ⚠️ Always `null`. Reddit does not publish it |
| `isPinned` | ⚠️ Always `null`. Reddit does not publish it |
| `numCrossposts` | ⚠️ Always `null`. Reddit does not publish it |
| `subredditSubscribers` | ⚠️ Always `null`. Reddit does not publish it (see the FAQ) |
| `postType` | Classification: `text`, `link`, `video`, `image`, `gallery` |
| `scrapedAt` | Scraping timestamp (ISO 8601) |
| `comments` | Array of comments (when you ask for them) |

#### Comment fields (10)

| Field | Description |
|-------|-------------|
| `id` | Comment ID |
| `author` | Commenter Reddit username |
| `body` | Comment text (up to 2,000 chars) |
| `score` | Net upvotes on the comment. ✅ with engagement metrics |
| `created` | Comment time, ISO 8601. ✅ with engagement metrics |
| `depth` | Position in the thread, 0 for top level. ✅ with engagement metrics |
| `isSubmitter` | Whether the commenter is the post author. ✅ with engagement metrics |
| `parentId` | The comment this one replies to. ✅ with engagement metrics |
| `controversiality` | ⚠️ Always `null`. Reddit does not publish it |
| `replies` | Number of direct replies |

### 🎯 Use cases

#### 1. AI & LLM training data

Reddit posts and comments are a gold mine for training conversational AI, instruction-tuning LLMs and building RAG systems. You get clean JSON that drops straight into your embedding pipeline. Use `searchQuery` to narrow it to your domain (medical, legal, finance).

#### 2. Sentiment analysis & brand monitoring

Collect Reddit posts and comments mentioning your brand, product or competitors, feed them into VADER, RoBERTa or an LLM, and track sentiment over time. You get full discussion threads, not isolated quotes.

#### 3. Lead generation

Find people asking for what your product solves, and reach them in the thread where they asked. Monitor the subreddits where buyers ask for recommendations (`r/smallbusiness`, `r/sysadmin`, `r/marketing`), or search all of Reddit with `searchQuery: "best CRM for small business"` and `sort: top, timeFilter: month` to catch the month's most visible requests.

Every post comes back with `author`, `subreddit`, `url` (the permalink), `flair` and `created`, which is everything a prospect list needs: who asked, where, the exact thread to reply in, and how recent the request is. Turn on comments and you also collect the people who replied asking the same thing, each with their own `author`. Export to CSV or Excel for a sales team that does not write code, or push the rows into your CRM with Apify Webhooks. An LLM can triage them first and keep only the posts that describe real buying intent.

#### 4. Market research

Monitor entire subreddits (`r/smallbusiness`, `r/saas`, `r/entrepreneur`) for trending topics, pain points and recurring questions, segmented by engagement and recency.

#### 5. Academic research

Reproducible, timestamped Reddit data for computational social science, public health monitoring and linguistic analysis, without the Reddit API's OAuth flow.

#### 6. Content discovery & trend spotting

Surface emerging topics before they hit mainstream media. Sort by `rising` or `top/day` to catch conversations at the right moment.

#### 7. Competitor intelligence

Pull discussions about competitor products to extract feature requests, complaints and comparison threads, ranked by the engagement they actually got. Hand the threads to an LLM to cluster the complaints into themes, and keep the `author` and permalink of the loudest ones: someone unhappy with a competitor is already a qualified lead.

### 🚀 How to use

#### Example 1. Hot posts from multiple subreddits

```json
{
    "subreddits": ["technology", "programming", "webdev"],
    "maxPosts": 50,
    "sort": "hot"
}
```

`maxPosts` applies per subreddit, so this returns up to 150 Reddit posts across the 3 subreddits, with engagement metrics included.

#### Example 2. Search across all of Reddit (lead generation)

```json
{
    "searchQuery": "best CRM for small business",
    "maxPosts": 100,
    "sort": "top",
    "timeFilter": "month"
}
```

The month's top posts matching your query, from anywhere on Reddit. This is the shape of a lead generation run: everyone who asked for a CRM this month, each row carrying the `author` who asked and the permalink to the thread you would reply in.

#### Example 3. Posts with nested comments

```json
{
    "subreddits": ["AskReddit"],
    "maxPosts": 25,
    "sort": "top",
    "timeFilter": "week",
    "includeComments": true,
    "maxCommentsPerPost": 20
}
```

25 top posts from `r/AskReddit` this week, each with up to 20 nested comments, engagement metrics included on both the posts and the comments.

#### Example 4. Full comment threads (AI and RAG pipelines)

```json
{
    "subreddits": ["AskReddit"],
    "maxPosts": 10,
    "includeComments": true,
    "maxCommentsPerPost": 500,
    "useRichData": true
}
```

Up to 500 comments per post, with every comment's score and position in the thread. This is the richest shape for an AI pipeline: whole discussions instead of isolated quotes, with `parentId` and `depth` to rebuild each thread before you chunk and embed it.

#### Example 5. From Python (AI and LLM datasets)

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")

run_input = {
    "subreddits": ["MachineLearning", "LocalLLaMA"],
    "maxPosts": 200,
    "sort": "top",
    "timeFilter": "week",
    "includeComments": True,
    "maxCommentsPerPost": 25,
}

run = client.actor("makework36/reddit-scraper").call(run_input=run_input)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], "·", item["score"], "·", item["created"])
```

#### Example 6. From Node.js

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });

const run = await client.actor('makework36/reddit-scraper').call({
    searchQuery: 'apify reddit scraper',
    maxPosts: 50,
    sort: 'top',
    timeFilter: 'all',
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} Reddit posts`);
```

#### Example 7. From cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/makework36~reddit-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "subreddits": ["news"],
    "maxPosts": 10,
    "sort": "new"
  }'
```

### 📥 Input

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `subreddits` | array | `[]` | Subreddit names, no `r/` prefix |
| `searchQuery` | string | (none) | Search Reddit globally for this term |
| `maxPosts` | integer | `50` | Max posts per subreddit (1-500) |
| `sort` | string | `hot` | `hot`, `new`, `top`, `rising` |
| `timeFilter` | string | `day` | Time range for `top`: `hour`, `day`, `week`, `month`, `year`, `all` |
| `includeComments` | boolean | `false` | Return comments for each post |
| `maxCommentsPerPost` | integer | `100` | Comments per post. Up to 1000 with engagement metrics on, up to 100 without |
| `useRichData` | boolean | automatic | Leave it alone for the automatic behaviour in the table above. Controls comment metrics only, post metrics always arrive. `true` for comment metrics on every run, `false` to skip them |
| `proxyConfiguration` | object | (optional) | **Optional.** Leave it empty and the Actor uses its own, at no proxy cost to you |

#### About `proxyConfiguration`

**You do not need to set it.** Everything above works out of the box, at no proxy cost to you.

Set it only if you would rather the run left through an exit IP you control, for example to keep your traffic isolated or to satisfy an internal policy. Yours then takes precedence, and the run log states which one was used. If you do supply your own, it has to be a residential or ISP proxy, and the log tells you plainly when it is not, rather than quietly returning `null` fields.

### 📋 Output example

Each item in the dataset is one Reddit post. When `includeComments: true`, each post carries a `comments` array.

Real output from a run on September 2, 2026 (`subreddits: ["Drizzy"]`, `sort: "top"`, `timeFilter: "day"`, `includeComments: true`):

```json
{
    "id": "t3_1w4ne7e",
    "subreddit": "Drizzy",
    "title": "Combination.",
    "author": "Viola-Intermediate",
    "score": 245,
    "upvoteRatio": 0.9919678714859438,
    "numComments": 14,
    "url": "https://www.reddit.com/r/Drizzy/comments/1w4ne7e/combination/",
    "postLanguage": "en",
    "subredditWeeklyActiveUsers": 292024,
    "subredditSubscribers": null,
    "postType": "image",
    "totalCommentsScraped": 13,
    "comments": [
        {
            "id": "t1_p78xz7j",
            "author": "Snoo-10056",
            "body": "siri, what's the definition of aura?",
            "score": 36,
            "created": "2026-09-01T20:20:02.512000+0000",
            "depth": 0,
            "isSubmitter": false,
            "parentId": null,
            "replies": 1
        },
        {
            "id": "t1_p79g9jh",
            "author": "xnjr1x",
            "body": "🗣\"something you can't fake.\"",
            "score": 14,
            "created": "2026-09-01T21:49:32.861000+0000",
            "depth": 1,
            "isSubmitter": false,
            "parentId": "t1_p78xz7j",
            "replies": 0
        }
    ]
}
```

#### A gallery post

```json
{
    "id": "t3_1s6gkmj",
    "subreddit": "pics",
    "title": "About 100,000 attended the No Kings protest in St. Paul, Minnesota",
    "author": "katotooo",
    "score": 48213,
    "upvoteRatio": 0.94,
    "numComments": 1204,
    "url": "https://www.reddit.com/r/pics/comments/1s6gkmj/about_100000_attended_the_no_kings_protest/",
    "selftext": null,
    "thumbnail": "https://preview.redd.it/oy94fh2hnvrg1.jpg?width=140&height=93",
    "imageUrls": [
        "https://preview.redd.it/oy94fh2hnvrg1.jpg?width=3024&format=pjpg",
        "https://preview.redd.it/9pmbe5aqnvrg1.jpg?width=4032&format=pjpg"
    ],
    "media": null,
    "created": "2026-03-29T00:21:20.000Z",
    "edited": false,
    "isVideo": false,
    "isSelf": false,
    "isGallery": true,
    "domain": "reddit.com",
    "linkUrl": "https://www.reddit.com/gallery/1s6gkmj",
    "postType": "gallery",
    "scrapedAt": "2026-03-29T08:05:31.904Z"
}
```

#### A video post

```json
{
    "id": "t3_ghi789",
    "subreddit": "nextfuckinglevel",
    "title": "Robot parkour demo from Boston Dynamics",
    "score": 31877,
    "upvoteRatio": 0.97,
    "media": {"videoUrl": "https://v.redd.it/....mp4", "duration": 47},
    "postType": "video"
}
```

### ⚡ Performance

#### What a run costs

**$1.50 per 1,000 posts.** A result is one Reddit post, with its comment thread attached.

**$0.70 per 1,000 comments that carry engagement metrics**, from **September 17, 2026**. A comment is billed only when it arrives with its `score`, `depth`, `created`, `isSubmitter` and `parentId` filled in. Comments that arrive without those fields cost nothing, today and after that date. Most Reddit scrapers bill every comment as a full result at around $3 per 1,000, so this stays about 4x cheaper.

No Reddit API subscription, no proxy add-ons, no hidden fees.

| Scenario | Posts | Comments with metrics | Cost | Typical runtime |
|----------|-------|-----------------------|------|-----------------|
| 1,000 posts, no comments | $1.50 | none | **$1.50** | ~5-10 min |
| 3 subreddits × 50 posts, no comments | $0.23 | none | **$0.23** | ~1-2 min |
| 500 posts + 100 comments each (default) | $0.75 | none | **$0.75** | ~20-35 min |
| 1,000 posts + 25 comments each (default) | $1.50 | 25,000 | **$19.00** | ~15-25 min |
| 500 posts + 100 comments each, `useRichData: true` | $0.75 | 50,000 | **$35.75** | ~20-35 min |

The third row is not a mistake: above 25 comments per post the metrics are off unless you ask for them, so those 50,000 comments arrive free. The table in [Engagement metrics](#-engagement-metrics) says exactly which runs include the metrics and which do not.

#### Run timeout

A run has a time budget, and the work is sequential: 100 posts with their comment threads need about **357 seconds** of actual work. The old default of 300 seconds left about 297 usable seconds, so those runs were cut short and you got a partial dataset.

**Since September 18, 2026 the default timeout is 1200 seconds (20 minutes).** A 100 post run with comments now finishes inside the default, and nothing has to be configured to get that.

For the larger scenarios in the table above (500 to 1,000 posts with their comments, 20 to 35 minutes of runtime), raise the timeout in the run options before you start. A run that still runs out of time delivers every post it collected and ends as succeeded. The posts it could not finish carry `isPartialResult: true` (plus `commentsIncomplete: true` or `enrichmentIncomplete: true`), comments it never fetched are not charged, and the status message says how many posts were cut short.

**Tips to spend less:**

- Set `includeComments: false` when you only need the posts.
- Set `useRichData: false` when you want the comment text but not the per-comment metrics. The comments still arrive; they just cost nothing.
- Use a tight `timeFilter` (`day` or `week`) instead of `all`.
- Ask for the number of comments you will actually read. 10-25 per post captures most of the signal.
- Store the post IDs you already have and skip them on the next run.
- Schedule hourly instead of polling every few minutes. Reddit's `new` listing does not change fast enough to justify it.

### ❓ FAQ

**Does this need a Reddit API key?**
No. No API key, no OAuth, no login, no app registration.

**Do I get upvote counts?**
Yes, on every run, without setting anything. Post `score` and `upvoteRatio` always come back. Per-comment scores are the part that depends on `useRichData`, see [Engagement metrics](#-engagement-metrics) for exactly when.

**Why is `subredditSubscribers` null?**
Because the number Reddit publishes there is not the subscriber count. Measured on September 2, 2026: 292,024 for r/Drizzy, which is plausible, and 3,599,935 for r/explainlikeimfive, a subreddit with more than 20 million subscribers. Calling it a subscriber count would be wrong, so you get it as `subredditWeeklyActiveUsers` instead, with no claim about what else it might mean.

**How is this different from the official Reddit API?**
The Reddit API caps you at 60 requests a minute and 10 posts per listing page, and requires OAuth. Here there are no such limits, search and comment threads come out of the box, and you get JSON, CSV or Excel.

**What does `maxPosts` mean?**
Per subreddit, not global. 3 subreddits × 50 `maxPosts` = up to 150 posts.

**How deep do comments go?**
Up to 3 levels: top level (depth 0), replies (depth 1), replies to replies (depth 2). Every comment carries its `parentId` so you can rebuild the thread.

**How many comments can I get per post?**
Up to 1000 when engagement metrics are on, up to 100 when they are not.

**Can I scrape NSFW subreddits?**
Yes, but results may include adult content.

**Is this legal?**
Collecting public Reddit data for research, journalism and business intelligence is generally allowed under fair-use principles. Consult your legal team for your case and review [Reddit's User Agreement](https://www.redditinc.com/policies/user-agreement).

**Can I use this for lead generation?**
Yes. Every post carries `author`, `subreddit`, `url` (the permalink) and `created`, so you can filter for people asking for what you sell and answer them in the thread where they asked. Export the list as CSV or Excel for a sales team, or push it into your CRM with Apify Webhooks. Reddit is a public forum, so reply in the thread and follow each subreddit's self-promotion rules.

**Can I feed this into an LLM or a RAG pipeline?**
Yes, that is what the output is shaped for. You get normalized JSON, 29 fields per post and 10 per comment, with the thread structure preserved through `parentId` and `depth`, so you can embed whole discussions instead of isolated quotes. The text stops where the author's text stops, with no boilerplate footer to strip before chunking.

**Can I schedule recurring runs?**
Yes. Use Apify's [Scheduler](https://docs.apify.com/platform/schedules) hourly, daily or weekly, and Apify Webhooks to push new data into your own database.

### 📊 Comparison

| Feature | This Reddit Scraper | Official Reddit API | Reddit PRAW library | Generic web scrapers |
|---------|---------------------|---------------------|---------------------|----------------------|
| Reddit API key required | ❌ No | ✅ Yes (OAuth) | ✅ Yes (OAuth) | ❌ No |
| Rate limit | None | 60 req/min | 60 req/min | Varies |
| Comment threads | ✅ Nested up to depth 3 | ✅ Full tree | ✅ Full tree | ❌ Usually not |
| Upvotes and engagement | ✅ Yes | ✅ Yes | ✅ Yes | ❌ Usually not |
| Search across Reddit | ✅ Yes | ✅ Yes | ✅ Yes | ❌ Manual |
| Multiple subreddits per run | ✅ Yes | ❌ One at a time | ❌ One at a time | ❌ Manual |
| Export to JSON / CSV / Excel | ✅ All three | ❌ JSON only | ❌ Python objects | Varies |
| Maintenance burden | Apify handles it | You handle OAuth + retries | You handle OAuth + retries | You handle everything |
| Setup time | <1 minute | 30-60 minutes | 15 minutes | Hours or days |

**Use this when:**

- You need Reddit data now, without setting up OAuth.
- You want structured JSON without writing parsers.
- You are feeding Reddit data into an AI or LLM pipeline.
- You are prospecting for leads and need the `author`, the subreddit and the permalink behind every post.
- You need several subreddits in one run.
- You need CSV or Excel for people who do not write code.

**Use the official Reddit API instead when:**

- You are building a bot that posts, votes or messages.
- You need real-time events.
- You are fine with 60 requests a minute and an OAuth setup.

### 📝 Changelog

- **3.1.30** (October 5, 2026)
  - **A run that runs out of time now ends as succeeded** instead of failed. You get every post it collected; the ones cut short carry `isPartialResult: true` with the reason, comments it never fetched are not charged, and the status message says how many posts were cut short and suggests a higher timeout.
  - **Private or restricted subreddits no longer fail the run.** A run with only private subreddits succeeds with 0 results and says which ones were skipped; a run mixing public and private subreddits returns what it could and lists the skipped ones.
  - A run blocked by Reddit (HTTP 403 or 429) that delivered nothing still fails, and names the status codes it saw.
  - The Actor may record anonymous run statistics (counts and outcome only, never your subreddits, queries or results) to improve reliability.

- **3.1.18** (September 18, 2026)
  - **The default run timeout is now 1200 seconds**, raised from 300. A run of 100 posts with their comment threads needs about 357 seconds of sequential work, which did not fit in the old default, so those runs were cut short and delivered a partial dataset. They now finish inside the default, with nothing to configure. See [Performance](#-performance).
  - **Fixed: engagement metrics arrive reliably again.** Between September 17 and September 18, 2026, `score`, `upvoteRatio` and `numComments` came back `null` on runs that should have carried them. The cause is fixed and verified. The automatic ceiling of 25 comments per post is unchanged: above it, ask for the metrics with `useRichData: true`.

- **3.1** (September 2, 2026)
  - **Engagement metrics now come included on most runs.** `score`, `upvoteRatio`, `numComments`, `flair`, `awards` and the per-comment numbers arrive without setting anything, whenever you ask for posts only or for up to 25 comments per post. Above that, ask for them with `useRichData: true`. Set `useRichData: false` to skip them and finish sooner. See [Engagement metrics](#-engagement-metrics).
  - **Up to 1000 comments per post** when engagement metrics are on, instead of 100.
  - **Fixed: post and comment text no longer ends with a trailing footer.** Earlier versions appended a fixed boilerplate string and a stray `&#32;` to the end of every `selftext` and every comment `body`. Text now stops where the author's text stops.
  - **Fixed: a run that ran out of time no longer reports success.** Results that were cut short carry `isPartialResult: true` and the posts still missing their comments carry `commentsIncomplete: true`, so a truncated dataset cannot be mistaken for a complete one.
  - **Fixed: runs use the timeout you set.** Before 3.1, a longer run was cut at 10 minutes whatever timeout was configured. See 3.1.18 for the current default.
  - **Fixed: a comment fetch that failed is no longer indistinguishable from a post with no comments.** Those posts now carry `commentsFetchFailed: true`.
  - **Added: promoted posts are excluded**, so sponsored content never arrives as a result.
  - **Added: `subredditWeeklyActiveUsers`**, reported under its own name rather than as a subscriber count, because it is not one.

- **3.0** (September 1, 2026) Rebuilt after Reddit changed what it publishes. Affected fields became `null` rather than `0`.

- **1.0** Initial public release. 29 post fields, 10 comment fields, search and subreddit modes, nested comment threads, JSON/CSV/Excel export.

# Changelog

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

# Actor input Schema

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

List of subreddit names to scrape, without the 'r/' prefix (e.g. \['technology', 'programming', 'artificial']). Each subreddit contributes up to 'maxPosts' posts. If you leave this empty, you MUST provide 'searchQuery' to search across all of Reddit. Example for tech discussion: \['technology', 'programming']. Example for trading: \['wallstreetbets', 'stocks', 'investing'].

## `searchQuery` (type: `string`):

Free-text search term. Combine with 'subreddits' to search within those subreddits, or leave 'subreddits' empty to search all of Reddit. Supports Reddit search syntax (e.g. 'openai AND gpt', 'flair:news', 'author:spez'). Leave empty if you only want to list posts from specific subreddits.

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

Maximum posts per subreddit (or in total when you use searchQuery without subreddits). One post is one billable result at $1.50 per 1,000. Typical values: 25 for a quick look, 50-100 for research, 250+ for a dataset. The ceiling is 500.

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

Order in which posts are returned. 'hot' = trending now, best for monitoring. 'new' = most recent, best for real-time tracking. 'top' = highest score in the 'timeFilter' window, best for historical analysis. 'rising' = gaining traction, best for spotting content early.

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

Time window for 'top' sort. Ignored for hot, new and rising. 'day' and 'week' are the common ones. Use 'all' for the all-time top posts. Example: sort='top' with timeFilter='week' returns the week's most upvoted posts.

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

Return the comment thread of every post alongside the post. Turn it on for sentiment analysis, Q\&A, thread analysis or training data. Leave it off when you only need the posts, and the run finishes sooner. From September 17, 2026, comments that arrive with their engagement metrics cost $0.70 per 1,000 comments; comments that arrive without them are free.

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

How many comments you want per post, at most. Only used when 'includeComments' is true. Up to 1000 when engagement metrics are on, up to 100 when they are not. Typical values: 25 for a summary, 100 for the full thread. It is also what a run costs: from September 17, 2026, every comment that arrives with its metrics costs $0.0007.

## `useRichData` (type: `boolean`):

Post engagement metrics (score, upvoteRatio, numComments, flair, awards, postLanguage) are always collected, on every run, whatever this is set to. This field controls only whether COMMENTS also come back with their own metrics (score, depth, created, isSubmitter and parentId), since that part is not free. Leave it alone and comments get their metrics whenever it is worth the wait, for up to 25 comments per post, or always when you are not collecting comments at all. Above 25 comments per post you get the comments themselves but not their metrics, unless you turn this on. Turn it on to get comment metrics in every case and to ask for up to 1000 comments per post instead of 100. Turn it off to never get them, whatever maxCommentsPerPost is. From September 17, 2026, each comment delivered with its own metrics costs $0.70 per 1,000 comments, comments delivered without them are free, so turning this off leaves your cost exactly where it is today. If either the post or the comment metrics cannot be collected (no proxy, no session, or a real block), the run still returns its posts and comments with those fields null, and bills nothing for them.

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

Optional. Leave it empty and this Actor uses its own, at no proxy cost to you. Set it only if you want the run to leave through an exit IP you control; yours then takes precedence and the run log says which one was used. If you supply your own, it must be a residential or ISP proxy.

## `requestDelaySecs` (type: `integer`):

Seconds to wait between requests to Reddit. Raise it to 5-10 if you collect many subreddits in one run and see rate-limit warnings in the log. Lower it only for small runs.

## Actor input object example

```json
{
  "subreddits": [
    "technology",
    "programming"
  ],
  "searchQuery": "openai AND gpt",
  "maxPosts": 50,
  "sort": "hot",
  "timeFilter": "day",
  "includeComments": false,
  "maxCommentsPerPost": 100,
  "requestDelaySecs": 3
}
```

# Actor output Schema

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

All scraped items in the default dataset (JSON).

## `csv` (type: `string`):

Default dataset formatted as CSV for spreadsheets (Google Sheets, Excel).

# 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": [
        "technology"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("makework36/reddit-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": ["technology"] }

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

```

## MCP server setup

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