# Reddit Posts Scraper (`automation-lab/reddit-posts-search-scraper`) Actor

Search and export normalized public Reddit posts by keyword, subreddit, author, URL, and time window for research and monitoring.

- **URL**: https://apify.com/automation-lab/reddit-posts-search-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.44 / 1,000 item processeds

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

## Reddit Posts Scraper

Collect normalized public **Reddit posts** for community research, topic monitoring, content discovery, and data pipelines.
Search by keyword, collect a subreddit or author's submissions, process a Reddit URL, and apply a UTC date window.
Each dataset row includes the post text, author, subreddit, engagement, flair, media links, permalink, and timestamps.

### What does Reddit Posts Scraper do?

Reddit Posts Scraper turns public post feeds into structured JSON records.
It supports four ways to identify posts:

- keyword queries, including focused `subreddit:NAME keyword` searches;
- one or more subreddit names;
- one or more public authors;
- Reddit post, subreddit, user, or search URLs.

The Actor deduplicates posts across inputs and enforces one run-wide `maxItems` limit.
It can filter records by both Reddit's relative time filter and exact `fromDate` / `toDate` boundaries.

### Who is this Reddit posts tool for?

- **Community managers** tracking topics across relevant subreddits.
- **Market researchers** collecting discussion titles, text, and engagement.
- **Content teams** finding questions and themes worth answering.
- **Developers and data teams** feeding public Reddit data into a warehouse or spreadsheet.
- **Analysts** comparing activity across communities or scheduled snapshots.

This Actor collects public posts only. It does not log in, vote, post, message users, or collect private communities.

### Why use this Actor?

- Multiple discovery inputs produce one consistent row format.
- Post IDs are deduplicated across all supplied targets.
- Engagement and flair are included when exposed by the available public data surface.
- Date boundaries are applied consistently before a record is saved.
- A blocked route is retried through bounded sessions and, where equivalent, a public structured fallback.
- Charge events map directly to the run start and emitted post records.

### What Reddit post data can I extract?

| Field | Meaning |
| --- | --- |
| `postId` | Reddit post ID |
| `title` | Post title |
| `body` | Public self-post text when available |
| `author` | Public username or `[deleted]` |
| `subreddit` | Community name without `r/` |
| `score` | Visible or archived post score |
| `commentsCount` | Visible or archived comment count |
| `upvoteRatio` | Public upvote ratio when available |
| `flair` | Post flair text |
| `postType` | `text`, `link`, `image`, `video`, or `unknown` |
| `mediaUrls` | Public image or video URLs discovered for the post |
| `outboundUrl` | Destination of a link post, or its Reddit URL |
| `permalink` | Canonical public Reddit post URL |
| `createdAt` | Post creation time in ISO 8601 |
| `scrapedAt` | Collection time in ISO 8601 |
| `matchedTarget` | Input target that discovered the post |
| `metricsAvailable` | Whether engagement enrichment was available |

### How to scrape Reddit posts

1. Open the Actor input page.
2. Add at least one search query, subreddit, author, or Reddit URL.
3. Choose a sort and relative time filter if relevant.
4. Optionally add exact UTC `fromDate` and `toDate` values.
5. Set `maxItems` to bound the output and cost.
6. Click **Start**.
7. Open the **Reddit posts** dataset view or export JSON, CSV, Excel, XML, or RSS.

A focused first run might use:

```json
{
  "searchQueries": ["subreddit:webscraping crawler"],
  "sort": "new",
  "timeFilter": "year",
  "maxItems": 20
}
```

### Input parameters

| Input | Type | Default | Description |
| --- | --- | --- | --- |
| `searchQueries` | string array | none | Keywords or phrases. Use `subreddit:NAME keyword` for a focused community search. |
| `subreddits` | string array | none | Public subreddit names without `r/`. |
| `authors` | string array | none | Public Reddit usernames without `u/`. |
| `startUrls` | URL request list | none | Reddit post, subreddit, user, or search URLs. |
| `sort` | string | `relevance` | `relevance`, `new`, `hot`, `top`, or `comments`. |
| `timeFilter` | string | `all` | `hour`, `day`, `week`, `month`, `year`, or `all`. |
| `fromDate` | `YYYY-MM-DD` | none | Keep posts on or after this UTC date. |
| `toDate` | `YYYY-MM-DD` | none | Keep posts on or before this UTC date. |
| `maxItems` | integer | `50` | Maximum unique posts across every input, from 1 to 5,000. |
| `maxRequestRetries` | integer | `2` | Transient request retries, from 0 to 5. |

