# Reddit Post Comment Thread & Filter Extractor (`nimbryxo-studio/reddit-post-comment-thread-and-filter-extractor`) Actor

Pulls every comment on one or more Reddit posts, with the full thread depth, parent links and awards, and lets you keep only the comments that match a score, author, keyword or length rule.

- **URL**: https://apify.com/nimbryxo-studio/reddit-post-comment-thread-and-filter-extractor.md
- **Developed by:** [Nimbryxo-studio](https://apify.com/nimbryxo-studio) (community)
- **Categories:** Social media, Automation, Developer tools
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Reddit Post Comment Thread & Filter Extractor

Paste in one or more Reddit post links and get every comment on that thread as a flat dataset row, in the order the thread tree expands collapsed replies. A companion record with the post's own stats is added for each URL, and a set of optional filters lets you narrow a huge thread down to only the comments worth reading before you export anything.

### What this actor does

- Loads each Reddit post you give it and opens collapsed "load more" and "continue this thread" sections so deep replies are not left out.
- Returns every comment with its author, text, score, nesting depth, and the ID of the comment it replies to, so you can rebuild the thread tree.
- Captures awards, gilding, controversiality, distinguished (mod/admin) status and user flair for each comment, when Reddit shows them.
- Applies any score, depth, author, keyword or word-count rule you set, dropping non-matching comments before they reach the dataset.
- Omits any field Reddit did not provide for a given comment or post, instead of writing a blank or null value.

### Output per record

Each run produces one post-metadata record per URL and one record per comment that passed your filters.

#### Post metadata record

| Field | Description |
| --- | --- |
| recordType | Always `post` for this record type |
| post_id | Reddit's post ID |
| post_name | Fullname in Reddit's `t3_<id>` format |
| title | Post title |
| author | Username of the poster |
| author_fullname | Poster's Reddit fullname ID |
| subreddit | Subreddit name without the `r/` prefix |
| subreddit_prefixed | Subreddit name with `r/` prefix |
| domain | Link domain for link posts (e.g. `self.programming`) |
| score | Post score (upvotes minus downvotes) |
| num_comments | Total comment count reported by Reddit |
| permalink | Full URL of the post |
| url | Same as permalink |
| selftext | Post body text, for text posts |
| selftext_html | Post body as HTML, for text posts |
| link_flair | Post flair text, if the subreddit uses flairs |
| is_self | True for text posts |
| is_stickied | True if the post is pinned |
| is_nsfw | True if marked over-18 |
| is_spoiler | True if marked as a spoiler |
| is_original_content | True if flagged as OC |
| is_locked | True if comments are locked |
| is_archived | True if the post is archived |
| more_comments_count | Count of "load more" links Reddit still showed after expansion |
| comment_sort | Comment sort order active on the page (e.g. `best`, `top`) |
| created_utc | Post creation time as a Unix timestamp |
| created_at | Post creation time as an ISO 8601 datetime |

#### Comment record

| Field | Description |
| --- | --- |
| recordType | Always `comment` for this record type |
| comment_id | Reddit's comment ID |
| comment_name | Fullname in Reddit's `t1_<id>` format |
| author | Username of the commenter, or `[deleted]` |
| author_fullname | Commenter's Reddit fullname ID |
| text | Comment body text |
| body_html | Comment body as HTML |
| score | Comment score (upvotes minus downvotes) |
| permalink | Direct link to the comment |
| post_url | URL of the post the comment belongs to |
| depth | Nesting level in the thread (0 = top-level reply to the post) |
| parent_comment_id | ID of the comment this one replies to, when it is not top-level |
| replies_count | Number of direct replies visible under this comment |
| subreddit | Subreddit the post belongs to |
| subreddit_prefixed | Subreddit with the `r/` prefix |
| is_op | True if the commenter is the post's original author |
| is_edited | True if the comment was edited after posting |
| edited_at | Edit timestamp, when Reddit discloses one |
| is_stickied | True if the comment is pinned by a moderator |
| is_collapsed | True if the comment was shown collapsed on the page |
| is_deleted | True if the comment body or author shows as deleted/removed |
| is_automod | True if posted by AutoModerator |
| is_likely_bot | True if the author name matches a common bot-naming pattern |
| comment_age_seconds | Seconds between posting and the time the comment was scraped |
| distinguished | Moderator/admin distinguish tag, when present |
| controversiality | Reddit's controversiality flag for the comment |
| user_flair | Commenter's subreddit flair text |
| word_count | Whitespace-separated word count of the comment body |
| body_quote_count | Number of quote blocks in the comment body |
| body_code_count | Number of code blocks in the comment body |
| body_link_count | Number of links in the comment body |
| awards | List of award objects (`name`, `icon`) the comment received |
| awards_count | Total number of awards received |
| gilded_count | Number of times the comment was gilded |
| created_utc | Comment creation time as a Unix timestamp |
| created_at | Comment creation time as an ISO 8601 datetime |

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `postUrls` | array | – | Reddit post URLs to scrape comments from (required) |
| `maxComments` | integer | `100` | Maximum number of comments to collect per post, 1-10000 |
| `expandThreads` | boolean | `true` | Click "load more" and "continue this thread" to reveal collapsed replies |
| `minScore` | integer | – | Drop comments scoring below this number |
| `maxDepth` | integer | – | Drop comments nested deeper than this (0 keeps only top-level replies) |
| `excludeDeleted` | boolean | `false` | Drop comments where the author is `[deleted]` or the body is `[removed]` |
| `authorFilter` | string | – | Keep only comments by an author whose name contains this text (case-insensitive) |
| `keywordFilter` | string | – | Keep only comments whose body contains this text; prefix with `!` to drop matches instead |
| `minWordCount` | integer | – | Drop comments shorter than this many words |
| `maxWordCount` | integer | – | Drop comments longer than this many words |

#### Example: default scrape of one thread

```json
{
  "postUrls": ["https://www.reddit.com/r/programming/comments/1s9jkzi/announcement_temporary_llm_content_ban/"],
  "maxComments": 200
}
```

#### Example: only substantial, positively-scored replies

```json
{
  "postUrls": ["https://www.reddit.com/r/AskScience/comments/1abc123/why_is_the_sky_blue/"],
  "minScore": 5,
  "minWordCount": 15,
  "excludeDeleted": true
}
```

#### Example: top-level comments from one author across two posts

```json
{
  "postUrls": [
    "https://www.reddit.com/r/technology/comments/1xyz789/post_one/",
    "https://old.reddit.com/r/technology/comments/1xyz790/post_two/"
  ],
  "maxDepth": 0,
  "authorFilter": "throwaway",
  "maxComments": 500
}
```

### Use cases

- **Sentiment and discourse research**: pull every reply to a thread to study how a community reacted to an announcement or news post.
- **Moderation audits**: use `excludeDeleted` and `authorFilter` to review what a specific user posted before their comments were removed.
- **Dataset building**: filter by `minWordCount` to collect substantive comments for training or evaluating language models.
- **Brand and product monitoring**: track replies mentioning a product name with `keywordFilter` across multiple relevant threads.
- **Thread archiving**: capture a full comment tree, including depth and parent IDs, before a thread is locked or archived.

### FAQ

**Does this need a Reddit account or login?**
No. It reads the public comment pages the same way a logged-out visitor would, so only posts and comments visible without logging in can be collected.

**Why are some comments missing from my results?**
Deleted or removed comments, comments beyond `maxComments`, and comments beneath unexpanded "load more" links (when `expandThreads` is off) will not appear. Your score, depth, author, keyword or word-count filters can also remove comments that were successfully scraped.

**What does `maxDepth: 0` give me?**
Only comments posted directly on the post itself, with no replies-to-replies.

**How is `keywordFilter` different from a normal search?**
It is a plain, case-insensitive substring match against the comment body. Prefixing the value with `!` inverts it, so `!spam` keeps everything except comments mentioning "spam".

**Why is a field missing on some comment or post records?**
Fields Reddit does not expose for that record (for example `edited_at` on a comment that was never edited) are left out of the record instead of being written as null or empty.

**Can I scrape a subreddit's whole post list, not just comments?**
No, this actor only works from direct post URLs you supply; it does not crawl subreddit listings.

**Does `old.reddit.com` vs `www.reddit.com` in my input matter?**
No, either form works — `post_url` in the output is normalized to the `www.reddit.com` form regardless of which you paste in.

**Is this affiliated with Reddit?**
No. This is an independent tool that reads Reddit's public comment pages and is not operated by or affiliated with Reddit, Inc.

# Actor input Schema

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

List of Reddit post URLs to scrape comments from.

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

Max comments per post.

## `expandThreads` (type: `boolean`):

Auto-expand collapsed comment threads and 'load more' sections.

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

Drop comments with score below this number.

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

Drop comments deeper than N levels (0 = top-level only).

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

Drop comments where author is `[deleted]` or text is `[removed]`.

## `authorFilter` (type: `string`):

Only emit comments by this author (case-insensitive substring match).

## `keywordFilter` (type: `string`):

Only emit comments whose body contains this substring (case-insensitive). Prefix with `!` to invert (`!spam` drops comments mentioning spam).

## `minWordCount` (type: `integer`):

Drop one-liner comments. Counts whitespace-separated tokens in the body.

## `maxWordCount` (type: `integer`):

Drop walls of text — useful when surveying short reactions only.

## Actor input object example

```json
{
  "postUrls": [
    "https://www.reddit.com/r/programming/comments/1s9jkzi/announcement_temporary_llm_content_ban/"
  ],
  "maxComments": 100,
  "expandThreads": true,
  "excludeDeleted": false
}
```

# Actor output Schema

## `comments` (type: `string`):

Dataset containing all scraped comments and post metadata records.

# 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/programming/comments/1s9jkzi/announcement_temporary_llm_content_ban/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nimbryxo-studio/reddit-post-comment-thread-and-filter-extractor").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/programming/comments/1s9jkzi/announcement_temporary_llm_content_ban/"] }

# Run the Actor and wait for it to finish
run = client.actor("nimbryxo-studio/reddit-post-comment-thread-and-filter-extractor").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 '{
  "postUrls": [
    "https://www.reddit.com/r/programming/comments/1s9jkzi/announcement_temporary_llm_content_ban/"
  ]
}' |
apify call nimbryxo-studio/reddit-post-comment-thread-and-filter-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nimbryxo-studio/reddit-post-comment-thread-and-filter-extractor"
        }
    }
}
```

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/jVr3LV1QcMOvylkWf/builds/VdKWKblN35lCfRp8c/openapi.json
