# Reddit Comments Scraper (`apt_marble/reddit-comments-scraper`) Actor

Export every comment from any Reddit thread as analysis-ready rows: text, author, score, reply depth and parent post on each one — including replies hidden behind "load more comments". Point it at post links or whole subreddits. No Reddit account or login needed. Pay only for the rows you keep.

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

## Pricing

from $0.35 / 1,000 comment or post rows

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/platform/actors/running/actors-in-store#pay-per-event

## 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 Comments Scraper

Turn any Reddit discussion into a clean, analysable dataset. Give it post links
or whole subreddits and it returns one row per comment — the text, the author,
the score, how deep in the reply chain it sits, and the parent post it belongs
to. It also opens the branches Reddit hides behind "load more comments", so you
get the parts of the conversation a normal copy-paste never reaches. No Reddit
account, no login, nothing to install.

### What you can do with it

- **Voice-of-customer research.** Pull every comment on threads about your
  product, a competitor, or a category, and read what people say unprompted.
- **Sentiment and topic analysis at scale.** Feed thousands of clean comment
  rows into your own model or spreadsheet instead of scraping screenshots.
- **Community and moderation reporting.** Track discussion volume, reply depth
  and the most-upvoted answers across a set of subreddits, on a schedule.
- **Q\&A and support mining.** Harvest the highest-scoring answers to recurring
  questions ("best X for Y") to build FAQs, docs or training data.
- **Influencer and advocate discovery.** See who consistently writes the
  top-scoring comments in the communities you care about.
- **Content research.** Take the top 10 hot posts in a subreddit and collect
  every reply to see which angles resonate before you write.

### What you get

One record per comment. Abridged real output:

```json
{
  "id": "oyzxp83",
  "fullId": "t1_oyzxp83",
  "type": "comment",
  "body": "Ignoring dental care.\n\nPeople in their 20s can skip cleanings and think, \"My teeth are fine.\"…",
  "url": "https://www.reddit.com/r/AskReddit/comments/1v32t70/people_who_are_40_what_is_a_silent_killer_habit/oyzxp83/",
  "author": "lonelygayPhD",
  "authorFlair": null,
  "score": 25296,
  "scoreHidden": false,
  "controversiality": 0,
  "totalAwards": 0,
  "createdAt": "2026-07-22T02:20:36.000Z",
  "editedAt": null,
  "subreddit": "AskReddit",
  "parentId": "t3_1v32t70",
  "isTopLevel": true,
  "isSubmitter": false,
  "depth": 0,
  "replyCount": 19,
  "stickied": false,
  "collapsed": false,
  "postId": "1v32t70",
  "postTitle": "People who are 40+, what is a \"silent killer\" habit that people in their 20s think is completely harmless…",
  "postUrl": "https://www.reddit.com/r/AskReddit/comments/1v32t70/people_who_are_40_what_is_a_silent_killer_habit/",
  "postAuthor": "The-Irumporai",
  "postScore": 15757,
  "postNumComments": 6251,
  "postCreatedAt": "2026-07-22T02:17:17.000Z",
  "threadSort": "top",
  "threadPosition": 1,
  "fromExpansion": false,
  "scrapedAt": "2026-07-28T20:35:43.112Z"
}
```

Every row stands on its own — the parent post's title, link, author and score
are repeated on each comment, so you can drop the dataset straight into a
spreadsheet, a database or a model without joining anything back together.

### Input reference