At least one discovery input is required.
Unsupported domains and malformed dates fail clearly instead of producing a silent empty dataset.

### Output example

This shortened example reflects the current normalized output shape:

```json
{
  "postId": "1visw8i",
  "title": "PatronView blocks Amazon's AI crawler after 117,000 daily page reads",
  "body": "",
  "author": "danie-l",
  "subreddit": "webscraping",
  "score": 1,
  "commentsCount": 0,
  "upvoteRatio": 1,
  "flair": "Bot detection 🤖",
  "postType": "link",
  "mediaUrls": [],
  "outboundUrl": "http://ppc.land/patronview-blocks-amazons-ai-crawler-after-117-000-daily-page-reads",
  "permalink": "https://www.reddit.com/r/webscraping/comments/1visw8i/",
  "createdAt": "2026-08-08T10:51:50.000Z",
  "scrapedAt": "2026-08-08T15:00:02.920Z",
  "source": "reddit",
  "matchedTarget": "r/webscraping",
  "metricsAvailable": true
}
```

Values change as Reddit discussions change.
A zero score or comment count can be a real value; use `metricsAvailable` to distinguish successful enrichment from limited metadata.

### How much does it cost to scrape Reddit posts?

The Actor uses pay-per-event pricing:

- one **Start** event of **$0.0025** per run;
- one **Item processed** event for each post saved;
- the BRONZE item price is **$0.0024 per post**, with lower unit prices on higher platform tiers.

At BRONZE pricing:

| Saved posts | Estimated Actor charge |
| ---: | ---: |
| 10 | $0.0265 |
| 100 | $0.2425 |
| 1,000 | $2.4025 |

The estimates are the start event plus saved-item events.
Your Apify plan and platform usage can affect the final account total.
Use `maxItems` to set a predictable output ceiling.

### Monitor communities and topics

For recurring monitoring, create an Apify Task with stable inputs and schedule it daily or weekly.
A useful weekly snapshot can include multiple communities:

```json
{
  "subreddits": ["artificial", "technology"],
  "fromDate": "2026-08-01",
  "toDate": "2026-08-08",
  "sort": "new",
  "maxItems": 100
}
```

Store each run's dataset ID or export rows to your destination.
Compare `postId`, `score`, and `commentsCount` across snapshots in your own database when change history matters.
The Actor emits a current normalized snapshot; it does not maintain cross-run alerts itself.

### Export Reddit posts to spreadsheets and data pipelines

From the dataset page you can download JSON, CSV, Excel, XML, or RSS.
For automation, connect the run or dataset to:

- Google Sheets for editorial and community review;
- Make or Zapier for downstream workflows;
- a webhook that starts when a run succeeds;
- a database or data warehouse through the Apify API;
- an LLM or retrieval pipeline using the normalized body and metadata.

Use `postId` as the stable source key when upserting records.
Use `matchedTarget` when one run combines several communities or queries.

### Run with the Apify API

Set `APIFY_TOKEN` in your shell rather than embedding it in source control.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~reddit-posts-search-scraper/runs?token=$APIFY_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"subreddits":["games"],"sort":"new","maxItems":25}'
```

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/reddit-posts-search-scraper').call({
  searchQueries: ['subreddit:webscraping crawler'],
  sort: 'new',
  timeFilter: 'year',
  maxItems: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/reddit-posts-search-scraper').call(run_input={
    'authors': ['spez'],
    'maxItems': 20,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use Reddit Posts Scraper with MCP

#### Claude Code

Add the Actor to Claude Code through Apify MCP:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/reddit-posts-search-scraper"
```

#### Claude Desktop

