# Reddit Scraper API: Posts & Comment Threads (`socialhz/reddit-search-scraper`) Actor

Search Reddit by keyword or subreddit — no login, no API key. Get post metadata plus full nested comment threads (up to 300/post). 5 sort orders, time filters, cursor paging. Pricing: posts $1.49/1K, comments $0.99/1K, $0.005/run. JSON/CSV export.

- **URL**: https://apify.com/socialhz/reddit-search-scraper.md
- **Developed by:** [Socialhz](https://apify.com/socialhz) (community)
- **Categories:** Social media, Lead generation, Marketing
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.49 / 1,000 post scrapeds

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?

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 Scraper API: Posts & Comment Threads

Search Reddit by keyword, restrict results to the communities you care about, and optionally pull each post's comment thread with reply nesting preserved.

Built for market research, lead generation, competitor monitoring and content analysis.

***

### What it does

- **Keyword search across Reddit** — 25 posts per page, with cursor-based paging
- **Subreddit scoping** — restrict to one or many communities
- **Five sort orders** — relevance, hot, top score, most recent, most commented
- **Time filtering** — hour through to all-time
- **Comment threads** — up to 300 comments per post, nested replies preserved, with depth and, where reported, the parent for every comment
- **Honest empty results** — a query that matches nothing returns nothing, rather than padding with irrelevant posts

### What it does not do

Stated plainly so there are no surprises after you have paid for a run.

| Not supported | Notes |
|---|---|
| Searching *inside* comments | Comments are retrieved per post, after that post has been found by a post search |
| Scraping a specific post by URL | Posts are reached through search only |
| User profiles or user history | Not available |
| Private, quarantined or deleted content | Returned as unavailable |
| Media file downloads | Image and video URLs are returned; files are not fetched |
| Live monitoring or streaming | Each run is a point-in-time snapshot. Use Apify Schedules for recurring runs |

***

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `query` | string | — | Keywords to search for. Optional if `subreddits` is set, but **one of the two is required** |
| `subreddits` | array | `[]` | Community names without the `r/` prefix, e.g. `["startups", "SaaS"]`. Empty searches all of Reddit |
| `sort` | enum | `relevance` | `relevance`, `hot`, `top`, `new`, `comments` |
| `timeFilter` | enum | `all` | `hour`, `day`, `week`, `month`, `year`, `all`. **Applies only to `top` and `comments` sort orders** — see Limits |
| `maxPosts` | integer | `100` | Upper bound on posts returned. Max `1000` |
| `includeComments` | boolean | `false` | Retrieve comment threads. Charged separately |
| `maxPostsToComment` | integer | `25` | How many of the returned posts get their comments retrieved. Max `500` |
| `maxCommentsPerPost` | integer | `100` | Comments per post, **including nested replies**. Max `300` |

#### Example input

```json
{
  "query": "project management software",
  "subreddits": ["startups", "SaaS"],
  "sort": "relevance",
  "timeFilter": "all",
  "maxPosts": 100,
  "includeComments": true,
  "maxPostsToComment": 25,
  "maxCommentsPerPost": 100
}
```

***

### Output

One record per post. Every record has the same shape — comment fields are always present, even when comments were not requested.

| Field | Type | Description |
|---|---|---|
| `id` | string | Reddit fullname, including the type prefix, e.g. `t3_1ps7lis` |
| `title` | string | Post title |
| `subreddit` | string | null | Community name, without `r/`. `null` when the community is not returned with the post |
| `subredditSubscribers` | number | null | Community size at time of retrieval |
| `author` | string | null | Username. `null` when the account is deleted |
| `score` | number | Net upvotes |
| `upvoteRatio` | number | null | Proportion of votes that are upvotes, `0`–`1` |
| `numComments` | number | Reddit's own comment count. **Includes deleted comments**, so it is usually higher than `commentsRetrieved` |
| `postedAt` | string | ISO 8601 UTC |
| `selfText` | string | null | Post body. `null` for link and media posts |
| `postType` | enum | `text`, `link`, `image`, `video` |
| `thumbnailUrl` | string | null | Preview image |
| `isNsfw` | boolean | Marked over-18 |
| `isSpoiler` | boolean | Marked spoiler |
| `url` | string | **The Reddit thread** — use this to reach the discussion |
| `contentUrl` | string | null | The outbound link for link and media posts. `null` for text posts |
| `comments` | array | Comment objects, flattened in thread order. Empty unless requested |
| `commentsRetrieved` | number | How many comments this record contains |
| `commentsRemaining` | boolean | `true` if further comments exist that were not retrieved |
| `commentsStatus` | enum | `retrieved`, `skipped_no_comments`, `skipped_limit`, `not_requested`, `unavailable` |

#### Comment object

| Field | Type | Description |
|---|---|---|
| `id` | string | Comment fullname, e.g. `t1_fl28mc9` |
| `author` | string | null | Username, `null` when deleted |
| `text` | string | Comment body |
| `score` | number | Net upvotes |
| `postedAt` | string | ISO 8601 UTC |
| `depth` | number | `0` is top level, `1` is a reply, `2` a reply to a reply, and so on |
| `parentId` | string | null | The post or comment this replies to. `null` when the source data does not include a parent reference |
| `replyCount` | number | Direct replies, including any not retrieved |

#### Example output

```json
{
  "id": "t3_1ps7lis",
  "title": "best project management software 2026 for small teams",
  "subreddit": "SaaS",
  "subredditSubscribers": 412883,
  "author": "Old_Mention_4851",
  "score": 17,
  "upvoteRatio": 0.89,
  "numComments": 52,
  "postedAt": "2025-12-21T14:20:48Z",
  "selfText": "i'm 29 and managing a small remote team at a startup...",
  "postType": "text",
  "thumbnailUrl": null,
  "isNsfw": false,
  "isSpoiler": false,
  "url": "https://www.reddit.com/r/SaaS/comments/1ps7lis/best_project_management_software/",
  "contentUrl": null,
  "comments": [
    {
      "id": "t1_n2k4xqa",
      "author": "YamNo178",
      "text": "Linear is solid but for small teams I'd go with Notion first.",
      "score": 3,
      "postedAt": "2025-12-21T16:02:11Z",
      "depth": 0,
      "parentId": "t3_1ps7lis",
      "replyCount": 2
    }
  ],
  "commentsRetrieved": 22,
  "commentsRemaining": true,
  "commentsStatus": "retrieved"
}
```

***

### Pricing

Charged per result, plus a small fixed fee when a run starts.

| Event | Price |
|---|---|
| Run start | $0.005 per run |
| Post | $1.49 per 1,000 posts |
| Comment | $0.99 per 1,000 comments |

#### Worked examples

**Spot check — 100 posts, no comments**
100 × $0.00149 + $0.005 = **$0.154**

**Research pull — 100 posts with comments**, with `maxPostsToComment` raised to 100 (≈50 comments each, ≈5,000 comments)
100 × $0.00149 + 5,000 × $0.00099 + $0.005 = **$5.10**

**Bulk — 1,000 posts, no comments**
1,000 × $0.00149 + $0.005 = **$1.50**

Set **Maximum cost per run** in the run options to cap spend. The Actor stops cleanly at that ceiling and returns everything collected and charged for up to that point.

***

### Limits

Worth reading before your first run.

**The time window is ignored on three of the five sort orders.** Reddit applies it only to `top` and `comments`. Choose `relevance`, `hot` or `new` and any time window other than `all` is dropped — the run log tells you when this happens.

**Large threads are not returned in full.** A post with 13,000 comments returns roughly 100 by default, or up to 300 with `maxCommentsPerPost` raised. `commentsRemaining` tells you when more exist.

**`numComments` will exceed `commentsRetrieved`.** Reddit's counter includes deleted and moderator-removed comments that no longer render. A post reporting 52 comments may legitimately return 22.

**Posts are retrieved in pages of 25.** Setting `maxPosts` to 30 makes two page requests.

**One post per record.** Comments are nested inside their post rather than being separate records.

***

### Tips

- **Scope to subreddits for signal.** An unscoped search for "project management" returns results from 17 unrelated communities. Naming two or three relevant subreddits removes almost all of that noise.
- **Leave comments off for discovery.** Find the posts first, then re-run with `includeComments` on a narrower `maxPosts` for the ones worth reading.
- **Use `top` + a time window for research**, `new` for recency. Do not combine `new` with a time window — it has no effect.
- **`url` is the thread; `contentUrl` is the outbound link.** For an image post, `url` is the Reddit discussion and `contentUrl` is the image itself.

***

### Support

Report a problem through the **Issues** tab on this Actor's page. Issues are acknowledged within two business days.

When reporting, please include the run ID, the input you used, and what you expected.

# Actor input Schema

## `query` (type: `string`):

Keywords to search for across Reddit posts. Optional when one or more subreddits are specified below, but at least one of the two must be provided.

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

Restrict results to specific communities. Enter subreddit names without the r/ prefix, for example: startups, SaaS. Leave empty to search all of Reddit.

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

Determines how Reddit ranks the returned posts.

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

Restricts results to a time period. Reddit applies this only to the Top score and Most commented sort orders. With any other sort order it is ignored, and the run log will say so.

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

Upper limit on the number of posts returned by this run. Results are retrieved in pages of 25.

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

Retrieves the comment thread for each returned post, preserving reply nesting. Comments are charged separately from posts and add noticeably to run time.

## `maxPostsToComment` (type: `integer`):

Applies when comment threads are included. Limits how many of the returned posts have their comments retrieved, in result order. Posts beyond this limit are still returned, marked as skipped.

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

Applies when comment threads are included, and counts nested replies toward the total. Very large threads are not returned in full; each record reports whether further comments remain.

## Actor input object example

```json
{
  "query": "project management software",
  "subreddits": [],
  "sort": "relevance",
  "timeFilter": "all",
  "maxPosts": 100,
  "includeComments": false,
  "maxPostsToComment": 25,
  "maxCommentsPerPost": 100
}
```

# Actor output Schema

## `posts` (type: `string`):

Every Reddit post returned by this run, with its comment thread when comments were requested.

# 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 = {
    "query": "project management software",
    "subreddits": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("socialhz/reddit-search-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 = {
    "query": "project management software",
    "subreddits": [],
}

# Run the Actor and wait for it to finish
run = client.actor("socialhz/reddit-search-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 '{
  "query": "project management software",
  "subreddits": []
}' |
apify call socialhz/reddit-search-scraper --silent --output-dataset

```

## MCP server setup

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