| Field | Type | Default | What it does |
| --- | --- | --- | --- |
| `postUrls` | list of strings | — | Threads to scrape. Full post links, share links or bare post ids (`1v32t70`). |
| `subreddits` | list of strings | empty | Optional. Take the latest posts from these communities and scrape their comments. Accepts `python`, `r/python` or a community link. |
| `postsPerSubreddit` | integer | `10` | How many posts to take from each community (max 200). Pinned announcements are skipped. |
| `subredditSort` | select | `hot` | Which posts to take: `hot`, `new`, `top`, `rising` or `controversial`. |
| `sort` | select | `top` | Order the thread is read in: `top`, `new`, `best`, `controversial`, `old` or `qa`. Decides which comments you get first when you cap the number. |
| `maxCommentsPerPost` | integer | `200` | Stop after this many comments in one thread (max 5000). Your main cost control. |
| `maxDepth` | integer | `10` | How deep to follow reply chains. `0` keeps only top-level comments, `1` adds their direct replies (max 20). |
| `expandAllComments` | boolean | `true` | Open the collapsed "load more comments" branches. Turn off for a faster, cheaper skim of the visible thread. |
| `maxExpansionRequestsPerPost` | integer | `20` | How hard to dig into one thread. Each extra round uncovers more of the hidden replies (max 200). |
| `minScore` | integer | empty | Keep only comments with at least this many upvotes. |
| `includeOpComments` | boolean | `true` | Keep comments written by the person who submitted the post. |
| `skipDeleted` | boolean | `true` | Drop the empty `[deleted]` and `[removed]` placeholders. |
| `includePostRecord` | boolean | `false` | Add one extra row per thread holding the post itself (title, body, score, media, thread statistics). |
| `maxConcurrency` | integer | `3` | How many posts to work on at the same time (max 10). |
| `country` | select | `us` | Which country's view of Reddit the run should use. |

You can use `postUrls`, `subreddits`, or both in the same run.

### Output fields

**Comment rows**

| Field | Type | Description |
| --- | --- | --- |
| `id` / `fullId` | string | Reddit's comment id (`oyzxp83`) and full name (`t1_oyzxp83`). |
| `type` | string | Always `comment` for comment rows. |
| `body` / `bodyHtml` | string | The comment text as plain text, and the same text with Reddit's formatting and links preserved. |
| `url` / `permalink` | string | Direct link to the comment. |
| `author` / `authorId` / `authorFlair` | string | Who wrote it, their account id and their flair in that community. |
| `score` / `scoreHidden` | number / boolean | Net upvotes, and whether the community hides scores on new comments. |
| `controversiality` / `totalAwards` | number | Reddit's controversy flag and the number of awards received. |
| `createdAt` / `editedAt` | date | When it was posted and, if applicable, edited. |
| `subreddit` / `subredditId` | string | Community it was posted in. |
| `parentId` / `isTopLevel` | string / boolean | What it replies to, and whether that is the post itself. |
| `depth` / `replyCount` | number | How deep in the reply chain it sits, and how many direct replies were captured. `replyCount` is empty on rows recovered from a hidden branch, because Reddit does not report a reply count for those. |
| `isSubmitter` | boolean | True when the comment's author also submitted the post. |
| `distinguished` / `stickied` / `locked` / `collapsed` | string / boolean | Moderator and Reddit display flags. |
| `postId` / `postTitle` / `postUrl` | string | The parent post, repeated on every row so each one stands alone. |
| `postAuthor` / `postScore` / `postNumComments` / `postCreatedAt` / `postFlair` | mixed | Parent-post context for filtering and grouping. |
| `threadSort` / `threadPosition` | string / number | The order the thread was read in, and this comment's position within it. |
| `fromExpansion` | boolean | True when the comment was recovered from a hidden "load more" branch. |
| `scrapedAt` | date | When this run read the thread. |

**Post rows** (only when `includePostRecord` is on) carry the full post —
`title`, `body`, `linkUrl`, `domain`, `score`, `upvoteRatio`, `numComments`,
`flair`, `over18`, `spoiler`, `media` (images, galleries, video with its
streaming variants), plus a summary of how the thread went: `commentsScraped`,
`commentsReportedByReddit`, `expansionRequests` (how many extra digging rounds
were spent on it), `expandableStubs`, `continuationStubs` and
`expansionTruncated`.

### Pricing

Pay per event — you pay for results, not for run time.

- **Comment or post row (`apify-default-dataset-item`) — $0.0003 each ($0.30
  per 1,000).** Charged once for every row saved: each comment, and each post
  row if you turned that on.
- **Full thread expansion (`full-thread-expansion`) — $0.004.** Charged once per
  post whose hidden "load more" branches were actually opened and produced extra
  comments. Threads with nothing hidden, and runs with `expandAllComments`
  switched off, never trigger it.