Add this HTTP server in Claude Desktop's MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "type": "http",
      "url": "https://mcp.apify.com?tools=automation-lab/reddit-posts-search-scraper"
    }
  }
}
```

#### Cursor

Add the same `mcpServers.apify` HTTP configuration in Cursor's MCP settings.

#### VS Code

Add the same Apify HTTP endpoint to your VS Code MCP server configuration.

Example prompts:

- “Collect 25 new posts from r/games and summarize the recurring themes.”
- “Search r/webscraping for crawler discussions and return the posts with the most comments.”
- “Create a weekly Reddit community monitoring input for r/artificial and r/technology.”

Review generated inputs before running them, especially `maxItems` and date boundaries.

### Data quality and source behavior

Reddit can challenge or rate-limit automated requests.
The Actor starts with a lightweight public feed, uses bounded sticky-session recovery when needed, and uses an equivalent public structured fallback for subreddit, author, and post targets.
It never converts a challenge page into an empty successful result.

Public archive enrichment can lag live Reddit or retain a historical value that later changes.
Deleted, removed, quarantined, banned, or private posts may be absent or have limited fields.
Global keyword searches rely on Reddit's public search feed; a `subreddit:NAME keyword` query has a stronger constrained fallback.

### Limits and troubleshooting

- A run can save at most 5,000 posts.
- Reddit feeds and archive endpoints can expose fewer records than requested.
- Date filtering applies before saving and charging an item.
- Inputs are processed in order until the run-wide item limit is reached.
- Duplicate IDs are saved once.
- This Actor collects posts, not comment bodies or full comment trees.

If a global query is blocked, retry later or constrain it as `subreddit:NAME keyword` when that scope meets your research job.
If an author or community has no rows, confirm that it is public and has submitted posts in the requested period.

### Responsible use and legality

Only collect public data you are permitted to use.
Follow Reddit's terms, applicable laws, and the requirements of your downstream systems.
Do not use the output for harassment, spam, invasive profiling, re-identification, or decisions that require protected personal data.
Minimize retention, secure exports, and honor deletion obligations relevant to your use case.
This documentation is not legal advice.

### FAQ

#### Can I search all of Reddit by keyword?

Yes, use `searchQueries` for public Reddit search.
For more resilient focused monitoring, use `subreddit:NAME keyword` or combine a query with explicit subreddit tasks.

#### Can I scrape a single Reddit post URL?

Yes. Add a public post URL to `startUrls`.
The result uses the same normalized fields and date filters as discovered records.

#### Can I collect posts by a Reddit user?

Yes. Add one or more usernames to `authors`, or provide a public Reddit user URL.
Private, suspended, or deleted accounts may return no records.

#### Does it collect comments?

It returns each post's public `commentsCount` when available, but it does not collect comment bodies.
Use a dedicated comments Actor when you need discussion trees.

#### Why is `metricsAvailable` false?

Reddit exposed the post through a feed but the engagement enrichment surface was unavailable.
The title, author, body/link, permalink, and timestamp remain useful; engagement fields may be zero.

#### Why did my run fail instead of returning an empty dataset?

A source challenge is not a genuine no-result response.
The Actor fails clearly after its bounded recovery routes are exhausted so monitoring systems can retry or alert rather than store a false empty snapshot.

### Related Automation Lab Actors

- [Reddit Scraper](https://apify.com/automation-lab/reddit-scraper) for broader Reddit post and comment workflows.
- [Reddit Historical Archive Scraper](https://apify.com/automation-lab/reddit-historical-archive-scraper) for explicit historical post and comment windows.
- [Reddit User Profile Bulk Scraper](https://apify.com/automation-lab/reddit-user-profile-bulk-scraper) for public profile metadata at scale.
- [Reddit Subreddit Metadata Scraper](https://apify.com/automation-lab/reddit-subreddit-metadata-scraper) for community-level metadata rather than post rows.

Choose this Actor when the primary output should be one normalized record per public Reddit post for search and scheduled monitoring.

# Actor input Schema

## `searchQueries` (type: `array`):

Keywords or phrases to search across public Reddit posts.

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

Subreddit names whose public post feeds should be collected, without r/.

## `authors` (type: `array`):

Reddit usernames whose public submitted posts should be collected, without u/.

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

Public Reddit post, subreddit, user, or search URLs. URL inputs use the same filters and item limit as other inputs.

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

Ordering requested from Reddit. Some feed types support a subset and use new as a safe fallback.

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

Reddit's relative time filter for searches and top feeds.

## `fromDate` (type: `string`):

Keep posts created on or after this UTC date (YYYY-MM-DD).

## `toDate` (type: `string`):

Keep posts created on or before this UTC date (YYYY-MM-DD).

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

Maximum unique post records saved across all inputs.

## `maxRequestRetries` (type: `integer`):

Retries for transient Reddit rate limits, server errors, and network failures.

## Actor input object example

```json
{
  "searchQueries": [
    "web scraping"
  ],
  "sort": "relevance",
  "timeFilter": "all",
  "maxItems": 20,
  "maxRequestRetries": 2
}
```

# Actor output Schema

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

Default dataset containing all collected Reddit post 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 = {
    "searchQueries": [
        "web scraping"
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/reddit-posts-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 = {
    "searchQueries": ["web scraping"],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/reddit-posts-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 '{
  "searchQueries": [
    "web scraping"
  ],
  "maxItems": 20
}' |
apify call automation-lab/reddit-posts-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/reddit-posts-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/DWQ309Ek3lSCg9x9B/builds/bNx6Dh63re06szikE/openapi.json
