# Reddit Scraper (`labrat011/reddit-scraper`) Actor

Scrape Reddit subreddit posts, comment threads, and user profiles. Monitor communities with date filters. No API keys needed. MCP-ready for AI agents. Search is currently unavailable.

- **URL**: https://apify.com/labrat011/reddit-scraper.md
- **Developed by:** [mick\_](https://apify.com/labrat011) (community)
- **Categories:** Social media, AI, Lead generation
- **Features:** Limited permissions
- **Stats:** 380 total users, 38 monthly users, 96.0% runs succeeded, 5 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.50 / 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.

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

<img src="https://apify-image-uploads-prod.s3.us-east-1.amazonaws.com/wCP1WauwRX2Gr3Gir-actor-dejMd0QoBemGH3zTn-FKlav3B3fK-reddit-scraper.png" alt="Reddit Scraper logo" width="120">

## Reddit Scraper

Scrape Reddit subreddit posts, full comment threads, and user profiles at scale. Filter to the last 24 hours or any date window, and watch the communities that matter to you. Works with n8n, Make, and Zapier. No API keys, no login, no OAuth. MCP-ready for AI agent pipelines.

> **Current status (6 November 2026)**
>
> ✅ **Working:** Subreddit Posts (all sorts, multiple subreddits, `includeComments`), Post Comments, User Profile, and date filters (`postedAfter`, `postedBefore`).
>
> ❌ **Search is turned off:** Reddit is refusing search requests, so Search Reddit mode is switched off for now. That covers post search, comment search, batch search and search inside a subreddit. A run with `mode: "search"` is rejected with an invalid input error before it starts, so it costs nothing. To follow a topic for now, use Subreddit Posts on the communities where it comes up, with sort `new` and `postedAfter`. The search sections below are kept for reference.

### What does it do?

Reddit Scraper pulls structured data straight from Reddit, with no OAuth and no Reddit API credentials. You get clean, consistent JSON output ready for analysis, NLP pipelines, or downstream AI tools.

**v1.5.0, October 2026:** Three things customers asked of every Reddit tool, all new here. **Comment search (turned off for now, see the status note above):** turn on `searchComments` to search Reddit's comments, where most brand and product mentions live, with each comment's post title, score and comment count attached. **Date windows:** `postedAfter` and `postedBefore` take a date or a rolling window like `"24 hours"` or `"7 days"`, so a scheduled monitor only returns what is new; with sort `new` the scan stops the moment it passes the window. **Full threads:** Post Comments mode now follows every "load more comments" link, so big threads return hundreds of comments with their true reply depth, set `maxCommentsPerPost` to `0` for everything Reddit shows. Runs are also much faster: requests go out over a lightweight browser-grade HTTP client, and a real browser starts only if Reddit pushes back, so a typical run finishes in seconds.

**v1.4.0, mid-October 2026:** Reddit now blocks its `.json` listings for every logged-out client, residential IPs included. Scrapers that read them return nothing. This release reads Reddit's own server-rendered pages instead, so all four modes work again, and runs are faster: a 10-post run now takes seconds. What changed in the output: `edited`, `isOriginalContent`, `authorFlair` and `crosspostParent` now always hold their empty values because Reddit's pages do not show them.

**October 2026:** A run where Reddit blocks every request now ends as **Failed**, not as an empty Succeeded run, so schedules, webhooks and API callers see the problem. API calls that turn on Apify Proxy without choosing a group now use residential IPs, which Reddit accepts far more reliably than datacenter IPs. The default memory is now 1 GB, which halves the start fee. Search results now carry a `searchQuery` field with the query that found each post, so a multi-query run splits cleanly by query.

**v1.3.0:** Input schema rewritten for clarity, including for AI agents calling this actor over MCP. Documents that search phrases must be quoted for exact matching, that `maxResults` is a run-wide budget shared across queries, and that `timeFilter` only applies when the sort is `top`. `searchQueriesList` now renders as a string list rather than a raw JSON field. The actor also now reads Reddit's own JSON listings on `www.reddit.com`, reached through a browser challenge warm-up, instead of parsing server-rendered HTML. Output stays the same.

**v1.2.0:** Reddit started returning 403 on its public `.json` endpoints in May 2026. This release switched to parsing Reddit's server-rendered HTML, so it kept working where `.json`-based scrapers broke. Output stayed the same. (v1.3.0 replaced the HTML parsing with browser-based `.json` reads, see above.) Also added a fail-fast health check and faster request pacing.

**v1.1.0:** Added batch search (`searchQueriesList`) - run multiple queries in a single job with automatic deduplication by post ID.

### 👥 Who Uses This

#### 🏢 Brand Monitoring and Market Research

You need to know what real people say about your product, competitors, or industry - not curated press releases, but unfiltered community discussion. Reddit is where honest opinions live. This actor lets you follow the communities where your product and competitors come up, with posts and their comments in one run, ready for sentiment analysis.

**Typical input:**

```json
{
    "mode": "subreddit_posts",
    "subreddits": ["yourindustry", "competitorsubreddit"],
    "sort": "new",
    "includeComments": true,
    "postedAfter": "24 hours",
    "maxResults": 500
}
```

Run this on a daily schedule and each run returns only the last day's posts and comments, without touching the Reddit website.

***

#### 💻 NLP and ML Engineers

You need topic-specific text at scale - Reddit comments and posts for training classifiers, fine-tuning embeddings, building sentiment models, or labeling datasets. The structured output (author, score, depth, timestamp) gives you signal for quality filtering without post-processing.

**Collect training data from multiple subreddits:**

```json
{
    "mode": "subreddit_posts",
    "subreddits": ["MachineLearning", "LocalLLaMA", "datascience", "learnmachinelearning"],
    "sort": "top",
    "timeFilter": "year",
    "maxResults": 2000,
    "includeComments": true
}
```

Filter by `score` (high-upvote posts = community-validated content) and `depth` (top-level comments = more coherent standalone text). The `userContentType` field on user profile mode lets you pull comment-only output for dialogue dataset construction.

***

#### 🛠️ Product Teams and Startups

You want to understand what problems your target market is describing in their own words - not survey responses, but organic complaints, feature requests, and workaround threads. Reading the right subreddits is a fast way to do Jobs-to-Be-Done research before writing a single line of code.

**Discovery research across communities:**

```json
{
    "mode": "subreddit_posts",
    "subreddits": ["entrepreneur", "smallbusiness", "SaaS"],
    "sort": "top",
    "timeFilter": "month",
    "includeComments": true,
    "maxResults": 200
}
```

Pull the top threads from several communities in one run. Export to CSV for tagging and clustering in a spreadsheet.

***

#### 📰 Social Media Analysts and Journalists

You're tracking narratives, investigating communities, or mapping how opinions shift around a topic over time. Reddit's threaded comment structure and upvote system give you signal on consensus and dissent that flat social feeds don't provide.

**Pull comment threads from key posts:**

```json
{
    "mode": "post_comments",
    "postUrls": [
        "https://www.reddit.com/r/politics/comments/abc123/some_breaking_story/",
        "https://www.reddit.com/r/technology/comments/def456/another_post/"
    ],
    "maxCommentsPerPost": 100
}
```

Use `user_profile` mode to audit a specific account's post and comment history across subreddits - useful for investigating astroturfing, coordinated behavior, or tracking how a public figure's community engagement evolves.

***

#### 🤖 AI/LLM Engineers and Agent Builders

You're building AI pipelines that need real-time access to community knowledge. RAG systems grounded in current Reddit discussions, agents that can read subreddits on demand, or workflows that pull fresh posts into an LLM context window.

**MCP tool config for Claude Desktop / Cursor / VS Code / Windsurf / Gemini CLI:**

```json
{
    "mcpServers": {
        "reddit-scraper": {
            "url": "https://mcp.apify.com?tools=labrat011/reddit-scraper",
            "headers": {
                "Authorization": "Bearer <APIFY_TOKEN>"
            }
        }
    }
}
```

This actor works as a hosted MCP tool via Apify's MCP server. No custom server, no infrastructure. Once configured, your AI agent can call `reddit-scraper` as a tool to read any subreddit, pull comment threads, or monitor user activity. Combine with other actors for multi-source research pipelines.

**Quick setup (Claude Code):**

```
claude mcp add reddit-scraper \
  -e APIFY_TOKEN=<YOUR_APIFY_TOKEN> \
  -- npx -y @apify/actors-mcp-server@latest --actors labrat011/reddit-scraper
```

***

### Features

- **3 working scraping modes:** subreddit posts, user profiles, post comments (Search Reddit mode is turned off for now, see the status note at the top)
- **Multi-target:** subreddits, usernames, and post URLs all accept lists - scrape many at once
- **Sort and filter:** hot, new, top (with configurable time range), rising, controversial
- **Date windows:** `postedAfter` / `postedBefore` with dates or rolling windows like `"7 days"`, built for scheduled monitoring
- **Full comment threads:** every "load more comments" link is followed, with true reply depth on each comment
- **User profiles:** posts only, comments only, or both
- **NSFW filter:** optionally include or exclude adult content. Excluding it drops NSFW posts and their comment threads together
- **Pagination:** automatic page-following up to Reddit's ~1,000-item limit
- **Browser-grade requests:** a lightweight HTTP client with a real browser's network fingerprint on rotating residential IPs, falling back to headless Chrome automatically if Reddit pushes back
- **28 output fields per post** - including upvote ratio, author flair, content type hints, edit timestamps, and crosspost detection
- **Retry logic:** exponential backoff on 429, IP rotation on 403
- **Clear empty-run signal:** a run that scrapes 0 results stops with a status message naming the likely cause, and pushes no items, so there is nothing to pay per result. If Reddit blocked every request, the run ends as **Failed**, not Succeeded, so schedules, webhooks and API callers see the error instead of an empty dataset
- **Runaway-run guard:** a run that is being heavily blocked, and so is spending far more time and bandwidth than its results justify, stops early with `Stopped at N items, run resource budget exceeded` rather than burning your budget. The guard is checked every few seconds, so it also stops a run that keeps loading pages without finding a single result. Healthy runs never reach it. For scheduled monitors with `postedAfter`, use sort `new` so each run stops at the edge of the window: it finishes in seconds and returns every new match. Re-run to continue
- **Migration tolerance:** a run interrupted by an Apify platform migration restarts and carries its result count across, rather than failing

***

### Scraping modes

#### Mode 1: Subreddit Posts

Scrape posts from one or more subreddits.

```json
{
    "mode": "subreddit_posts",
    "subreddits": ["python", "machinelearning", "webdev"],
    "sort": "top",
    "timeFilter": "month",
    "maxResults": 200
}
```

Sort options: `hot`, `new`, `top`, `rising`, `controversial`. `timeFilter` applies only when the sort is `top`: `hour`, `day`, `week`, `month`, `year`, `all`.

The same rule holds in Search mode, where the sort field is `searchSort`. `timeFilter` is accepted with any sort value but only takes effect when that value is `top`. The default `relevance` sort favours highly upvoted posts, which are often years old, so pair `top` with `timeFilter` when you need recent results.

***

#### Mode 2: Search Reddit (turned off)

**Search mode is turned off for now, because Reddit is refusing search requests. A run with `mode: "search"` is rejected before it starts.** The rest of this section is kept for reference.

Search across all of Reddit or within a specific subreddit. Use `searchQueriesList` to run multiple queries in one job.

**Quote your phrases.** Reddit matches loose words by default, so an unquoted multi-word query returns mostly unrelated posts. Wrap a phrase in double quotes to match it exactly:

```json
{ "searchQuery": "\"looking for an alternative to\"" }
```

Unquoted, `looking for an alternative to` matches any post containing some of those common words. Quoted, it matches the phrase.

**Single query:**

```json
{
    "mode": "search",
    "searchQuery": "best python web framework 2025",
    "searchSort": "relevance",
    "maxResults": 100
}
```

**Batch search (v1.1.0):**

```json
{
    "mode": "search",
    "searchQueriesList": ["ChatGPT vs Claude", "best LLM 2025", "AI coding assistant"],
    "searchSort": "top",
    "timeFilter": "year",
    "maxResults": 300
}
```

Results across all queries are merged and deduplicated by post ID. Every result carries a `searchQuery` field with the query that found it, so you can split the dataset by query. `searchQueriesList` overrides `searchQuery` when provided.

`maxResults` is a budget for the whole run, not per query, and it is consumed one query at a time. With six queries and `maxResults: 25`, the first query can use the entire budget and the rest return nothing. Allow at least 25 per query you expect results from.

**Comments share that budget.** With `includeComments` on, every comment is a result, so raise `maxResults` when you turn it on. No single post may take more than a fifth of the budget, so a run always spans several posts rather than one big thread. If you want one thread in depth, that is what Post Comments mode is for: search first, then feed the post URLs into it.

**Restricted to a subreddit:**

```json
{
    "mode": "search",
    "searchQuery": "fastapi vs django",
    "searchSubreddit": "python",
    "searchSort": "top",
    "maxResults": 50
}
```

**Search comments too:**

```json
{
    "mode": "search",
    "searchQuery": "\"notion alternative\"",
    "searchPosts": true,
    "searchComments": true,
    "searchSort": "new",
    "postedAfter": "7 days",
    "maxResults": 200
}
```

With both on, posts may use up to half of `maxResults` and comments fill the rest. Comment results carry `postTitle`, `postScore` and `postNumComments` for the post they were left on, and `url` links straight to the comment.

**Only what is new:** `postedAfter` and `postedBefore` accept a date (`2026-10-01`), a date and time, or a rolling window (`"24 hours"`, `"7 days"`, `"3 months"`). They work in every mode. With `searchSort: "new"` (or `sort: "new"` for subreddits) the scan stops as soon as it passes `postedAfter`, which keeps scheduled runs fast and cheap. With other sorts, such as `hot` or `top`, a subreddit or query moves on once several pages in a row hold nothing inside the window, so a narrow window on a big feed finishes in seconds instead of reading the whole feed. For the most complete date-window results, use sort `new`.

Search sort options: `relevance`, `hot`, `top`, `new`, `comments`.

***

#### Mode 3: User Profile

Scrape posts and/or comments from Reddit user profiles.

```json
{
    "mode": "user_profile",
    "usernames": ["user1", "user2"],
    "userContentType": "overview",
    "maxResults": 200
}
```

Content type options: `overview` (posts + comments), `submitted` (posts only), `comments` (comments only).

***

#### Mode 4: Post Comments

Extract the comment thread from specific Reddit posts. Every "load more comments" link is followed, top-level and inside reply chains, so a big thread returns hundreds of comments, each with its true reply `depth`. Set `maxCommentsPerPost` to `0` to read everything Reddit shows.

```json
{
    "mode": "post_comments",
    "postUrls": [
        "https://www.reddit.com/r/Python/comments/1r19hu1/after_25_years_using_orms_i_switched_to_raw/",
        "https://www.reddit.com/r/machinelearning/comments/abc123/some_post/"
    ],
    "maxCommentsPerPost": 100
}
```

***

### Input parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `mode` | string | `subreddit_posts` | Scraping mode: `subreddit_posts`, `user_profile`, `post_comments`. `search` is turned off for now |
| `subreddits` | string\[] | - | Subreddit names (without r/ prefix). Mode: subreddit_posts |
| `sort` | string | `hot` | Sort order: `hot`, `new`, `top`, `rising`, `controversial` |
| `timeFilter` | string | `week` | Time range. Applies **only** when the sort is `top` (`sort` in subreddit mode, `searchSort` in search mode): `hour`, `day`, `week`, `month`, `year`, `all` |
| `searchQuery` | string | - | Single search term. Wrap in double quotes for exact-phrase matching. Mode: search |
| `searchQueriesList` | string\[] | `[]` | Multiple search queries, merged and deduplicated. Quote each phrase for exact matching. Overrides `searchQuery`. Mode: search |
| `searchSubreddit` | string | - | Restrict search to one subreddit. Leave empty for all of Reddit |
| `searchSort` | string | `relevance` | Search sort: `relevance`, `hot`, `top`, `new`, `comments` |
| `searchPosts` | boolean | `true` | Search mode: return matching posts |
| `searchComments` | boolean | `false` | Search mode: also return matching comments, with their post's title, score and comment count |
| `usernames` | string\[] | - | Reddit usernames (without u/ prefix). Mode: user_profile |
| `userContentType` | string | `overview` | `overview` (posts+comments), `submitted`, `comments` |
| `postUrls` | string\[] | - | Full Reddit post URLs. Mode: post_comments |
| `maxCommentsPerPost` | integer | `100` | Max comments per post. `0` = no per-post limit. In subreddit/search mode, also capped at a fifth of `maxResults` |
| `maxResults` | integer | `100` | Max results for the whole run (1–10,000), shared across all queries and consumed in order. Posts and comments share it. Free tier: 25 per run |
| `includeComments` | boolean | `false` | Also fetch comments for each post in subreddit/search mode. Counts toward `maxResults`, so raise it when turning this on. Slower, higher proxy cost |
| `includeNsfw` | boolean | `false` | Include NSFW posts. Off by default, which drops NSFW posts and the comments on them. A subreddit that is entirely NSFW returns nothing and is skipped after a few pages |
| `postedAfter` | string | - | Only items created after this: a date, a date and time, or a window like `"7 days"`. All modes |
| `postedBefore` | string | - | Only items created before this. Same formats as `postedAfter` |
| `proxyConfiguration` | object | Residential | Proxy settings. Residential proxies required. Apify Proxy with no group selected uses RESIDENTIAL; an explicit group or custom proxy URLs are kept |

***

### Output

Results are saved to the default dataset. Download as JSON, CSV, Excel, or XML from the Output tab.

#### Post fields

| Field | Type | Description |
|-------|------|-------------|
| `type` | string | Always `"post"` |
| `id` | string | Reddit post ID |
| `subreddit` | string | Subreddit name |
| `title` | string | Post title |
| `author` | string | Author username |
| `selftext` | string | Post body text. Empty for link, image and video posts |
| `url` | string | Reddit permalink |
| `externalUrl` | string | Linked URL (for link posts) |
| `score` | integer | Net upvotes |
| `numComments` | integer | Total comment count |
| `created` | string | ISO 8601 UTC timestamp |
| `isNSFW` | boolean | NSFW flag |
| `isSpoiler` | boolean | Spoiler flag |
| `isPinned` | boolean | Stickied/pinned flag |
| `flair` | string | Post flair text |
| `awards` | integer | Award (gilding) count |
| `domain` | string | Link domain (e.g. `self.python`) |
| `isVideo` | boolean | Video post flag |
| `thumbnail` | string | Thumbnail URL (empty for self/text posts) |
| `isPromoted` | boolean | Always `false`. Ads are skipped, kept for schema stability |
| `upvoteRatio` | number | Upvote ratio (0–1), community consensus signal. `null` in search results |
| `edited` | false | Always `false`. Reddit's pages do not show edit times, kept for schema stability |
| `postHint` | string | Post type hint: `link`, `image`, `hosted:video`, or empty for text posts |
| `isOriginalContent` | boolean | Always `false`, kept for schema stability |
| `authorFlair` | string | Always empty, kept for schema stability |
| `crosspostParent` | string | Always empty, kept for schema stability |
| `mediaOnly` | boolean | Always `false`, kept for schema stability |
| `isGallery` | boolean | Reddit gallery post |
| `searchQuery` | string | Search mode only: the query that found this post. A post matched by several queries keeps the first one |

#### Comment fields

| Field | Type | Description |
|-------|------|-------------|
| `type` | string | Always `"comment"` |
| `id` | string | Comment ID |
| `postId` | string | Parent post ID |
| `subreddit` | string | Subreddit name |
| `author` | string | Author username |
| `body` | string | Comment text |
| `score` | integer | Net upvotes |
| `created` | string | ISO 8601 UTC timestamp |
| `depth` | integer | Nesting depth (0 = top-level) |
| `isSubmitter` | boolean | Whether author is the post's OP |
| `awards` | integer | Always `0` for comments, kept for schema stability |
| `url` | string | Reddit permalink |
| `edited` | false | Always `false`, kept for schema stability |
| `searchQuery` | string | Search mode only: the query that found the comment or its parent post |
| `postTitle` | string | Comment search only: title of the post the comment was left on |
| `postScore` | integer | Comment search only: that post's score |
| `postNumComments` | integer | Comment search only: that post's comment count |

#### Example output

```json
{
    "type": "post",
    "id": "1r19hu1",
    "subreddit": "Python",
    "title": "After 25 years using ORMs, I switched to raw SQL",
    "author": "example_user",
    "selftext": "Here's what I learned after making the switch...",
    "url": "https://www.reddit.com/r/Python/comments/1r19hu1/...",
    "externalUrl": "",
    "score": 1842,
    "numComments": 312,
    "created": "2025-03-01T09:14:22+00:00",
    "isNSFW": false,
    "isSpoiler": false,
    "isPinned": false,
    "flair": "Discussion",
    "awards": 5,
    "domain": "self.Python",
    "isVideo": false,
    "thumbnail": "",
    "isPromoted": false,
    "upvoteRatio": 0.89,
    "edited": false,
    "postHint": "",
    "isOriginalContent": false,
    "authorFlair": "",
    "crosspostParent": "",
    "mediaOnly": false,
    "isGallery": false
}
```

***

### Cost

This actor uses **pay-per-event (PPE) pricing**. You pay for results, not for machine time.

- **$0.0015 per result**, charged on each item pushed to the dataset, so **$1.50 per 1,000 results**
- **$0.02 per GB of actor memory** when the run starts, which is $0.02 on the default 1 GB
- **Nothing else.** Compute time and residential proxy traffic are not billed to you, they are already covered by the per-result price
- **Free Apify plan: 25 results per run.** Any paid Apify plan raises the limit to 10,000
- **Your spending cap is respected.** Set a maximum total charge on the run and the actor works out how many results it covers, stops there, and says so in the log

**Worked pricing example:**
Scraping r/python, sorted by top of the month, returning 100 results on the default 1 GB:

- 100 results × $0.0015 = **$0.15**
- actor start, 1 GB × $0.02 = **$0.02**
- **Total: $0.17 per run**

A subreddit page returns ~25 posts, and requests go out about twice a second over rotating residential IPs, so a 100-post subreddit run finishes in seconds. Enabling `includeComments` adds requests per post, and makes every comment a billable result, so raise `maxResults` to match.

***

### MCP Integration

This actor works as an MCP tool via Apify's hosted MCP server. No custom server needed - AI agents can call it directly.

- **Endpoint:** `https://mcp.apify.com?tools=labrat011/reddit-scraper`
- **Auth:** `Authorization: Bearer <APIFY_TOKEN>`
- **Transport:** Streamable HTTP
- **Works with:** n8n, Make, Zapier, Claude Desktop, Cursor, VS Code, Windsurf, Warp, Gemini CLI

**Claude Desktop / Cursor config:**

```json
{
    "mcpServers": {
        "reddit-scraper": {
            "url": "https://mcp.apify.com?tools=labrat011/reddit-scraper",
            "headers": {
                "Authorization": "Bearer <APIFY_TOKEN>"
            }
        }
    }
}
```

AI agents can scrape subreddit posts, pull full comment threads, and monitor user activity, all as a callable tool without managing any infrastructure. Search mode is turned off for now. Every result is flat JSON with stable field names, so an agent can read it without post-processing.

**Ask it for what an agent usually needs:**

- **"What's new in this community this week?"** Subreddit Posts mode with `sort: "new"` and `postedAfter: "7 days"`.
- **"Read this whole discussion."** Post Comments mode with `maxCommentsPerPost: 0`. Every comment carries its reply `depth`, so the thread can be rebuilt.
- **"Watch these subreddits every day."** The same run on a schedule with `postedAfter: "24 hours"` returns only what is new, and stops scanning as soon as it passes that point.

**If you are calling this from an agent, these settings matter most:**

- **Quote your phrases.** Reddit matches loose words unless a phrase is quoted, so `"looking for an alternative to"` and `looking for an alternative to` return very different results. The unquoted form succeeds and returns mostly unrelated posts, with no error to signal it.
- **Use `postedAfter` for recency.** It takes a rolling window like `"24 hours"` or `"7 days"` and works in every mode. `timeFilter` only applies when the sort is `top`.
- **Set a spending cap.** Give the run a maximum total charge and it stops at the number of results that covers, which keeps an autonomous agent inside its budget.

***

### Technical details

- Reads Reddit's own server-rendered pages on `www.reddit.com`, no API credentials, no OAuth
- Fetches page HTML with a browser-impersonating HTTP client, so no browser has to start for a normal run. If Reddit refuses that client, the run switches to headless Chromium with matched user-agent and client-hint profiles. Either way only the HTML is loaded, never images, scripts or styles
- Paced at about two requests per second with jitter, over rotating residential IPs that change every few dozen requests
- Exponential backoff on 429 (3s base, doubles per retry); IP rotation on 403 and 503
- Pagination by following the next-page link Reddit renders (up to ~1,000 items per listing)
- Results pushed in batches of 25 for memory efficiency
- A run that yields 0 results stops with a status message naming the likely cause. A run where Reddit blocked every request is marked Failed
- A run whose time and bandwidth outgrow what its result count justifies, which in practice means one that is being heavily blocked, stops early and says so in its status message
- The running result count is persisted, so a platform migration mid-run does not fail the run

***

### Limitations

- Search mode is turned off for now, because Reddit is refusing search requests. This covers post search, comment search, batch search and search inside a subreddit
- Reddit caps listing pagination at roughly 1,000 items per subreddit/user endpoint
- Comment threads hold what Reddit shows logged-out visitors, which leaves out removed and deleted comments, so a thread can return fewer comments than its `numComments` count
- A platform migration mid-run does not resume the exact position. The result count carries over, so the run still finishes at the size you asked for, but items returned before the interruption can appear a second time. Deduplicate on `id` if you run large jobs

***

### FAQ

#### Is it legal to scrape Reddit?

Web scraping of publicly available data is generally legal, as established by the *hiQ Labs v. LinkedIn* ruling. This actor only accesses public Reddit content visible to any anonymous browser visitor. It does not bypass login walls, CAPTCHAs, or access private content.

#### Why are residential proxies required?

Reddit blocks nearly all datacenter IP ranges. Residential proxies route requests through real ISP connections that Reddit does not filter. Without them, many requests return 403s. If you call the actor through the API with `{"useApifyProxy": true}` and no group, it uses RESIDENTIAL for you.

#### How does batch search work?

Batch search is turned off for now, along with the rest of Search mode. This is how it works when search is available:

Set `searchQueriesList` to an array of query strings. The actor runs each query sequentially and merges results into a single dataset, removing duplicate posts (matched by Reddit post ID). This is useful for brand monitoring (track multiple product names in one run), competitive research, or collecting data across related topics.

#### Can I use this with the Apify API?

Yes. Call the actor via the Apify REST API and poll for results, or use the Apify Python or JavaScript client libraries. Results are available in JSON, CSV, Excel, and XML formats.

#### What happens if a subreddit, user, or post URL doesn't exist?

The scraper logs a warning and skips the invalid target. All remaining valid targets in the same run continue as normal.

***

### 🔗 Related Actors

| Actor | What it does | Pairs well with Reddit Scraper when... |
|-------|-------------|----------------------------------------|
| [Academic Paper Scraper](https://apify.com/labrat011/academic-paper-scraper) | Google Scholar, Semantic Scholar, arXiv | You find a paper discussed on Reddit and want the full metadata and abstract |
| [PubMed Scraper](https://apify.com/labrat011/pubmed-scraper) | 35M+ biomedical abstracts from NCBI | r/science or health subreddit posts reference medical studies you want to retrieve |
| [Clinical Trials Scraper](https://apify.com/labrat011/clinical-trials-scraper) | ClinicalTrials.gov study data | Reddit health communities discuss ongoing trials you want to track |
| [LinkedIn Jobs Scraper](https://apify.com/labrat011/linkedin-jobs-scraper) | Job postings and company data | You monitor r/cscareerquestions or industry subreddits and want matching job listings |
| [NPI Provider Contact Finder](https://apify.com/labrat011/npi-provider-contact-finder) | Healthcare provider directory | Health subreddit discussions lead to provider lookup needs |

***

### n8n example

**Currently unavailable:** this workflow uses Search mode, which is turned off for now because Reddit is refusing search requests. It will not run until search is back.

A ready-to-import n8n workflow: scheduled Reddit search, phrase tagging, and
append to Google Sheets. It searches the language people use when they are
frustrated rather than product names, which surfaces buying-intent posts
before anyone has named a specific tool. The workflow ships with the Actor
source and carries no credentials.

**Setup**

1. Install the Apify community node. n8n does not ship one:
   `Settings > Community nodes > Install > @apify/n8n-nodes-apify`
2. On the `Search Reddit for Pain Points` node, add your Apify API token. A
   free token works; free accounts are capped at 25 results per run.
3. On the `Log Pain Points to Sheet` node, connect Google and paste your
   spreadsheet ID. Set **Mapping Column Mode** to `Map Automatically`.
4. Name the sheet tab `Reddit Pain Points` and put these twelve headers in
   row 1, in any order: `date, id, title, url, subreddit, author, score,
   comments, upvoteRatio, matchedPhrase, body, created`. Auto-mapping matches
   on header name, so a missing header silently drops that column.
5. Edit `searchQueriesList` in the Apify node to your own phrases.

Two settings decide whether this works. **Quote your phrases**: Reddit matches
loose words by default, so `looking for an alternative to` unquoted returns
posts sharing a few common words, which is close to random. Quoted, it matches
the phrase. And **use `searchSort: "top"` together with `timeFilter`**: the
default `relevance` sort favours highly upvoted posts that are often years
old, and `timeFilter` only takes effect when the sort is `top`.

### License

MIT.

### Feedback

Found a bug or have a feature request? Open an issue on the Issues tab in Apify Console.

# Actor input Schema

## `mode` (type: `string`):

What type of Reddit data to scrape.

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

List of subreddit names to scrape (without r/ prefix). Example: python, webdev, machinelearning

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

How to sort subreddit posts.

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

Time range filter. Applies ONLY when the sort is Top: that means sort='top' in Subreddit Posts mode, or searchSort='top' in Search mode. With any other sort value this field is accepted but has no effect.

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

Keyword or phrase to search across Reddit. IMPORTANT: Reddit matches loose words by default, not phrases. To match an exact phrase, wrap it in double quotes: "looking for an alternative to". (When sending input as JSON, the quotes must be escaped.) An unquoted multi-word query returns largely unrelated posts. Use searchQueriesList for multiple queries in one run.

## `searchQueriesList` (type: `array`):

Run multiple search queries in a single job. Results are merged and deduplicated by post ID, and this field overrides Search Query when provided. IMPORTANT: wrap each phrase in double quotes for exact-phrase matching, for example "looking for an alternative to" as one entry and "is there a tool that" as another. (When sending input as JSON, the inner quotes must be escaped.) Unquoted phrases return loosely matched, mostly irrelevant posts. Note that maxResults is a shared budget across all queries and is consumed in order, so later queries return nothing once it is used up. Ideal for brand monitoring, competitor research, and topic mapping.

## `searchSubreddit` (type: `string`):

Optional: restrict search to a specific subreddit (without r/ prefix). Leave empty to search all of Reddit.

## `searchSort` (type: `string`):

How to sort search results. Relevance, the default, favours highly upvoted posts, which are often several years old. For recent results use Top together with timeFilter, or New for the newest posts regardless of engagement.

## `searchPosts` (type: `boolean`):

Return matching posts. On by default.

## `searchComments` (type: `boolean`):

Also return matching comments, which is where most brand and product mentions live. Each comment carries the title, score and comment count of the post it was left on (postTitle, postScore, postNumComments). Counts toward maxResults.

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

List of Reddit usernames to scrape (without u/ prefix).

## `userContentType` (type: `string`):

What type of content to scrape from user profiles.

## `postUrls` (type: `array`):

Full Reddit post URLs to extract comments from.

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

Maximum number of comments to extract per post, nested replies included. Set to 0 to read the whole thread. In Subreddit Posts and Search mode, comments count toward maxResults and a single post may use at most a fifth of it, so one long thread cannot fill the run before the second post is reached. The run log says so when that lowers this number. Post Comments mode is not capped this way: there the thread is the target.

## `maxResults` (type: `integer`):

Maximum number of results for the whole run. This is a shared total, not a per-query limit: when using searchQueriesList the budget is consumed one query at a time, so allow at least 25 per query you expect results from. Free Apify plan users are limited to 25 results per run. Any paid Apify plan allows up to 10,000.

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

When scraping posts (subreddit or search mode), also fetch comments for each post. Comments count toward maxResults, so raise maxResults when you turn this on. No single post may use more than a fifth of the budget, which keeps a run spread across several posts. To pull one thread in depth, use Post Comments mode instead. Slower and uses more proxy traffic.

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

When enabled, adult/NSFW content is included in results. Default is off, which filters out NSFW posts and the comments on them, so a filtered post never leaves its thread behind.

## `postedAfter` (type: `string`):

Only return posts and comments created after this point. Use a date (2026-10-01), a date and time (2026-10-01T12:00:00Z), or a window back from now such as '24 hours', '7 days' or '3 months', which suits scheduled runs. With sort 'new', the scan stops as soon as it passes this point, which keeps monitoring runs fast.

## `postedBefore` (type: `string`):

Only return posts and comments created before this point. Same formats as postedAfter.

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

Proxy settings. Residential proxies are strongly recommended, Reddit blocks most datacenter IPs.

## Actor input object example

```json
{
  "mode": "subreddit_posts",
  "subreddits": [
    "python"
  ],
  "sort": "hot",
  "timeFilter": "week",
  "searchQuery": "machine learning",
  "searchQueriesList": [],
  "searchSort": "relevance",
  "searchPosts": true,
  "searchComments": false,
  "usernames": [
    "spez"
  ],
  "userContentType": "overview",
  "postUrls": [
    "https://www.reddit.com/r/Python/comments/1r19hu1/after_25_years_using_orms_i_switched_to_raw/"
  ],
  "maxCommentsPerPost": 100,
  "maxResults": 100,
  "includeComments": false,
  "includeNsfw": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Dataset containing all scraped posts and comments

# 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"
    ],
    "searchQuery": "machine learning",
    "searchQueriesList": [],
    "usernames": [
        "spez"
    ],
    "postUrls": [
        "https://www.reddit.com/r/Python/comments/1r19hu1/after_25_years_using_orms_i_switched_to_raw/"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("labrat011/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": ["python"],
    "searchQuery": "machine learning",
    "searchQueriesList": [],
    "usernames": ["spez"],
    "postUrls": ["https://www.reddit.com/r/Python/comments/1r19hu1/after_25_years_using_orms_i_switched_to_raw/"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("labrat011/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": [
    "python"
  ],
  "searchQuery": "machine learning",
  "searchQueriesList": [],
  "usernames": [
    "spez"
  ],
  "postUrls": [
    "https://www.reddit.com/r/Python/comments/1r19hu1/after_25_years_using_orms_i_switched_to_raw/"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call labrat011/reddit-scraper --silent --output-dataset

```

## MCP server setup

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