So a 500-comment thread is about $0.15 plus $0.004 for the expansion, and a
10,000-comment pull is about $3.00. If you set a budget limit, the run stops
cleanly at the limit instead of overshooting it.

### Limits and what this actor cannot do

- **Reddit itself caps a community feed at roughly 1,000 posts.** When you seed
  threads from a subreddit, that is the ceiling on how many posts one community
  can hand over in a run, no matter how high you set `postsPerSubreddit`. Get
  more by splitting across sort orders or by feeding post links directly.
- **Very large threads are sampled, not exhausted.** A thread with thousands of
  comments is read as far as your caps allow; `maxCommentsPerPost` and
  `maxExpansionRequestsPerPost` decide how far it digs. When branches are still
  hidden at the end, the run says so and the post row's `expansionTruncated`
  flag is set.
- **"Continue this thread" branches are reported, not followed.** Once a reply
  chain gets very deep, Reddit stops showing it inline and offers a "continue
  this thread" link instead; that stretch of conversation is only reachable by
  scraping the sub-thread as a target of its own. The actor counts how many
  such branches it saw (`continuationStubs`) instead of pretending they were
  read.
- **Deleted and removed comments are gone at Reddit's end.** Only the
  `[deleted]` / `[removed]` placeholder survives; the original text is not
  recoverable by anyone. Keep them with `skipDeleted: false` if you want the
  gaps in your data.
- **Private, banned and unavailable communities return nothing.** They are
  reported and skipped; one bad target never fails the whole run. Members-only
  content is out of reach. Quarantined communities have not been tested.
- **No moderator-only data.** Mod logs, removal reasons, reports and moderator
  lists are not part of what Reddit shows the public, so they are not in the
  output.
- **No live viewer counts.** "Users here now" is not available, and post view
  counts always come back empty. Judge activity from comment volume and
  timestamps instead.
- **Scores can be hidden.** Communities may hide comment scores for the first
  hours of a thread; those rows carry `scoreHidden: true` and a placeholder
  score.
- **Very heavy runs are paced by Reddit itself.** Large jobs slow down rather
  than fail; keep `maxConcurrency` moderate if you are scraping hundreds of
  threads in one go.

### FAQ

**Do I need a Reddit account?**
No. You do not need a Reddit account, a login, or any credentials — just enter
what you want and run it.

**How fast is it?**
Fast. Comments arrive in large batches rather than one at a time, and several
posts are worked on in parallel. In testing, the first 300 comments of a
6,000-comment thread took about five seconds, and small threads finish in well
under a second each.

**What is the difference between `maxCommentsPerPost` and `maxDepth`?**
`maxCommentsPerPost` limits how many comments you collect per thread;
`maxDepth` limits how far down reply chains you follow. Set `maxDepth: 0` for a
clean list of top-level answers only — ideal for "ask" style threads.

**Can I run it on a schedule?**
Yes. A common pattern is a daily run over a handful of subreddits with
`subredditSort: new`, which keeps a rolling archive of fresh discussion. Each
run is independent and always returns the current state of the threads it reads.

**Why did I get fewer comments than the post's comment count?**
Reddit's headline count includes deleted placeholders and branches it will not
hand over all at once. Raise `maxCommentsPerPost` and
`maxExpansionRequestsPerPost`, set `maxDepth` higher, and turn `skipDeleted`
off if you want the placeholders too. The post row's `commentsScraped` versus
`commentsReportedByReddit` shows exactly how much of a thread you captured.

**Can I scrape one branch of a discussion rather than a whole post?**
Paste the post link and use `minScore` or `maxDepth` to narrow it down; every
row carries `parentId`, so you can rebuild any branch of the conversation
yourself.

**What can I export it as?**
Anything the platform offers — JSON, CSV, Excel or XML — or read the dataset
straight into your own tooling.

# Actor input Schema

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

Threads to scrape. Paste full post links, share links, or bare post ids (for example 1v32t70). Leave empty if you would rather pick whole subreddits below.

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

