# Reddit Monitor & Scraper - Brand Mentions, Signals (`webdata_labs/reddit-signal-scraper`) Actor

\[💵 $2.00 / 1K] Monitor Reddit brand and competitor mentions, return only new discussions, filter by relevance, and export posts, comments, RAG Markdown, or JSONL.

- **URL**: https://apify.com/webdata\_labs/reddit-signal-scraper.md
- **Developed by:** [WebData Labs](https://apify.com/webdata_labs) (community)
- **Categories:** Marketing, Social media, For creators
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 reddit results

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

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

Monitor Reddit for brand mentions, competitor conversations, buying intent, recommendation requests, and precise problem phrases. Run the Actor once for research or schedule it as a recurring monitor that returns only discussions it has not delivered before.

The Actor reads public Reddit pages without requiring a Reddit account, normalizes posts and comments into clean dataset rows, and can produce ranked monitoring matches, RAG-ready Markdown, or JSONL chat records. The default input is ready to run and returns recent posts from `r/programming`.

### What you can do

- Track brand, product, founder, campaign, and competitor names across Reddit.
- Return only new discussions on every scheduled run with one switch.
- Watch selected subreddits or search all public Reddit results.
- Collect a complete public thread view: post metadata plus nested comments.
- Find buying intent, recommendation requests, tracked keywords, and explicit problem phrases.
- Rank matches with a transparent, deterministic relevance score.
- Filter posts and comments by age, keywords, NSFW status, depth, and output limits.
- Export normalized records for Sheets, Slack alerts, CRMs, BI tools, data warehouses, vector databases, and model pipelines.
- Use the Actor from Apify Console, API, JavaScript, Python, curl, MCP clients, or n8n.

### Only new discussions since your last run

Enable `onlyNew` to turn any stable source configuration into a recurring Reddit monitor. The Actor automatically derives a private monitor identity from the meaningful input configuration and remembers the stable Reddit IDs that it successfully emitted.

On the first run, matching rows are returned normally. On later runs with the same monitoring configuration, previously emitted rows are skipped. You do not need to create a storage, copy an ID, choose a record name, or manage any state fields.

For a dependable recurring monitor:

1. Create an Apify Task from the input you want to monitor.
2. Set `onlyNew` to `true`.
3. Keep the sources, filters, comment settings, output format, tracking keywords, and relevance threshold stable.
4. Add a schedule, for example every hour or every morning.
5. Connect the dataset to Slack, Google Sheets, a webhook, n8n, or your own application.

Changing the monitored sources or meaningful filters creates a separate monitoring history automatically. Changing only the output row cap does not reset history, so you can safely raise or lower `maxItems` for the same monitor. A row is remembered only after it is accepted for dataset delivery; budget-limited or failed writes are not marked as delivered.

### Quick start

The default prefill is intentionally small and useful:

```json
{
  "subreddits": ["programming"]
}
```

It uses the schema defaults: newest posts, comments skipped, safe-for-work content only, standard records, and up to 100 output rows.

A practical brand monitor:

```json
{
  "searches": ["Acme Cloud", "AcmeCloud"],
  "trackingKeywords": ["Acme Cloud", "AcmeCloud"],
  "onlyNew": true,
  "sort": "new",
  "postDateLimit": "7d",
  "skipComments": true,
  "outputFormat": "signals",
  "minimumRelevanceScore": 30,
  "maxItems": 100
}
```

A competitor watchlist:

```json
{
  "subreddits": ["SaaS", "startups", "Entrepreneur"],
  "trackingKeywords": ["Competitor One", "Competitor Two", "Competitor Three"],
  "onlyNew": true,
  "sort": "new",
  "postDateLimit": "14d",
  "skipComments": true,
  "outputFormat": "signals",
  "minimumRelevanceScore": 30,
  "maxItems": 150
}
```

### Sources

You can combine multiple source types in one run.

#### Subreddit listings

Pass subreddit names with or without the `r/` prefix. The Actor supports `new`, `hot`, `top`, `rising`, and `controversial` listing orders. `top` can be combined with the Reddit time window.

```json
{
  "subreddits": ["programming", "webdev"],
  "sort": "top",
  "time": "week",
  "skipComments": true,
  "maxItems": 100
}
```

#### Reddit search

Pass one or more phrases in `searches`. Leave `searchCommunityName` empty to search Reddit broadly, or set it to one subreddit name to scope every phrase.

```json
{
  "searches": ["best CRM for a small business", "CRM recommendations"],
  "searchCommunityName": "smallbusiness",
  "sort": "new",
  "postDateLimit": "30d",
  "maxItems": 100
}
```

#### Public Reddit URLs

`startUrls` accepts public subreddit, search, user profile, and post URLs. A post URL is the best choice when you need comments from a known thread.

```json
{
  "startUrls": [
    {
      "url": "https://www.reddit.com/r/programming/"
    }
  ],
  "skipComments": true,
  "maxItems": 50
}
```

### Relevance scoring

Choose `outputFormat: "signals"` to get explainable monitoring matches instead of raw records. Every result includes `relevanceScore`, `signalTypes`, `matchedKeywords`, `evidence`, and public engagement context.

The score is deterministic and capped at 100:

```text
keyword component       = 30 + min(20, matched keyword count × 8)
buying intent           = +35
recommendation request  = +30
precise problem phrase  = +25
engagement boost        = min(15, round(log2(engagement count + 1) × 2))
relevanceScore          = min(100, sum of applicable components)
```

The keyword component is added only when at least one configured tracking keyword is found. Matching is case-insensitive. Buying-intent and recommendation categories use explicit language patterns such as active product evaluation, purchase plans, comparisons, or requests for alternatives.

The problem category intentionally requires phrase-level evidence such as “struggling with,” “running into an issue,” “stopped working,” “keeps failing,” or “waste of time.” A single generic word such as “problem” is not enough. This reduces noisy classifications and makes `evidence` easier to audit.

`engagementCount` is derived from the public engagement fields available for the source row. For a post it combines score and comment count; for a comment it uses the public comment score. Negative public scores do not reduce relevance.

Set `minimumRelevanceScore` between 0 and 100. A threshold around 25–35 is useful for broad monitoring. A threshold around 50–65 is better when an alert channel should contain only stronger purchase, recommendation, or problem signals.

### Input

The Console input is organized into five sections. Network routing and retry behavior are managed internally.

#### Sources

| Field | Type | Default | Description |
|---|---|---:|---|
| `subreddits` | string array | `[]` | Subreddit names with or without `r/`. The Console prefill contains `programming`. |
| `searches` | string array | `[]` | Brand, competitor, product, category, or research phrases to search. |
| `startUrls` | request array | `[]` | Public subreddit, search, user profile, or post URLs. |
| `searchCommunityName` | string | empty | Optional subreddit applied to every phrase in `searches`. |

#### Filters

| Field | Type | Default | Description |
|---|---|---:|---|
| `sort` | enum | `new` | `new`, `hot`, `top`, `rising`, `controversial`, `relevance`, or `comments`. |
| `time` | enum | `all` | `all`, `hour`, `day`, `week`, `month`, or `year`. Used by relevant listing/search orders. |
| `postDateLimit` | string | empty | Earliest accepted post, as an ISO date or relative value such as `7d`, `2 weeks`, or `48 hours`. |
| `includeNSFW` | boolean | `false` | Whether to include posts Reddit marks as over-18. |
| `trackingKeywords` | string array | `[]` | Phrases used for deterministic matching and relevance scoring. |
| `excludeKeywords` | string array | `[]` | Drop any post or comment containing one of these phrases. |

#### Comments

| Field | Type | Default | Description |
|---|---|---:|---|
| `skipComments` | boolean | `true` | Skip thread visits for faster post-only monitoring. |
| `maxComments` | integer | `100` | Maximum retained public comments per post. `0` means the hard cap of 1,000. |
| `maxCommentDepth` | integer | `10` | Maximum nested reply depth to retain, from 0 to 20. |
| `commentDateLimit` | string | empty | Earliest accepted comment, as an ISO date or relative cutoff. |

#### Monitoring

| Field | Type | Default | Description |
|---|---|---:|---|
| `onlyNew` | boolean | `false` | Automatically remember delivered rows and return only unseen results for the same configuration. |

#### Output

| Field | Type | Default | Description |
|---|---|---:|---|
| `outputFormat` | enum | `default` | `default`, `signals`, `rag-markdown`, or `jsonl-finetune`. |
| `minimumRelevanceScore` | integer | `25` | Minimum 0–100 score for `signals` output. |
| `maxItems` | integer | `100` | Maximum delivered dataset rows. `0` uses the Actor's internal safety cap. |

At least one source must be present after aliases are normalized. In the Console, the prefilled `subreddits` value satisfies this requirement.

### Output formats

All rows include a `recordType` so downstream workflows can branch without guessing from optional fields.

#### Posts and comments

Use `outputFormat: "default"` for normalized Reddit records.

Common post fields:

| Field | Meaning |
|---|---|
| `recordType` | `post` |
| `id`, `fullId` | Short Reddit ID and Reddit fullname |
| `title`, `text` | Post title and self-text |
| `url`, `permalink`, `linkUrl` | Canonical URL, Reddit-relative path, and outbound link |
| `subreddit`, `author` | Public community and username |
| `score`, `upvoteRatio`, `numComments` | Public engagement values when exposed |
| `createdAt`, `scrapedAt` | Content time and extraction time in UTC |
| `domain`, `flair` | Link domain and flair |
| `isNsfw`, `isSpoiler`, `isStickied`, `isLocked`, `isVideo` | Public flags |
| `thumbnail`, `imageUrls`, `language` | Media and language metadata when exposed |
| `sourceQuery` | Input source that produced the row |

Common comment fields:

| Field | Meaning |
|---|---|
| `recordType` | `comment` |
| `id`, `fullId` | Short comment ID and Reddit fullname |
| `body` | Public comment text |
| `postId`, `postTitle` | Parent post identity and title |
| `parentId`, `depth` | Parent fullname and nested reply depth |
| `subreddit`, `author`, `score` | Public community, username, and score |
| `isSubmitter`, `isStickied` | Whether the author created the post and whether the comment is pinned |
| `url`, `createdAt`, `scrapedAt`, `sourceQuery` | Provenance and timestamps |

Public subreddit and user URLs can also return `subreddit` or `user` records. Community fields include `name`, `displayName`, `publicDescription`, `subscribers`, `activeUsers`, `iconUrl`, and `bannerUrl`. Profile fields include `username`, `displayName`, `description`, `totalKarma`, and `iconUrl` when Reddit exposes them.

#### Monitoring relevance

Use `outputFormat: "signals"` for ranked and explainable monitoring rows.

```json
{
  "recordType": "signal",
  "sourceRecordType": "post",
  "id": "abc123",
  "title": "Looking for an alternative to our current project tool",
  "text": "Our team is struggling with the current setup. What should we switch to?",
  "url": "https://www.reddit.com/r/example/comments/abc123/example/",
  "subreddit": "example",
  "author": "sampleuser",
  "createdAt": "2026-07-30T09:00:00.000Z",
  "relevanceScore": 90,
  "signalTypes": ["buying_intent", "recommendation_request", "pain_point"],
  "matchedKeywords": [],
  "engagementCount": 38,
  "evidence": [
    "Language indicates active purchase interest.",
    "The author asks for a recommendation or alternative.",
    "A precise problem phrase is present."
  ],
  "sourceQuery": "project management software"
}
```

#### RAG Markdown

Use `outputFormat: "rag-markdown"` to produce one self-contained discussion document per source post. Each row has:

- `recordType: "rag_chunk"`
- a stable `chunkId` for vector database upserts
- `title` and canonical `url`
- a `markdown` document containing post context and collected public discussion
- flat `metadata` with source, post, subreddit, author, timestamps, and filtering context

This format works well with Pinecone, Qdrant, Weaviate, pgvector, Elasticsearch, OpenSearch, or a document store that feeds an embedding pipeline. Chunking and embeddings are intentionally left to the downstream system because model context sizes and retrieval strategies differ.

#### JSONL chat records

Use `outputFormat: "jsonl-finetune"` for one structured chat example per source discussion. Every row has `recordType: "finetune"`, a stable `chunkId`, `messages`, `metadata`, and source provenance. The `messages` array follows the common `role` and `content` structure and can be exported from the dataset as JSONL.

Review, filter, and label examples before using public discussions in a training pipeline. The Actor prepares consistent records; it does not assert that every collected discussion is suitable training data.

### Eight ready-to-use task recipes

Each recipe is included in the Actor repository under `examples/` and is available as a public, one-click task:

- [Monitor Reddit brand mentions](https://apify.com/webdata_labs/reddit-signal-scraper/examples/monitor-brand-mentions)
- [Track Reddit competitor mentions](https://apify.com/webdata_labs/reddit-signal-scraper/examples/track-competitors-watchlist)
- [Find Reddit buying-intent signals](https://apify.com/webdata_labs/reddit-signal-scraper/examples/find-buying-intent)
- [Create a weekly subreddit digest](https://apify.com/webdata_labs/reddit-signal-scraper/examples/weekly-subreddit-digest)
- [Export Reddit thread comments](https://apify.com/webdata_labs/reddit-signal-scraper/examples/pull-thread-comments)
- [Search Reddit with a date cutoff](https://apify.com/webdata_labs/reddit-signal-scraper/examples/search-with-date-cutoff)
- [Build a Reddit RAG corpus](https://apify.com/webdata_labs/reddit-signal-scraper/examples/build-rag-corpus)
- [Export Reddit JSONL fine-tuning data](https://apify.com/webdata_labs/reddit-signal-scraper/examples/export-jsonl-finetuning)

#### 1. Monitor brand mentions

```json
{
  "searches": ["OpenAI", "ChatGPT"],
  "trackingKeywords": ["OpenAI", "ChatGPT"],
  "onlyNew": true,
  "sort": "new",
  "postDateLimit": "7d",
  "skipComments": true,
  "outputFormat": "signals",
  "minimumRelevanceScore": 30,
  "maxItems": 100
}
```

Schedule hourly or daily and send new rows to an alert channel.

#### 2. Track a competitor watchlist

```json
{
  "subreddits": ["SaaS", "startups", "Entrepreneur"],
  "trackingKeywords": ["Notion", "Asana", "ClickUp"],
  "onlyNew": true,
  "sort": "new",
  "postDateLimit": "14d",
  "skipComments": true,
  "outputFormat": "signals",
  "minimumRelevanceScore": 30,
  "maxItems": 150
}
```

Use one saved task for a stable competitor set. Duplicate the task when you need independent histories for different markets or teams.

#### 3. Find buying intent

```json
{
  "searches": ["project management software", "best task management tool"],
  "trackingKeywords": ["project management", "task management"],
  "sort": "new",
  "postDateLimit": "30d",
  "skipComments": true,
  "outputFormat": "signals",
  "minimumRelevanceScore": 55,
  "maxItems": 100
}
```

The higher threshold favors active evaluation and recommendation language over casual mentions.

#### 4. Build a weekly subreddit digest

```json
{
  "subreddits": ["programming"],
  "onlyNew": true,
  "sort": "top",
  "time": "week",
  "postDateLimit": "7d",
  "skipComments": true,
  "outputFormat": "default",
  "maxItems": 100
}
```

Schedule weekly and summarize the delivered dataset in your preferred workflow.

#### 5. Pull a public thread and its comments

```json
{
  "startUrls": [
    {
      "url": "https://www.reddit.com/r/AskReddit/comments/1v96m3r/whats_a_boring_business_that_quietly_makes_its/"
    }
  ],
  "skipComments": false,
  "maxComments": 0,
  "maxCommentDepth": 20,
  "outputFormat": "default",
  "maxItems": 0
}
```

`0` requests the Actor's safety cap. Publicly reachable comment depth and volume still depend on what Reddit exposes.

#### 6. Search with a date cutoff

```json
{
  "searches": ["TypeScript"],
  "sort": "new",
  "postDateLimit": "14d",
  "skipComments": true,
  "outputFormat": "default",
  "maxItems": 200
}
```

Relative cutoffs are evaluated at run time, which makes them suitable for scheduled tasks.

#### 7. Build a RAG corpus

```json
{
  "subreddits": ["programming"],
  "sort": "top",
  "time": "week",
  "postDateLimit": "7d",
  "skipComments": false,
  "maxComments": 50,
  "maxCommentDepth": 8,
  "outputFormat": "rag-markdown",
  "maxItems": 25
}
```

Use `chunkId` as the stable upsert key and retain `metadata` for source citations.

#### 8. Export JSONL for a model pipeline

```json
{
  "subreddits": ["programming"],
  "sort": "top",
  "time": "week",
  "postDateLimit": "7d",
  "skipComments": false,
  "maxComments": 30,
  "maxCommentDepth": 6,
  "outputFormat": "jsonl-finetune",
  "maxItems": 20
}
```

Apply your own quality, licensing, privacy, and labeling review before training.

### Pricing

The Store price starts at **$2.00 per 1,000 delivered dataset rows**. There is no Actor start fee, empty result fee, or separate request fee. Apify platform usage is included in the pay-per-result price.

| Apify plan | Price per 1,000 results | Price per result |
|---|---:|---:|
| Free | $2.00 | $0.0020 |
| Bronze | $1.80 | $0.0018 |
| Silver | $1.60 | $0.0016 |
| Gold | $1.50 | $0.0015 |

The billable event is a successfully delivered `reddit-result`. The Actor checks the platform's charged-result response and does not mark rows as seen when the run budget prevents their delivery.

For predictable cost:

- Start with `skipComments: true` for broad monitoring.
- Use a recent `postDateLimit` on scheduled runs.
- Set `maxItems` to the maximum number of rows your downstream workflow can use.
- Collect comments only for narrow searches or direct post URLs.
- Test new monitors with a small cap before increasing volume.

### API

Replace `YOUR_APIFY_TOKEN` where needed. The Actor ID is `webdata_labs/reddit-signal-scraper`.

#### JavaScript

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

const client = new ApifyClient({
    token: process.env.APIFY_TOKEN,
});

const input = {
    searches: ['Acme Cloud', 'AcmeCloud'],
    trackingKeywords: ['Acme Cloud', 'AcmeCloud'],
    onlyNew: true,
    sort: 'new',
    postDateLimit: '7d',
    skipComments: true,
    outputFormat: 'signals',
    minimumRelevanceScore: 30,
    maxItems: 100,
};

const run = await client.actor('webdata_labs/reddit-signal-scraper').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();

console.log(`Received ${items.length} new Reddit rows`);
```

#### Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])

actor_input = {
    "subreddits": ["SaaS", "startups"],
    "trackingKeywords": ["Acme Cloud", "Competitor One"],
    "onlyNew": True,
    "sort": "new",
    "postDateLimit": "7d",
    "skipComments": True,
    "outputFormat": "signals",
    "minimumRelevanceScore": 30,
    "maxItems": 100,
}

run = client.actor("webdata_labs/reddit-signal-scraper").call(
    run_input=actor_input
)
items = client.dataset(run["defaultDatasetId"]).list_items().items

print(f"Received {len(items)} new Reddit rows")
```

#### curl

Synchronous run with dataset items returned in the response:

```bash
curl "https://api.apify.com/v2/acts/webdata_labs~reddit-signal-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "searches": ["Acme Cloud"],
    "trackingKeywords": ["Acme Cloud"],
    "onlyNew": true,
    "sort": "new",
    "postDateLimit": "7d",
    "skipComments": true,
    "outputFormat": "signals",
    "minimumRelevanceScore": 30,
    "maxItems": 100
  }'
```

For long runs, start the Actor asynchronously, poll the run until it reaches a terminal state, then fetch items from `defaultDatasetId`. This avoids client timeouts and makes retries easier to control.

### Use with MCP and AI agents

Apify provides a remote MCP endpoint at `https://mcp.apify.com`. Connect an MCP-compatible client with your Apify credentials, expose this Actor as an allowed tool, and ask the client to run monitoring jobs or inspect results.

Install it for Claude Code with the Apify CLI:

```bash
apify mcp install claude-code --tools webdata_labs/reddit-signal-scraper
```

The same command can be adapted to other supported clients by changing the client argument. In Claude Desktop, add Apify as a custom remote connector, use `https://mcp.apify.com` as the server URL, authenticate with Apify, and allow `webdata_labs/reddit-signal-scraper`.

Useful agent prompts:

- “Run `webdata_labs/reddit-signal-scraper` for new mentions of Acme Cloud from the last seven days. Rank monitoring matches and show only results above 40.”
- “Monitor r/SaaS and r/startups for Acme Cloud and two competitors. Return only discussions not delivered by the previous run.”
- “Collect this public Reddit thread and format the discussion as RAG Markdown with source metadata.”
- “Search Reddit for people actively comparing project management tools and return the strongest explainable matches.”

For unattended agents, use a saved Apify Task with conservative limits. Keep destructive or external actions—such as posting messages, updating a CRM, or emailing a lead—behind an explicit approval step in your own workflow.

### n8n workflow

A reliable recurring flow uses these nodes:

1. **Schedule Trigger** — run hourly, daily, or weekly.
2. **Apify node or HTTP Request** — start a saved task or call the Actor with `onlyNew: true`.
3. **Wait and poll** — fetch run status until it is `SUCCEEDED`, `FAILED`, `ABORTED`, or `TIMED-OUT`.
4. **HTTP Request** — fetch dataset items from the run's `defaultDatasetId`.
5. **IF** — stop when the item array is empty; an empty second monitor run is a valid outcome.
6. **Split Out** — process each new dataset row.
7. **Switch** — route by `recordType`, `signalTypes`, or a `relevanceScore` band.
8. **Slack, Google Sheets, Notion, database, or webhook** — deliver or store the selected rows.

Recommended operational details:

- Let Apify Tasks hold the stable Actor input instead of duplicating JSON across n8n nodes.
- Set the HTTP timeout above the expected Actor duration.
- Retry transient request failures, but do not automatically rerun a successful task merely because it returned zero items.
- Use the canonical Reddit `url` as a human-facing link and `fullId` or `chunkId` as the downstream deduplication key.
- Store the Apify run ID with downstream records for traceability.
- Alert separately on failed Actor runs and on downstream delivery failures.

### Reliability and data behavior

The Actor is designed for public-data monitoring, not authenticated account automation.

- Requests use adaptive pacing, bounded retries, exponential backoff, and jitter for temporary Reddit or network failures.
- Public rows are deduplicated by stable Reddit identity before output.
- Output limits are enforced across combined sources, not independently per source.
- Dates are normalized to ISO 8601 UTC strings where the source exposes a timestamp.
- Relative date filters are resolved from the run start time.
- Keyword matching is case-insensitive and deterministic.
- Exclusion filtering is applied before output conversion.
- The monitor records only rows successfully accepted for dataset delivery.
- Network routing is managed by the Actor and is not exposed as a tuning surface.

Reddit can change public HTML, cursor behavior, or rate limits without notice. The Actor retries temporary failures and fails clearly when a source cannot be processed safely; it does not fabricate missing rows.

#### Comment completeness

The Actor follows comment data exposed on public thread and subtree pages. `maxComments` is a retention ceiling, not a promise that Reddit will expose that many comments. Deleted, removed, private, quarantined, login-gated, collapsed, or account-gated branches may be absent. Reddit's visible comment count can include rows that are unavailable to a public unauthenticated request.

Use a direct post URL, a narrow row cap, and `skipComments: false` when comment completeness matters. For broad brand monitoring, post-only runs are faster and more predictable.

#### Search and listing completeness

Reddit decides which results and pagination cursors are exposed for a query or listing. Very deep historical retrieval is therefore not guaranteed, even with a high output cap. Use date cutoffs and recurring `onlyNew` schedules to collect fresh coverage continuously instead of relying on one very deep backfill.

Search sort modes and time windows follow Reddit's public behavior. A subreddit listing and a Reddit search for the same phrase can produce different result sets.

### Related Actors

Combine this Actor with other WebData Labs products:

- [Trustpilot Review Scraper](https://apify.com/webdata_labs/trustpilot-review-scraper) — monitor public review changes and customer feedback.
- [Website Contact Extractor](https://apify.com/webdata_labs/website-contact-extractor) — enrich approved company research with public contact details.
- [Review Pain Miner API](https://apify.com/webdata_labs/review-pain-miner-api) — structure recurring problems found in review datasets.
- [TikTok Comment Intent Leads](https://apify.com/webdata_labs/tiktok-comment-intent-leads) — find explainable intent signals in public TikTok discussions.
- [TikTok Comments Scraper](https://apify.com/webdata_labs/tiktok-comments-scraper) — collect public comment datasets from TikTok.

A common monitoring stack uses Reddit for community conversations, Trustpilot for review changes, and TikTok for high-volume social comments. Keep each source in its own dataset and join them downstream using your brand, competitor, or campaign taxonomy.

### Responsible use

Use this Actor only for lawful purposes and public data you are permitted to process. Follow Reddit's terms, Apify's terms, applicable privacy and data-protection law, contractual restrictions, and the rules that apply to your organization and location.

Do not use the output for harassment, unlawful discrimination, doxxing, credential collection, invasive profiling, or automated decisions that create significant effects for individuals. Avoid redistributing personal data without a lawful basis. Minimize retention, protect access tokens and datasets, honor valid deletion requests, and apply human review before contacting people or making consequential decisions.

The Actor does not bypass private communities, deleted content, authentication controls, or technical access restrictions. Public availability does not automatically grant every downstream use right. You are responsible for your input, schedule, retention policy, integrations, and use of the resulting data.

### FAQ

#### Does it require Reddit API credentials?

No. It reads public Reddit pages and does not require you to supply Reddit account credentials.

#### Can it monitor multiple brands or competitors?

Yes. Add several phrases to `searches` and `trackingKeywords`, or watch a stable set of subreddits. For unrelated products or teams, use separate saved tasks so each monitor has clear ownership and history.

#### Why did a recurring run return zero rows?

With `onlyNew: true`, zero rows normally means the Actor found no unseen results that passed the configured filters. It can also mean the current public Reddit result window contains only records delivered earlier. Check run status and logs before treating an empty dataset as a failure.

#### What resets monitoring history?

Changing meaningful monitor inputs—sources, filters, comment settings, output format, tracking keywords, or relevance threshold—creates a new automatic monitor identity. Changing `maxItems` alone does not. Creating the same configuration under a different Actor installation also keeps its storage isolated.

#### Can I retrieve every comment from a large thread?

You can request up to the 1,000-comment safety cap, but Reddit may expose fewer comments publicly. Removed, collapsed, private, or account-gated branches may not be available. The Actor returns the public rows it can verify.

#### What does `maxComments: 0` mean?

It requests the Actor's internal hard cap of 1,000 retained public comments per post. It does not mean unlimited requests or guaranteed completeness.

#### What does `maxItems: 0` mean?

It uses an internal run safety cap. For scheduled monitoring and paid runs, an explicit finite limit is easier to budget.

#### How should I choose a relevance threshold?

Start at 25–35 for discovery. Use 50–65 for alert channels or sales-research queues where buying, recommendation, or precise problem evidence should dominate. Review a small sample and adjust for your vocabulary.

#### Can I add my own classifier?

Yes. Use `default` output to retain normalized source records, or use `signals` as a deterministic first-stage filter. Then send the dataset to your own rules, model, webhook, or n8n workflow.

#### Which output should I use for a vector database?

Use `rag-markdown`. Store `chunkId` as the upsert key, embed `markdown`, and retain `metadata` plus `url` for filtering and citations.

#### Which output should I use for JSONL?

Use `jsonl-finetune`, export the dataset as JSONL, and apply your own quality and rights review. The generated structure is a starting point, not an automatically approved training set.

#### Is the Actor safe to schedule?

Yes, when you use a saved task, finite limits, recent date cutoffs, and alerts for failed runs. `onlyNew` is designed for recurring use, and adaptive pacing is handled internally.

#### Does it post, vote, message, or log in to Reddit?

No. It is a read-only public-data collector.

### Changelog

#### 2026-07-30

- Repositioned the Actor around recurring Reddit brand and competitor monitoring.
- Added one-switch `onlyNew` monitoring with automatic, Actor-isolated persistent history.
- Renamed monitoring ranking to `relevanceScore` and the input threshold to `minimumRelevanceScore`.
- Tightened problem detection to require explicit phrase-level evidence.
- Simplified the Console to 18 visible fields in Sources, Filters, Comments, Monitoring, and Output.
- Moved network pacing, retry policy, pagination safety, and monitor storage behind the Actor interface.
- Added pay-per-result aware dataset delivery with the domain event `reddit-result`.
- Added eight ready-to-use monitoring, research, comments, RAG, and JSONL task recipes.
- Expanded output schemas, monitoring documentation, MCP setup, n8n guidance, pricing, legal notes, and operational limits.

#### 2026-07-29

- Added public Reddit search, listing, user, post, and nested comment extraction.
- Added deterministic keyword and intent signals.
- Added relative and ISO date filters.
- Added RAG Markdown and JSONL chat output.
- Added structured dataset views for records, monitoring matches, and AI-ready rows.

### Support

If a public Reddit URL stops working or an output field changes, open an issue from the Actor page. Include:

- the Apify run ID;
- the source type and a non-sensitive example URL or search phrase;
- the expected and observed row counts;
- whether comments and `onlyNew` were enabled;
- the output format;
- the approximate time of the run.

Do not post API tokens, private dataset links, personal data, or credentials in a public issue. For reproducible reports, start with a small `maxItems` value and the narrowest source that demonstrates the behavior.

# Actor input Schema

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

Subreddit names with or without the r/ prefix. Add several communities for one watchlist.

## `searches` (type: `array`):

Search phrases to track across Reddit, such as a brand name, competitor, or product category.

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

Public subreddit, search, user profile, or post URLs to collect directly.

## `searchCommunityName` (type: `string`):

Optional subreddit name applied to every search phrase.

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

Order in which Reddit exposes posts or search results.

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

Reddit time window for top and search results.

## `postDateLimit` (type: `string`):

Keep posts on or after an ISO date or relative cutoff such as 7d, 2 weeks, or 48 hours.

## `includeNSFW` (type: `boolean`):

Include content Reddit marks as over-18.

## `trackingKeywords` (type: `array`):

Brand, competitor, product, or problem phrases used for deterministic matching and relevance scoring.

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

Drop posts and comments containing any of these phrases.

## `skipComments` (type: `boolean`):

Return posts faster without visiting comment threads. Turn off to collect discussions.

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

Maximum public comments retained per visited post. Use 0 for the hard cap of 1,000.

## `maxCommentDepth` (type: `integer`):

Maximum nested reply depth to retain.

## `commentDateLimit` (type: `string`):

Keep comments on or after an ISO date or relative cutoff such as 7d or 48 hours.

## `onlyNew` (type: `boolean`):

Remember emitted records automatically and return only unseen results on later runs with the same configuration.

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

Return posts and comments, relevance-ranked monitoring matches, RAG Markdown, or JSONL chat rows.

## `minimumRelevanceScore` (type: `integer`):

Keep monitoring matches at or above this transparent 0-100 relevance threshold.

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

Maximum rows delivered in the dataset. Use 0 for the internal hard cap.

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

Internal Reddit access configuration managed automatically by the Actor.

## Actor input object example

```json
{
  "subreddits": [
    "programming"
  ],
  "searches": [],
  "startUrls": [],
  "sort": "new",
  "time": "all",
  "includeNSFW": false,
  "trackingKeywords": [],
  "excludeKeywords": [],
  "skipComments": true,
  "maxComments": 100,
  "maxCommentDepth": 10,
  "onlyNew": false,
  "outputFormat": "default",
  "minimumRelevanceScore": 25,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Dataset containing the selected Reddit output format.

## `files` (type: `string`):

Key-value store containing the run summary.

# 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 = {
    "subreddits": [
        "programming"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("webdata_labs/reddit-signal-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 = { "subreddits": ["programming"] }

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

```

## MCP server setup

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

```

## OpenAPI specification

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