# Reddit Scraper - Posts, Comments & Search (`smart_albatross/reddit-posts-comments-scraper`) Actor

Scrape Reddit posts, comments, subreddits, user profiles and keyword search results. Filter by flair, score and date; export reply trees, text and media to JSON, CSV or Excel. No Reddit API key required. Run through the Apify API or connect n8n, Make and Zapier.

- **URL**: https://apify.com/smart\_albatross/reddit-posts-comments-scraper.md
- **Developed by:** [Dev](https://apify.com/smart_albatross) (community)
- **Categories:** Social media
- **Stats:** 4 total users, 3 monthly users, 97.4% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $7.50 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

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 — Posts, Comments, Search and Flairs

Collect public Reddit posts, comments, subreddit feeds, keyword search results, user profiles and flair metadata. Export text, scores, dates, media and reply relationships to JSON, CSV or Excel, or connect the Actor to n8n, Make, Zapier and the Apify API.

This version includes operator-managed Reddit access. **Customers do not need to supply Reddit cookies or configure a proxy.** It uses Reddit's web-facing routes, not the official Reddit developer API, and is not affiliated with Reddit.

#### Quick start

1. Choose **What do you want to collect?** (leave Auto for ordinary URLs).
2. Enter **Subreddits** such as `n8n`, or use **Reddit URLs** instead.
3. Optionally enter a keyword, then set **Maximum output rows**; start with 10. Choose **Posts and their comments** if you want reply trees.
4. Start the Actor and inspect or export the dataset.

```json
{
  "subreddits": ["n8n"],
  "sort": "new",
  "maxItems": 10
}
```

#### Result pricing

**Current status (September 8, 2026): $7.50 per 1,000 saved results for both ordinary and keyword scraping, plus the existing startup fee.** The requested lower tariff below is **not yet active or scheduled**: Apify rejected its submission because pricing was changed too recently. The Actor's Pricing tab is authoritative; the billing code does not charge an unregistered keyword event.

The requested tariff is **$3 per 1,000 ordinary results** and **$5 total per 1,000 keyword-search results**, plus the existing Actor start event ($0.0005 at the default 512 MB; the number of start events scales with allocated memory). The table below describes this requested tariff, not the current one.

**Activation:** check this Actor's Pricing tab for the active tariff and any scheduled effective date. If Apify applies a notice period, the preceding tariff remains in effect until that date; a run uses the pricing snapshot assigned when it starts. Billing-capable builds (1.8 and later) apply the new split automatically when the keyword event becomes active. Use `latest`; older pinned builds do not implement the keyword surcharge.

| Saved result | Base result charge | Keyword surcharge | Total per result |
| --- | --- | --- | --- |
| Ordinary subreddit/profile/post scraping, comment trees and flair metadata | $0.003 | None | $0.003 |
| Post, community or user search-query results; comment keyword-search results | $0.003 | $0.002 | $0.005 |

Keyword billing follows each result's source, including complete Reddit search URLs with a query. It does not depend on whether an ordinary scraped post happens to contain the word. In mixed-source runs, ordinary rows stay at the ordinary rate. Flat comments retrieved from searched posts inherit the search source rate; they are not necessarily keyword-matching comments unless you use Comment keyword search.

Only saved dataset rows are result-billed. Duplicates, filtered-out candidates, scanned pages and unavailable comments are not result-billed. A post containing nested `comments`/`commentsFlat` is one dataset row; nested replies are not billed separately. The start event still applies to runs returning no rows.

Apify may display two result events for keyword output: the base result event plus `keyword-result`. Their sum is **$5/1,000**, not $8/1,000. `SUMMARY.billing` reports row categories, active unit prices, and budget stops. Runs stop before another result would exceed the configured spending limit. Taxes or account-specific discounts, if any, are handled by Apify.

#### Supported sources

- Subreddits: `/r/n8n/new/`, `/hot/`, `/top/?t=week`, `/rising/` and `/controversial/`.
- Direct posts: canonical Reddit post URLs or supported `t3_` post identifiers.
- Public user profiles: `/user/username/` for profile details, `/submitted/` for posts, `/comments/` for comment history and `/overview/` for mixed history.
- Reddit keyword search: add a keyword to subreddit names or subreddit feed URLs to search within those communities. With no sources, the keyword runs a global search. Complete search URLs also work on their own.
- Community details: `/r/n8n/about/`.
- Flair templates: choose **Flair templates** with subreddit names, or use `/r/n8n/flairs/`.

Use an explicit public subreddit such as `r/all` instead of an account-personalized home feed. Use canonical post URLs rather than browser-resolved share links. Private, quarantined or unverified-visibility content is not returned through managed access.

#### Search, ranking and filters

```json
{
  "subreddits": ["n8n"],
  "search": "workflow",
  "sort": "top",
  "time": "month",
  "minScore": 5,
  "maxItems": 25
}
```

Post searches support relevance, hot, top, new and most-comments ordering. Time windows include hour, day, week, month, year and all time. Without a keyword, explicit feed URL ordering takes precedence. Adding a keyword turns a subreddit feed into a search and uses **Result order**, not the feed's `/new/` or `/hot/` path. Explicit search URLs retain their own sort/time parameters. User histories and subreddit feeds support their respective Reddit sort options.

Post keywords use Reddit's indexed search semantics, not a guaranteed literal substring filter. Comment keyword search separately verifies literal matching against the full current comment body.

#### Simple form and existing JSON inputs

The main form has seven controls: collection mode, subreddits, URLs, keyword, row limit, result order and time range. Date/flair/score filters, comment-tree settings, comment matching and page limits are in optional collapsible sections. There is no prefilled subreddit URL to accidentally consume your search limit.

Legacy aliases and technical controls remain available in JSON, including `searchMode`, `subreddit`, `profile`, `postUrls`, `maxPosts`, `postSort`, `timeRange`, `includeComments`, `outputFormat`, `flairId`, `excludeFlairs`, `authorFlair`, `discoverFlairs`, `includePromoted`, `skipRemoved`, `includePostBody`, `pageSize`, `repairMissing`, `repairThreshold` and `requestDelayMs`. Managed access still rejects customer credentials/proxy overrides and custom code.

**Migration note:** combining a keyword with subreddit feeds now searches those communities. To intentionally retain the old independent URL jobs plus global search, supply `"searchScope": "independent"` in JSON. Those jobs still share one row cap and earlier sources may consume it. A keyword combined with a profile or direct post URL now produces a clear error instead of silently running an unrelated global search. All existing field names remain supported, but this ambiguous combined-input behavior is intentionally changed.

Available filters include post flair text or template ID, excluded flairs, author flair, minimum score, minimum comment count, before/after timestamps, NSFW selection and removed/deleted-comment exclusion. Filters are applied before consuming the output limit. Pagination continues until the cap, page limit or available listing ends.

```json
{
  "startUrls": ["https://www.reddit.com/r/n8n/new/"],
  "flair": "Help",
  "postedAfter": "2026-01-01",
  "minComments": 2,
  "maxItems": 20,
  "endPage": 5
}
```

#### Comments and reply trees

```json
{
  "startUrls": ["https://www.reddit.com/r/SUBREDDIT/comments/POST_ID/TITLE/"],
  "mode": "posts-and-comments",
  "maxItems": 1,
  "maxComments": 100,
  "maxCommentsPerPost": 100,
  "commentSort": "new"
}
```

Replace the placeholder with a real public post URL. Enriched posts contain `comments` and `commentsFlat`, retaining parent IDs, post context and depths. Comment sorts include confidence, top, new, controversial, old and Q\&A. Reddit's displayed count may include replies that are deleted, removed, unavailable or not returned by its web routes.

For comment-only output, use `mode: "comments"` with `postUrls` or supported Start URLs and a comment limit. Original `subreddit`, `profile`, `maxPosts`, `postUrls` and `maxComments` inputs remain supported. Original non-URL `posts-and-comments` inputs retain flat post/comment rows; compatible URL inputs keep their nested output convention. Overlapping sources are deduplicated within a run.

#### Comment keyword search across subreddits

Available in version 1.6 and later. Earlier versions do not include this mode.

Use `mode: "comment-search"` (or `searchMode: "comment"`) to search comment text directly, without first searching parent posts. Clear Start URLs and supply a literal keyword/phrase and subreddit names:

```json
{
  "mode": "comment-search",
  "search": "workflow",
  "subreddits": ["n8n", "automation"],
  "keywordMatch": "whole-word",
  "caseSensitive": false,
  "sort": "new",
  "time": "all",
  "postedAfter": "2026-09-01T00:00:00Z",
  "postedBefore": "2026-09-07T23:59:59.999Z",
  "maxItems": 100,
  "endPage": 20,
  "maxScannedComments": 10000
}
```

Each dataset row is a verified, currently retrievable comment matching the keyword, subreddit and **comment creation time**, not the parent post's date. Older threads can contain recent matching comments. Only emitted matches consume `maxItems` and result-row charges. Candidates may be inspected internally without being emitted.

- Matching: `substring` (default), Unicode-aware `whole-word`, or `phrase` (normalizes whitespace). Case-insensitive by default. Supply plain text without Reddit operators or surrounding quotes.
- Dates: `postedAfter` and `postedBefore` are inclusive. Date-only values mean midnight UTC. `time` is an additional coarse Reddit search window; use `all` when exact date filters should be the only time restriction.
- Limits: `maxItems` is global after filtering/deduplication; 0 removes this result cap. `endPage` defaults to 20 per subreddit; 0 removes the page cap. `maxScannedComments` defaults to 10000 globally and must remain finite. These limits do not imply full historical coverage.
- Sorting: `new` (default), `top`, or `relevance`. Pages alternate between subreddits; combined output is not globally sorted across sources. A small result limit may be satisfied by the first source.
- Coverage: `SUMMARY` includes per-source pages/scanned/emitted counts, unavailable candidates, remaining-page indicators and `result-limit`, `scan-limit`, `page-limit` or `search-exhausted` stop reasons. Search exhaustion means no further indexed results were exposed, not that every historical comment was found. Reddit controls page size: a fetched page may contain more candidates than the remaining scan budget. `searchCandidatesReturned` reports received candidates; `scannedComments` counts those processed within the budget, and `unprocessedVerifiedComments` reports any verified rows left unprocessed after the result cap.

Search snippets are rechecked against public comment data before output. Removed/unavailable comments are omitted. The mode does not expand reply trees. Post URLs, post/author flair filters, score filters, NSFW filters and custom output hooks are not supported in this mode; conflicting inputs are rejected rather than ignored. Missing Reddit fields remain null. Public visibility checks, TLS verification, pacing and fail-fast access handling still apply.

Reddit search controls which candidates are discoverable; this is not an exhaustive substring scan of a subreddit's history. Deleted, private, unindexed or inaccessible comments cannot be promised. Comment-search latency includes page retrieval and public-comment verification and differs from single-post benchmarks.

#### Output fields

Posts include IDs, title, text and HTML when available, author, subreddit, permalink, creation/edit times, scores, upvote ratio, comment count, flair IDs/text/colors, author flair, gallery/image/video links, flags and source context.

Comments include comment/post/parent IDs, author, text and HTML, score, timestamps, depth and post context. Profiles and community records have their own metadata fields. Flair records include label, template ID, rich text and colors. Fields that Reddit does not provide remain null rather than being invented. Owner-specific saved/vote/moderation details are stripped; removed content is not restored through account privileges.

#### Performance and limits

The lightweight HTTP build avoids launching Chromium. It saves the first result immediately, then batches subsequent dataset writes while scraping continues. The `SUMMARY` key-value record reports source progress, warnings, request timings, first-result timings, committed rows and dataset batch counts.

Earlier session-backed cloud tests returned single rows in about 3–7 seconds, including three concurrent runs in 2.66–3.15 seconds. A 25-row test took 3.35 seconds. These are small-workload observations, **not a guaranteed response time or sustained-capacity claim**. Additional visibility checks, comment expansion, filters, Reddit throttling and platform startup can increase runtime.

`maxItems` limits output across all sources in a run; nested comments use separate limits. `endPage` applies per source. Zero means no caller-specified cap, not guaranteed retrieval of every historical item. Reddit listing/search ceilings still apply. This HTTP release does not include the original browser-based deep-pagination fallback.

Managed access is initially intended for low-volume workloads. It enforces request pacing within each run and stops on authentication failures or rate limits. It does not automatically rotate accounts to retry blocked requests, and does not yet provide a distributed account-pool scheduler across customer runs. Expired operator sessions require operator maintenance.

#### Security and migration notes

Customer JavaScript hooks (`customMapFunction` and `extendOutputFunction`), customer cookies, proxy overrides, custom user agents and browser overrides are disabled in this managed release. They are rejected by runtime validation, not merely hidden in the UI. Remove those fields from old tasks/API inputs before running this version. Normal scraping filters, formats and limits remain available.

Operator credentials are stored as secret runtime configuration, not in public inputs, source files, datasets or build arguments. The Actor only reads public Reddit content and does not vote, post, message or modify accounts.

For programmatic use, start the Actor with your Apify token and the same JSON input, wait for completion or use a webhook, then retrieve its default dataset. See [Apify run and build options](https://docs.apify.com/actors/running/runs-and-builds).

# Actor input Schema

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

Choose posts, posts with comments, comment rows from post URLs, or keyword-matching comments. Auto detects ordinary URLs. No separate Search mode is needed.

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

Names without r/, e.g. n8n and automation. For posts, add a keyword to search within these communities. Required for comment keyword search. Leave empty when using URLs instead.

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

Subreddit feeds, posts, profiles or complete search URLs. With a keyword, subreddit feeds become scoped post searches. For comment keyword search use Subreddits instead. Do not enter the same source twice.

## `search` (type: `string`):

With subreddit names/feed URLs: search posts in those communities. With no sources: global Reddit search. Posts use Reddit search syntax, not strict literal filtering. Comment keyword search requires literal text and Subreddits.

## `maxItems` (type: `integer`):

Maximum saved rows across this run, after filtering and deduplication. Default 100; 0 removes this cap, not Reddit's coverage limits. Comment trees have separate expansion caps below.

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

Post search: relevance, hot, top, new, comments. Comment keyword search: new, top, relevance. Feeds use their URL order; when adding a keyword to a feed, this field orders the search instead.

## `time` (type: `string`):

Reddit search/top-feed time window. For exact timestamps use Optional filters. Not every feed sort supports time windows.

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

Inclusive ISO date/time, e.g. 2026-09-01 or 2026-09-01T12:00:00Z.

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

Inclusive ISO date/time. Date-only values mean midnight UTC.

## `flair` (type: `string`):

Only post rows with this exact flair text (case insensitive). Continues pagination until the output/page limit or feed exhaustion.

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

Minimum score for post and comment rows.

## `minComments` (type: `integer`):

Minimum Reddit-reported comment count for post rows.

## `nsfw` (type: `string`):

Filters returned rows by Reddit's NSFW flag. Does not grant access to restricted content.

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

Comment trees only: total comments retrieved across posts. Default 100. Use 0 to remove this expansion cap; Maximum output rows still applies to flat comment output.

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

Optional per-post cap. Set 0 for no per-post cap.

## `commentSort` (type: `string`):

Ordering used for comment trees.

## `keywordMatch` (type: `string`):

Comment-search mode only. Defaults to substring. Applied to the full current comment body before saving. Reddit's index determines which candidates are discoverable; substring matching does not expand its index coverage.

## `caseSensitive` (type: `boolean`):

Comment-search mode only. False by default; true requires matching letter case in the comment body.

## `maxScannedComments` (type: `integer`):

Comment-search safety cap across all sources, counting candidates including duplicates and non-matches. Defaults to 10000. Separate from Maximum output rows, which counts only verified matches. Check SUMMARY for early stops.

## `endPage` (type: `integer`):

Maximum listing pages fetched per source. Comment search defaults to 20 per subreddit; other modes default to no page cap. 0 removes this cap, but comment search still enforces Maximum scanned comments.

## `searchMode` (type: `string`):

Select what the keyword search returns. Comment search requires Subreddits below and a literal keyword/phrase; clear Start URLs.

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

Expand replies and attach a reply tree plus commentsFlat under each post. maxComments and maxCommentsPerPost bound expansion. Nested comments are part of the post row.

## `pageSize` (type: `integer`):

Up to 100 listing records per request; use 25 when comparing page counts with smaller-page scrapers.

## `flairId` (type: `string`):

Exact flair template ID. Use flair discovery to retrieve IDs and colors.

## `excludeFlairs` (type: `array`):

Exclude exact flair labels, case insensitive.

## `authorFlair` (type: `string`):

Only post/comment rows with this exact author flair (case insensitive).

## `discoverFlairs` (type: `boolean`):

Emit available flair templates before scraping each subreddit URL. Flair rows count toward maxItems. Use mode flairs with subreddit to retrieve templates only.

## `outputFormat` (type: `string`):

epctex naming uses lowercase types, full post IDs, and compatible aliases; comments keep short IDs plus commentId. Legacy preserves original post id/type.

## `subreddit` (type: `string`):

Subreddit name without r/. Use this or Profile, not both.

## `profile` (type: `string`):

Reddit username without u/. Use this or Subreddit, not both.

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

Posts whose complete comment trees should be expanded. Also accepts redd.it links, share links, comment permalinks, and t3 IDs.

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

Maximum unique posts. Set 0 to continue until Reddit exhausts its listing.

## `postSort` (type: `string`):

Legacy post-sort option. Prefer Sort above for URL/search runs; original browser-only CLI profile continuation supports New.

## `timeRange` (type: `string`):

Time filter used by Top and Controversial post sorts.

## `includePromoted` (type: `boolean`):

Include advertisements when Reddit returns them.

## `skipRemoved` (type: `boolean`):

Drop comment rows whose body is \[removed] or \[deleted].

## `includePostBody` (type: `boolean`):

Convenient for flat exports but increases dataset size.

## `repairMissing` (type: `boolean`):

Re-fetch parent subtrees when Reddit's batch endpoint silently omits several reply IDs.

## `repairThreshold` (type: `integer`):

Repair a parent subtree after this many omitted replies. Lower values improve coverage but cost more requests.

## `requestDelayMs` (type: `integer`):

Minimum delay between successive requests in this run. Managed access enforces at least 1500 ms and stops on access failures/rate limits.

## `searchScope` (type: `string`):

Default targets searches within supplied subreddit feeds. independent explicitly restores the older separate URL + global-search jobs sharing one row cap.

## Actor input object example

```json
{
  "mode": "auto",
  "maxItems": 100,
  "sort": "relevance",
  "time": "all",
  "nsfw": "include",
  "maxComments": 100,
  "maxCommentsPerPost": 0,
  "commentSort": "confidence"
}
```

# Actor output Schema

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

The default dataset containing one item per post or comment.

## `summary` (type: `string`):

Final mode, item count, and completion timestamp. Comment search also reports scanned/filtered/unavailable candidates and per-source stop reasons; no full-history guarantee.

# 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 = {
    "mode": "auto",
    "maxItems": 100,
    "sort": "relevance",
    "time": "all",
    "nsfw": "include"
};

// Run the Actor and wait for it to finish
const run = await client.actor("smart_albatross/reddit-posts-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 = {
    "mode": "auto",
    "maxItems": 100,
    "sort": "relevance",
    "time": "all",
    "nsfw": "include",
}

# Run the Actor and wait for it to finish
run = client.actor("smart_albatross/reddit-posts-comments-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 '{
  "mode": "auto",
  "maxItems": 100,
  "sort": "relevance",
  "time": "all",
  "nsfw": "include"
}' |
apify call smart_albatross/reddit-posts-comments-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,smart_albatross/reddit-posts-comments-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/16JQJNfVzAAHgMFYR/builds/hfq8GtueXa7fBKOT4/openapi.json