Optional. Instead of (or as well as) individual links, take the latest posts from these communities and scrape their comments. Accepts python, r/python or a full community link.

## `postsPerSubreddit` (type: `integer`):

How many posts to take from each subreddit before scraping their comments.

## `subredditSort` (type: `string`):

Which posts to take from each subreddit: the hot front page, the newest, the all-time top, rising, or the most controversial.

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

The order Reddit returns the thread in. This decides which comments you get first when you cap the number per post.

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

Stop after this many comments in a single thread. Big threads can hold thousands, so this is your main cost control.

## `maxDepth` (type: `integer`):

How deep to follow reply chains. 0 keeps only top-level comments, 1 adds their direct replies, and so on.

## `expandAllComments` (type: `boolean`):

Follow the collapsed branches Reddit hides behind "load more comments" and pull those replies in too. Turn off for a faster, cheaper skim of the visible thread.

## `maxExpansionRequestsPerPost` (type: `integer`):

Upper limit on how hard the scraper digs into one thread. Each round uncovers up to 100 more hidden comments.

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

Optional. Keep only comments with at least this many upvotes. Leave empty to keep everything.

## `includeOpComments` (type: `boolean`):

Keep comments written by the person who submitted the post. Turn off to see only what other people said.

## `skipDeleted` (type: `boolean`):

Drop the empty \[deleted] and \[removed] placeholders so your dataset holds real text only.

## `includePostRecord` (type: `boolean`):

Add one extra row per thread holding the post itself (title, body, score, media) alongside its comments.

## `maxConcurrency` (type: `integer`):

How many posts to work on at the same time. Higher finishes sooner; lower is gentler.

## `country` (type: `string`):

Which country's view of Reddit to use. Reddit content is the same almost everywhere, so the default suits nearly every run.

## Actor input object example

```json
{
  "postUrls": [
    "https://www.reddit.com/r/AskReddit/comments/1v32t70/people_who_are_40_what_is_a_silent_killer_habit/"
  ],
  "subreddits": [],
  "postsPerSubreddit": 10,
  "subredditSort": "hot",
  "sort": "top",
  "maxCommentsPerPost": 200,
  "maxDepth": 10,
  "expandAllComments": true,
  "maxExpansionRequestsPerPost": 20,
  "includeOpComments": true,
  "skipDeleted": true,
  "includePostRecord": false,
  "maxConcurrency": 3,
  "country": "us"
}
```

# Actor output Schema

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

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

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

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "postUrls": [
        "https://www.reddit.com/r/AskReddit/comments/1v32t70/people_who_are_40_what_is_a_silent_killer_habit/"
    ],
    "subreddits": [],
    "postsPerSubreddit": 10,
    "subredditSort": "hot",
    "sort": "top",
    "maxCommentsPerPost": 200,
    "maxDepth": 10,
    "maxExpansionRequestsPerPost": 20,
    "maxConcurrency": 3,
    "country": "us"
};

// Run the Actor and wait for it to finish
const run = await client.actor("apt_marble/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 = {
    "postUrls": ["https://www.reddit.com/r/AskReddit/comments/1v32t70/people_who_are_40_what_is_a_silent_killer_habit/"],
    "subreddits": [],
    "postsPerSubreddit": 10,
    "subredditSort": "hot",
    "sort": "top",
    "maxCommentsPerPost": 200,
    "maxDepth": 10,
    "maxExpansionRequestsPerPost": 20,
    "maxConcurrency": 3,
    "country": "us",
}

# Run the Actor and wait for it to finish
run = client.actor("apt_marble/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 '{
  "postUrls": [
    "https://www.reddit.com/r/AskReddit/comments/1v32t70/people_who_are_40_what_is_a_silent_killer_habit/"
  ],
  "subreddits": [],
  "postsPerSubreddit": 10,
  "subredditSort": "hot",
  "sort": "top",
  "maxCommentsPerPost": 200,
  "maxDepth": 10,
  "maxExpansionRequestsPerPost": 20,
  "maxConcurrency": 3,
  "country": "us"
}' |
apify call apt_marble/reddit-comments-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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