# 🔴 Reddit Comment Scraper Plus 💬 (`scrapio/reddit-comments-scraper`) Actor

Use Reddit Comments Scraper to gather Reddit comment data at scale. Capture comment threads, upvotes, authors, and posting time to analyze discussions, audience sentiment, and community engagement patterns.

- **URL**: https://apify.com/scrapio/reddit-comments-scraper.md
- **Developed by:** [Scrapio](https://apify.com/scrapio) (community)
- **Categories:** Automation, Lead generation, Social media
- **Stats:** 9 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$14.99/month + usage

To use this Actor, you pay a monthly rental fee to the developer. The rent is subtracted from your prepaid usage every month after the free trial period.You also pay for the Apify platform usage, which gets cheaper the higher Apify subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#rental-actors

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### Reddit Comment Scraper — Extract Comments, Replies and Posts

Reddit Comment Scraper Plus pulls comment threads from any Reddit post — every top-level comment, every nested reply, and the parent post's own submission record — delivered as typed JSON rows in your Apify dataset, not raw HTML you have to parse yourself. Point it at a single post URL for one thread, or a subreddit or user URL to auto-discover posts first. Real ISO-8601 timestamps, full thread metadata (OP flag, awards, flair, distinguished badges, nesting depth), nine comment-level filters, and optional LLM sentiment/topic enrichment ship with every run. This guide covers every input and output field, and how teams actually deploy it.

### 🧭 What Does Reddit Comment Scraper Plus Do?

Reddit Comment Scraper Plus is an Apify Actor that fetches Reddit comment data through Reddit's own OAuth API host (`oauth.reddit.com`) using an anonymous "installed\_client" bearer token — a device-grant flow that needs no user login, no client secret, and no Reddit account of your own. Requests impersonate a Chrome 131 TLS fingerprint via `curl_cffi`, because Reddit's anonymous public `.json` endpoints now return a blocking Fastly edge page from every IP and proxy tier the actor's author tested. No Reddit account, cookies, or user-supplied credentials are required anywhere in the flow — the bearer token is negotiated by the actor itself, fresh, on every run. It returns three entity types from a single run: **comments**, **replies**, and the **post** they belong to.

- 💬 **Comments** — every top-level comment on a post, in your chosen sort order (Best/Top/New/Controversial/Old/Q\&A/Hot)
- ↩️ **Replies** — nested replies collected as their own rows (`type = reply`, `isReply = true`), linked to their parent via `parentId`, and mirrored to a per-run `replies-<runId>` dataset
- 📌 **Post record** — one row per post (`type = post`) carrying `title`, `selftext`, score, upvote ratio, comment count, author, and creation date
- 🔎 **Auto-discovery** — paste a subreddit or user URL instead of a post URL and the actor discovers up to `maxPosts` posts first, then scrapes each one for comments
- 🧹 **Nine comment-level filters** — keyword include/exclude, minimum score, oldest date, exclude deleted/removed, exclude AutoModerator, OP-only — applied to comment and reply rows only; the post record is always kept
- 🤖 **Optional AI enrichment** — sentiment, emotion, topics, language, and a toxicity score added per comment, via any of seven LLM providers, off by default
- 🌐 **Proxy honored exactly** — your `proxyConfiguration` selection is used as configured on every request, with no hidden fallback tier

### ⚡ Features & Capabilities

What follows is what the actor actually extracts, how it stacks up against the most-documented competing Reddit scrapers, and where a different tool is the honest choice.

#### Core features

- Full comment/reply record with 41 fields per row (see Output Format below), including exact Reddit metadata: `distinguished`, `stickied`, `gilded`, `awardCount`, `controversiality`, `authorFlair`, `authorFullname`
- Derived metrics computed at scrape time, not passed through raw: `ageHours` (hours since creation), `wordCount`, and `engagementScore` — `score / max(ageHours, 1.0)`, rounded to 3 decimals
- Reply rows are pushed live to the default dataset **and** mirrored to a per-run `replies-<runId>` dataset, so you can export just the reply set without filtering the combined dataset
- `sortOrder` maps directly to six of Reddit's own comment-sort values, plus `best` → Reddit's internal `confidence` sort
- Optional multi-provider AI enrichment (Anthropic, OpenAI, Google, xAI, DeepSeek, Perplexity, Mistral — auto-detected from the model name) adds `sentiment`, `emotion`, `language`, `topics`, and `toxicityScore`; every one of those fields stays `null` if `aiEnhancement` is off or no valid API key is supplied
- On an HTTP 401 from Reddit's API, the actor refreshes its bearer token and retries the same request automatically — no run failure from a single expired token

#### How Reddit Comment Scraper Plus compares to other Reddit scrapers

| Feature | Reddit Comment Scraper Plus | harshmaur/reddit-scraper | betterdevsscrape/reddit-scraper |
| --- | --- | --- | --- |
| Output format | Typed JSON dataset rows | JSON, CSV, Excel, XML, HTML (as observed on the Apify Store on 2026-07-26) | JSON, CSV, Excel (as observed on the Apify Store on 2026-07-26) |
| Entity coverage | Comments, replies, and the parent post record | Posts, comments, user profiles, and communities (as observed on the Apify Store on 2026-07-26) | Posts, comments, communities, and users (as observed on the Apify Store on 2026-07-26) |
| Reply-thread extraction | ✅ dedicated `includeReplies` / `maxRepliesPerComment`, mirrored to a per-run dataset | "Complete comment threads … including nested replies" (as observed on the Apify Store on 2026-07-26) | Fetches "collapsed/hidden comments beyond Reddit's initial ~500" (as observed on the Apify Store on 2026-07-26) |
| Comment-level filters | ✅ 6 filters: keyword include/exclude, min score, oldest date, exclude deleted/AutoMod, OP-only | Not documented at comment level — only post-level filters (score, flair, domain, author) are documented (as observed on the Apify Store on 2026-07-26) | Only post-level filters documented (`minScore`, `flairFilter`, `domainFilter`, `authorFilter`) (as observed on the Apify Store on 2026-07-26) |
| Built-in AI enrichment | ✅ optional sentiment/emotion/language/topics/toxicity via 7 LLM providers | Not documented | Not documented |
| Reddit login required | No | No (as observed on the Apify Store on 2026-07-26) | No (as observed on the Apify Store on 2026-07-26) |

If your use case is feeding structured data to an LLM, the output format row is the decision-maker — HTML parsing inside an agent loop is a reliability failure mode, not a feature. Every field above is a typed JSON primitive by the time it reaches your dataset.

#### When another tool might suit you better

If you need keyword search across all of Reddit (not just a fixed post, subreddit, or user), or subreddit/community metadata like member counts and rules, or full user-profile fields (karma breakdown, account age, verification), harshmaur/reddit-scraper documents all three on its Apify Store listing (as observed on 2026-07-26) — this actor does none of them; it discovers posts only from a subreddit or user URL you supply, and never returns a standalone community or user-profile row. If AI enrichment isn't something you need and you only want comments as fast and cheaply as possible with no LLM calls in the loop, either competitor is a leaner choice for that narrower job.

#### Reddit Comment Scraper Plus within the Scrapio data stack

Reddit Comment Scraper Plus is Scrapio's only Reddit actor — it covers comments, replies, and post context from a single run. For other platforms in the Scrapio stack, see Related Scrapers & Tools below.

### Why do developers and data teams scrape Reddit?

#### 🏢 Community managers and brand teams

Feed a subreddit URL into `startUrls`, set `keywords` to your brand or product name, and turn on `excludeAutoMod` and `excludeDeleted` to cut noise before it counts toward `maxComments`. The dataset gives you `contentText`, `upvotes`, `author`, and `subreddit` per comment — enough to see what a community is actually saying about you without opening Reddit or paying for the official API's rate-limited access. `minScore` lets you focus on comments the community itself has already surfaced as worth reading.

#### 📊 AI training data and RAG indexing

`contentText` is the highest-information text field on every comment and reply row — the actual human-written text, not metadata — and it's populated on every row regardless of any other setting. For **RAG enrichment**, `parentId` lets you reconstruct a comment's place in its thread, and the linked post row (`postId`) carries the original submission's `title` and `selftext` as surrounding context. For **training data**, turning on `aiEnhancement` adds `sentiment`, `emotion`, `topics`, and `language` as structured, consistently-typed annotations per comment — but only when a valid provider API key is supplied; without one those fields return `null` on every row, not fabricated values.

#### 📱 Competitive and market intelligence

Run the actor on a schedule against a competitor's brand-name keyword or a relevant subreddit, and track `upvotes` and `engagementScore` deltas between runs to see which mentions are actually gaining traction versus sitting flat. `ageHours` on every row lets you profile how quickly a thread is accumulating comments, and `excludeKeywords` filters out unrelated noise (giveaways, unrelated crossposts) before it counts against your `maxComments` budget.

#### 🔬 Research and academic use

The actor returns only what the Reddit OAuth API serves to an anonymous, logged-in-nowhere client — no private subreddits, no quarantined communities requiring a session, no friends-only content. Comment threads (`parentId` through `depth`) support discourse-analysis and content-moderation research on public subreddits, within the bounds of what Reddit already makes publicly visible.

#### 🎥 Product and SaaS development

Because output is a stable, typed schema rather than scraped HTML, teams build monitoring dashboards, sentiment-tracking tools, and enrichment APIs directly on top of the dataset — join `postId` across comment and reply rows to reconstruct full threads, or pipe `subreddit` and `engagementScore` into an internal trend-tracking dashboard without maintaining Reddit-specific scraping code in-house.

### 🍚 Input Parameters

All 18 parameters, exactly as defined in `.actor/actor.json`. Only `startUrls` is required.

| Parameter | Required | Type | Description | Example Value |
| --- | --- | --- | --- | --- |
| `startUrls` | Yes | array | One or more Reddit URLs: a post URL (scrapes its comments), a subreddit URL (auto-discovers posts), or a user URL (scrapes that user's recent comments). Bare post IDs and `redd.it` short links are also accepted. | `["https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/"]` |
| `sortOrder` | No | string | How Reddit sorts the comment thread before scraping. Enum: `best` (⭐ confidence), `top` (🔝), `new` (🆕), `controversial` (⚔️), `old` (🕰️), `qa` (❓), `hot` (🔥). Default `top`. | `"top"` |
| `maxComments` | No | integer | Max TOP-LEVEL comments to collect per post. `0` = unlimited. Min `0`, max `10000`, default `50`. Replies are additional, capped separately by `maxRepliesPerComment`. | `50` |
| `includeReplies` | No | boolean | Collect nested replies in addition to top-level comments. Reply rows are labelled `type='reply'`, `isReply=true`, linked via `parentId`, and mirrored to a per-run `replies-<runId>` dataset. Default `true`. | `true` |
| `maxRepliesPerComment` | No | integer | Max reply rows (all nesting levels) per top-level comment. `0` = unlimited. Min `0`, max `5000`, default `10`. Only applies when `includeReplies` is on. | `10` |
| `includePost` | No | boolean | Emit one `type='post'` row per post with `title`, `selftext`, score, upvote ratio, comment count, author, and creation date. Default `true`. | `true` |
| `maxPosts` | No | integer | When a subreddit or user URL is provided, how many posts to auto-discover and scrape. Ignored for direct post URLs. Min `1`, max `250`, default `10`. | `10` |
| `keywords` | No | array | Keep only comments whose text contains at least one of these words/phrases (case-insensitive). Empty = keep all. Never filters out the post record. | `["update", "release"]` |
| `excludeKeywords` | No | array | Drop comments whose text contains any of these words/phrases (case-insensitive). | `["giveaway"]` |
| `minScore` | No | integer | Keep only comments with at least this many upvotes. Default `0` (keep all). Scores can be negative on Reddit. | `5` |
| `oldestDate` | No | string | Keep only comments created on or after this date. Accepts an absolute date (`YYYY-MM-DD`) or a relative value like `"7 days"`, `"3 months"`. Empty = no date filter. | `"7 days"` |
| `excludeDeleted` | No | boolean | Skip comments whose author or body is `[deleted]` or `[removed]`. Default `false`. | `true` |
| `excludeAutoMod` | No | boolean | Skip comments posted by AutoModerator. Default `false`. | `true` |
| `onlyOP` | No | boolean | Keep only comments written by the post's original poster (`is_submitter=true`). Default `false`. | `false` |
| `aiEnhancement` | No | boolean | Analyze each comment's text with an LLM to add sentiment, emotion, topics, language, and a toxicity score. Requires an API key below or the matching provider env var. Default `false`. | `false` |
| `aiModel` | No | string | Provider auto-detected from the name: `claude-*`=Anthropic, `gpt-*`/`o1`/`o3`=OpenAI, `gemini-*`=Google, `grok-*`=xAI, `deepseek-*`=DeepSeek, `sonar*`=Perplexity, `mistral-*`=Mistral. Default `"claude-haiku-4-5"`. | `"claude-haiku-4-5"` |
| `aiApiKey` | No | string (secret) | API key for the selected provider. Optional if the matching env var is set on the actor (`ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GEMINI_API_KEY` / `XAI_API_KEY` / `DEEPSEEK_API_KEY` / `PERPLEXITY_API_KEY` / `MISTRAL_API_KEY`). | — |
| `proxyConfiguration` | No | object | Reddit rate-limits and blocks datacenter IPs on its endpoints, so RESIDENTIAL proxy is strongly recommended. Your selection is honored exactly — no hidden fallback. Default: `{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}`. | `{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}` |

```json
{
  "startUrls": ["https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/"],
  "sortOrder": "top",
  "maxComments": 100,
  "includeReplies": true,
  "maxRepliesPerComment": 20,
  "includePost": true,
  "maxPosts": 10,
  "keywords": [],
  "excludeKeywords": ["giveaway"],
  "minScore": 0,
  "oldestDate": "",
  "excludeDeleted": true,
  "excludeAutoMod": true,
  "onlyOP": false,
  "aiEnhancement": false,
  "aiModel": "claude-haiku-4-5",
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

#### Supported URL types and input formats

`startUrls` entries are classified by the actor's own URL router before any request is made:

- **Post URL** → scrapes its comments: `https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/`
- **Subreddit URL** → auto-discovers up to `maxPosts` posts and scrapes each: `https://www.reddit.com/r/ChatGPT/`
- **User URL** → scrapes that user's recent comments/posts: `https://www.reddit.com/user/spez/`
- **Bare post ID** → e.g. `1epeshq` or `t3_1epeshq`, matched by pattern and expanded to a full comments URL
- **`redd.it` short link** → e.g. `https://redd.it/1epeshq`, resolved to the same comments URL as the full post link

Any URL that doesn't match a post, subreddit, or user pattern is logged as unrecognized and skipped — the run continues with the remaining entries rather than failing outright.

### 📦 Output Format

Every row is typed JSON pushed live to the default dataset as it's collected. Export from the Apify Console or API in any of Apify's standard dataset formats (JSON, CSV, Excel, XML, RSS). The Console's default dataset view surfaces 25 of the fields below for quick scanning — every field listed here is still present on every row.

#### Output for comments and replies

Comments and replies share one row schema (41 fields); `type`, `isReply`, `isTopLevel`, and `parentId` tell them apart. A comment's `parentId` is `null` (its parent is the post); a reply's `parentId` is the normalized id of the comment or reply it replies to.

```json
{
  "type": "comment",
  "isReply": false,
  "isTopLevel": true,
  "subreddit": "ChatGPT",
  "subredditId": "t5_2xhpi",
  "title": "These are all AI generated, no human made any of this art",
  "commentId": "lh27ab3",
  "postId": "t3_1epeshq",
  "parentId": null,
  "parentFullId": "t3_1epeshq",
  "author": "example_user",
  "authorFullname": "t2_9f8g7h6",
  "authorFlair": null,
  "isSubmitter": false,
  "distinguished": null,
  "stickied": false,
  "createdAt": "2024-08-05T14:22:10Z",
  "edited": false,
  "editedAt": null,
  "upvotes": 214,
  "controversiality": 0,
  "depth": 0,
  "gilded": 0,
  "awardCount": 1,
  "locked": false,
  "archived": false,
  "contentText": "The level of detail on some of these is honestly impressive.",
  "bodyHtml": "&lt;div class=\"md\"&gt;&lt;p&gt;The level of detail on some of these is honestly impressive.&lt;/p&gt;&lt;/div&gt;",
  "permalink": "https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/lh27ab3/",
  "userUrl": "https://www.reddit.com/user/example_user/",
  "url": "https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/",
  "ageHours": 18.42,
  "replyCount": 3,
  "wordCount": 11,
  "engagementScore": 11.618,
  "sentiment": null,
  "emotion": null,
  "language": null,
  "topics": null,
  "toxicityScore": null,
  "scrapedAt": "2026-07-26T09:14:02Z"
}
```

A reply to the comment above carries `"type": "reply"`, `"isReply": true`, `"isTopLevel": false`, `"parentId": "lh27ab3"`, and `"depth": 1` — otherwise the same 41 keys.

#### Output for the post record

The post row adds five fields the comment/reply schema doesn't carry (`upvoteRatio`, `numComments`, `over18`, `selftext`, `postUrl`) for 46 fields total. `commentId`, `parentId`, and `parentFullId` are always `null` on a post row; `isSubmitter`, `controversiality`, and `depth` are always `null` too, since none of those apply to a submission.

```json
{
  "type": "post",
  "isReply": false,
  "isTopLevel": null,
  "subreddit": "ChatGPT",
  "subredditId": "t5_2xhpi",
  "title": "These are all AI generated, no human made any of this art",
  "commentId": null,
  "postId": "t3_1epeshq",
  "parentId": null,
  "parentFullId": null,
  "author": "op_username",
  "authorFullname": "t2_1a2b3c4",
  "authorFlair": null,
  "isSubmitter": null,
  "distinguished": null,
  "stickied": false,
  "createdAt": "2024-08-04T20:01:00Z",
  "edited": false,
  "editedAt": null,
  "upvotes": 5423,
  "upvoteRatio": 0.92,
  "numComments": 812,
  "controversiality": null,
  "depth": null,
  "gilded": 0,
  "awardCount": 4,
  "locked": false,
  "archived": false,
  "over18": false,
  "contentText": "",
  "selftext": "",
  "postUrl": "https://i.redd.it/abc123def456.jpg",
  "bodyHtml": null,
  "permalink": "https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/",
  "userUrl": "https://www.reddit.com/user/op_username/",
  "url": "https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/",
  "ageHours": 42.1,
  "replyCount": 812,
  "wordCount": 0,
  "engagementScore": 128.81,
  "sentiment": null,
  "emotion": null,
  "language": null,
  "topics": null,
  "toxicityScore": null,
  "scrapedAt": "2026-07-26T09:14:00Z"
}
```

#### Schema stability and export options

Field names are fixed by this actor's own row-building code (`build_comment_record` and `build_post_record` in `src/main.py`), not passed through raw from Reddit's internal API field names — you build against `contentText`, `upvotes`, `authorFullname`, and so on, whatever Reddit calls the underlying key on its side.

Only `comment` and `reply` rows are charged, under the `row_result` event. The `post` row is pushed with no charged event attached — an uncharged bonus context row, one per post. Reply rows are additionally mirrored, unmodified and still uncharged, to a per-run dataset named `replies-<runId>` when the actor is running on the Apify platform. To isolate the free context rows from the charged ones in the default dataset, filter with `item["type"] == "post"`.

### 💡 Reddit Comment Scraper Plus Strategy Guide

#### 🎯 Strategy 1: Real-time enrichment pipeline

Trigger a run whenever a new Reddit post URL enters your system — a support ticket, a mention alert, a link shared in Slack. Call the actor with that single URL in `startUrls` and a modest `maxComments` (20–50) to keep the run fast. Read back `contentText`, `upvotes`, and `awardCount` from the top comments and write them onto the source record as an engagement snapshot — a support or community team gets thread context without opening Reddit.

#### 🎯 Strategy 2: Scheduled monitoring and alerting

Attach an Apify Schedule to run the actor daily or hourly against a fixed subreddit or a keyword list in `keywords`, with `includeReplies` on. Diff each run's `upvotes` and `replyCount` per `commentId` against the previous run's values for the same comment, and alert when `engagementScore` crosses a threshold you define — a sudden score jump on a specific comment is a stronger signal than the raw thread's total comment count.

#### 🎯 Strategy 3: Bulk dataset build

Feed a large `startUrls` list of post or subreddit URLs, or a single subreddit URL with a high `maxPosts`, and let the run push every accepted comment, reply, and post row live to one dataset. Export the finished dataset to CSV or load it via the Apify API into a database. The actor has no documented run-level concurrency setting of its own — posts within a single run are processed one after another — so size `maxPosts`, `maxComments`, and `maxRepliesPerComment` to the depth you actually need. One real cap worth planning around: expanding collapsed "load more comments" placeholders is bounded to 25 rounds of up to 100 comment IDs each per post, so an exceptionally deep or wide thread may not fully expand even with `maxComments` and `maxRepliesPerComment` both set high.

#### Strategy comparison at a glance

| Strategy | Best for | Run pattern | Output format |
| --- | --- | --- | --- |
| Real-time enrichment | Support tickets or CRM records needing thread context | Triggered, single post URL, small `maxComments` | Live dataset row → written back to source record |
| Scheduled monitoring | Brand and competitive tracking over time | Apify Schedule, recurring, `includeReplies` on | Dataset diffed run-over-run on named fields |
| Bulk dataset build | Research cohorts, training/RAG datasets | One run, large `startUrls` or `maxPosts` | Full dataset exported to CSV/database |

### 🌴 Related Reddit Scrapers & Tools

Reddit Comment Scraper Plus is the only Reddit actor in the Scrapio catalog. For social data on other platforms:

| Scraper | What it extracts |
| --- | --- |
| Facebook Page Posts & Comments Scraper (Scrapio) | Posts, comments, and replies from Facebook Pages |
| Twitter Profile & Tweets Scraper (Scrapio) | Tweets and profile data from public X/Twitter accounts |
| TikTok Trending Scraper With Trend Insights (Scrapio) | Trending TikTok posts and engagement metrics |
| YouTube Transcript Scraper With AI Enrichment (Scrapio) | Video transcripts with optional AI enrichment |
| Instagram Hashtag Scraper Posts, Likes and Comments (Scrapio) | Instagram posts and comments by hashtag |

### How to integrate Reddit Comment Scraper Plus with your stack

Reddit Comment Scraper Plus works with any language or tool that can make an HTTP request through the Apify API — you don't need to write Reddit-specific scraping code yourself.

#### Python

```python
from apify_client import ApifyClient
import csv

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("reddit-comment-scraper-plus").call(run_input={
    "startUrls": ["https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/"],
    "sortOrder": "top",
    "maxComments": 100,
    "includeReplies": True,
    "maxRepliesPerComment": 20,
})

rows = []
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item.get("type") in ("comment", "reply"):
        rows.append({
            "type": item["type"],
            "author": item["author"],
            "text": item["contentText"][:120],
            "upvotes": item["upvotes"],
        })

with open("reddit_comments.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["type", "author", "text", "upvotes"])
    writer.writeheader()
    writer.writerows(rows)
```

#### Node.js

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

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

const run = await client.actor('reddit-comment-scraper-plus').call({
  startUrls: ['https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/'],
  sortOrder: 'top',
  maxComments: 100,
  includeReplies: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
const comments = items.filter((i) => i.type === 'comment' || i.type === 'reply');
console.table(comments.map((c) => ({
  type: c.type,
  author: c.author,
  upvotes: c.upvotes,
})));
```

#### Async and scheduled pipelines

For fire-and-forget large jobs, call the actor via `client.actor(...).start()` instead of `.call()` and poll the run status, or read the dataset once the run reaches `SUCCEEDED`. Attach an Apify Schedule for a recurring cadence, or configure a platform-level Apify webhook on run events (e.g. `ACTOR.RUN.SUCCEEDED`) to trigger downstream processing — the actor itself doesn't call any webhook or notification API; it only pushes dataset rows and log lines during the run.

### 🎯 Who Needs Reddit Comment Scraper Plus? (Use Cases & Industries)

#### 🏢 Community managers and brand teams

A community manager watching a product launch subreddit sets `keywords` to the product name and `excludeAutoMod`/`excludeDeleted` to true, then reads `contentText` and `upvotes` on the comments that clear `minScore` to build a daily sentiment digest — without exporting anything manually from Reddit's own site.

#### 📊 Data and AI teams

A team building a RAG index over public product discussions ingests `contentText` from comment and reply rows, using `parentId` and `postId` to keep each reply attached to its parent comment and source post as one retrievable context unit.

#### 📱 Competitive intelligence analysts

An analyst tracking a competitor's mentions runs the actor on a schedule against a relevant subreddit with `keywords` set to the competitor's name, watching `engagementScore` and `replyCount` to see which threads are actually gaining traction versus getting posted and ignored.

#### 🔬 Researchers

An academic studying public discourse on a specific subreddit collects comment threads (`contentText`, `depth`, `parentId`) for discourse-analysis or content-moderation research, scoped to what that subreddit's own comment listing already shows a logged-out visitor.

#### 🎥 Product and SaaS teams

A team building a Reddit-monitoring product ingests `subreddit`, `postId`, and `engagementScore` across many runs to power a customer-facing trend dashboard, rather than building and maintaining their own Reddit API client in-house.

### Is it legal to scrape Reddit?

Scraping publicly accessible web data is broadly permitted in the United States — the Ninth Circuit's ruling in *hiQ Labs, Inc. v. LinkedIn Corp.* (9th Cir. 2019) held that accessing data a website makes publicly visible does not violate the Computer Fraud and Abuse Act. That precedent concerns U.S. federal computer-crime law specifically; it does not settle every jurisdiction or every legal theory a platform might raise.

Scraping Reddit may still violate Reddit's own Terms of Service, which is a separate, civil matter between you and Reddit — not a criminal one — and is a risk you take on directly, not one this actor can absorb for you. Comment and reply rows carry identifiable data about the people who wrote them — `author`, `authorFullname`, and `userUrl` — which is personal data under data-protection frameworks even when the username is pseudonymous. If you collect and store that data, you take on data-protection obligations — GDPR in the EU/UK, CCPA in California, and equivalents elsewhere — for that portion of the output.

Reddit Comment Scraper Plus returns only publicly accessible data. What you do with that data is your responsibility — consult legal counsel for commercial applications involving personal data.

### ❓ Frequently asked questions

#### Does Reddit Comment Scraper Plus work without a Reddit account?

Yes. The actor negotiates its own anonymous OAuth bearer token on every run using Reddit's "installed\_client" device grant; no Reddit account, cookies, or user-supplied login credentials are used anywhere in the code.

#### How does Reddit Comment Scraper Plus handle Reddit's anti-scraping measures?

It requests through Reddit's OAuth API host with a real Chrome 131 TLS fingerprint (via `curl_cffi`, since Reddit's anonymous public `.json` endpoints return a blocking page from every IP the actor's author tested), refreshes its bearer token automatically on a 401 response, retries failed requests up to 4 times with an increasing delay between attempts, and honors your `proxyConfiguration` exactly on every request with no hidden fallback tier.

#### Can I run Reddit Comment Scraper Plus at scale without getting blocked?

`maxComments` accepts up to 10,000 and `maxRepliesPerComment` up to 5,000, but expanding Reddit's collapsed "load more comments" placeholders is bounded to 25 rounds of up to 100 comment IDs per round for a given post — an exceptionally deep or wide thread may not fully expand even with both limits set to their maximum. There is no documented uptime or success-rate figure for this or any Actor to cite.

#### How fresh is the data Reddit Comment Scraper Plus returns?

It's a live fetch on every run — the actor makes real-time requests to Reddit's API for each run; it does not read from a cache. `scrapedAt` on every row records the exact fetch time.

#### Which Reddit fields work best for AI training and RAG indexing?

`contentText` is the high-information text field for both comments and replies, populated on every row regardless of any other setting; `parentId` and `postId` let you reconstruct a full thread as one retrievable context unit. When `aiEnhancement` is turned on with a valid provider key, `sentiment`, `emotion`, `topics`, and `language` add structured, consistently-typed annotations for training data — without a key, those four fields plus `toxicityScore` return `null` on every row rather than a guessed value.

#### Does Reddit Comment Scraper Plus return personal data protected by GDPR/CCPA?

Yes, on every comment and reply row. `author`, `authorFullname`, and `userUrl` identify the individual who wrote the comment, even where the username is pseudonymous rather than a real name. The actor returns only what's publicly visible on Reddit; the lawful basis for storing and using that data for your specific purpose sits with you as the operator.

#### Does Reddit Comment Scraper Plus work with Claude, ChatGPT, and other AI agent tools?

Yes, as an HTTP endpoint callable by any agent framework through the Apify API — start a run, poll for completion, and read the dataset. Every response is typed JSON, ready to drop into an LLM context window without a parsing step.

#### How does Reddit Comment Scraper Plus compare to other Reddit scrapers?

Against harshmaur/reddit-scraper (posts, comments, user profiles, and communities, as observed on the Apify Store on 2026-07-26): that actor documents 140+ fields across four entity types, keyword search across all of Reddit, and MCP-native AI-agent integration, none of which this actor offers; this actor adds comment-level filtering (keywords, score, date, deleted/AutoMod exclusion, OP-only) and optional multi-provider AI enrichment that its listing does not document. Against betterdevsscrape/reddit-scraper (posts, comments, communities, and users, as observed on the Apify Store on 2026-07-26): that actor claims fetching collapsed/hidden comments beyond Reddit's initial ~500 and date-window pagination past Reddit's ~1,000-post cap, both genuinely useful for post-heavy workloads; this actor is comment-and-reply focused and doesn't return a standalone post-listing entity beyond the posts it discovers to scrape comments from. Against crawlerbros/reddit-comment-scraper (comments-only via Playwright browser automation, as observed on the Apify Store on 2026-07-26): that actor scrapes `old.reddit.com` through a real browser rather than the OAuth API this actor uses, which is a heavier but sometimes more resilient access path; this actor adds the post record, reply-specific filtering, subreddit/user auto-discovery, and AI enrichment that its comments-only scope doesn't cover.

### ℹ️ Disclaimer

Reddit Comment Scraper Plus extracts only publicly available data from Reddit. This tool is intended for lawful use cases only. Users are responsible for complying with Reddit's Terms of Service and applicable data protection laws in their jurisdiction.

# Actor input Schema

## `startUrls` (type: `array`):

Paste one or more Reddit URLs. Supported:
• Post URL → scrapes its comments (e.g. https://www.reddit.com/r/ChatGPT/comments/1epeshq/these\_are\_all\_ai/)
• Subreddit URL → auto-discovers the latest posts and scrapes each (e.g. https://www.reddit.com/r/ChatGPT/)
• User URL → scrapes that user's recent comments (e.g. https://www.reddit.com/user/spez/)
Bare post IDs and redd.it short links are also accepted.

## `sortOrder` (type: `string`):

How Reddit sorts the comment thread before scraping. 'Best' (confidence) surfaces the highest-quality comments first; 'Top' the highest-scored; 'New' the newest. Default: Top.

## `maxComments` (type: `integer`):

Maximum number of TOP-LEVEL comments to collect from each post. Replies are additional and capped separately by 'Max Replies per Comment'. Set 0 for unlimited. Example: maxComments=10 + maxRepliesPerComment=3 → up to 10 comments plus up to 3 replies each. Default: 50.

## `includeReplies` (type: `boolean`):

Collect nested replies (child comments) in addition to top-level comments. Reply rows are labelled type='reply', isReply=true, linked to their parent via parentId, and mirrored to a per-run 'replies-<runId>' dataset. Default: true.

## `maxRepliesPerComment` (type: `integer`):

Maximum reply rows (all nesting levels) to collect under each top-level comment. Set 0 for unlimited. Only applies when 'Include Replies' is on. Default: 10.

## `includePost` (type: `boolean`):

Emit one row (type='post') per post with the submission details: title, selftext, score, upvote ratio, number of comments, author and creation date. Default: true.

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

When a subreddit or user URL is provided, how many posts to auto-discover and scrape. Ignored for direct post URLs. Default: 10.

## `keywords` (type: `array`):

Only keep comments whose text contains at least one of these words/phrases (case-insensitive). Leave empty to keep all. Does not filter out the post record.

## `excludeKeywords` (type: `array`):

Drop comments whose text contains any of these words/phrases (case-insensitive).

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

Only keep comments with at least this many upvotes (score). Default: 0 (keep all). Note: scores can be negative on Reddit.

## `oldestDate` (type: `string`):

Only keep comments created on or after this date. Accepts an absolute date (YYYY-MM-DD) or a relative value like '7 days', '3 months'. Leave empty for no date filter.

## `excludeDeleted` (type: `boolean`):

Skip comments whose author or body is \[deleted] or \[removed]. Default: false.

## `excludeAutoMod` (type: `boolean`):

Skip comments posted by AutoModerator (bot stickies/rules). Default: false.

## `onlyOP` (type: `boolean`):

Keep only comments written by the post's original poster (is\_submitter=true). Default: false.

## `aiEnhancement` (type: `boolean`):

Analyze each comment's text with an LLM to add sentiment, emotion, topics, language and a toxicity score. Requires an API key below (or the matching provider env var). Adds cost and runtime. Default: false.

## `aiModel` (type: `string`):

Provider auto-detected from the name: claude-*=Anthropic, gpt-*/o1/o3=OpenAI, gemini-*=Google, grok-*=xAI, deepseek-*=DeepSeek, sonar*=Perplexity, mistral-\*=Mistral. Cheaper mini/flash/haiku/lite models are recommended for classification.

## `aiApiKey` (type: `string`):

API key for the selected provider. Optional if the matching env var is set on the Actor (ANTHROPIC\_API\_KEY / OPENAI\_API\_KEY / GEMINI\_API\_KEY / XAI\_API\_KEY / DEEPSEEK\_API\_KEY / PERPLEXITY\_API\_KEY / MISTRAL\_API\_KEY).

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

Reddit rate-limits and blocks datacenter IPs on its public JSON endpoints, so RESIDENTIAL proxy is strongly recommended for reliable results. Your selection here is honored exactly — no hidden fallback. Leave proxy off to connect directly (may be blocked by Reddit).

## Actor input object example

```json
{
  "startUrls": [
    "https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/"
  ],
  "sortOrder": "top",
  "maxComments": 50,
  "includeReplies": true,
  "maxRepliesPerComment": 10,
  "includePost": true,
  "maxPosts": 10,
  "keywords": [],
  "excludeKeywords": [],
  "minScore": 0,
  "excludeDeleted": false,
  "excludeAutoMod": false,
  "onlyOP": false,
  "aiEnhancement": false,
  "aiModel": "claude-haiku-4-5",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "startUrls": [
        "https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/"
    ],
    "keywords": [],
    "excludeKeywords": [],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapio/reddit-comments-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 = {
    "startUrls": ["https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/"],
    "keywords": [],
    "excludeKeywords": [],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapio/reddit-comments-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    "https://www.reddit.com/r/ChatGPT/comments/1epeshq/these_are_all_ai/"
  ],
  "keywords": [],
  "excludeKeywords": [],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call scrapio/reddit-comments-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=scrapio/reddit-comments-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/vH73ExGY0bQuwmUmW/builds/ciJimFlW4SF3OJXNr/openapi.json
