# Reddit Scraper | All in one (`scrapeforge/reddit-scraper`) Actor

Scrape Reddit posts, comments, subreddits, and user profiles. Extract engagement metrics, media, nested comment threads, and 35+ data fields. Filter by date, score, NSFW, and media.

- **URL**: https://apify.com/scrapeforge/reddit-scraper.md
- **Developed by:** [ScrapeForge](https://apify.com/scrapeforge) (community)
- **Categories:** Social media, Automation, News
- **Features:** Limited permissions
- **Stats:** 44 total users, 9 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.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?

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

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

## How to integrate an Actor?

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

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

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

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

# README

## Reddit Scraper 🤖

Scrape **Reddit posts, comments, subreddits, search results, and user profiles** — fast, at scale, and **without a Reddit API key or login**. Extract engagement metrics, media URLs, nested comment threads, and 35+ structured fields from any public Reddit content.

Perfect for market research, brand monitoring, sentiment analysis, trend tracking, lead generation, and feeding LLMs/RAG pipelines with real Reddit discussions.

### Why this scraper

- 🔑 **No API key, no Reddit account** — just run it.
- ⚡ **Fast & concurrent** — processes posts in parallel; a lightweight *metadata-only* mode for cheap, high-speed monitoring.
- 🔎 **Deep search coverage** — returns **several times more results per query** than a basic search.
- 💬 **Full comment threads** — nested replies, optionally flattened into one row per comment.
- 🧱 **35+ structured fields** per post, ready for analysis or the API/MCP.
- 💸 **Transparent, low cost** — pay only for what you scrape.

### What you can scrape

| Source | How |
|--------|-----|
| **Subreddit** posts | `subreddits: ["technology"]` |
| **Search** across Reddit | `searchTerms: ["machine learning"]` |
| **User** posts & comments | `usernames: ["spez"]` |
| **Any Reddit URL** | `startUrls` — posts, subreddits, users, or search URLs |

### Two modes: tune speed vs. depth

| | **Full mode** (default) | **Fast mode** |
|---|---|---|
| Set | `fetchPostDetails: true` | `fetchPostDetails: false` |
| Gets | title, body text, **upvote ratio**, media, all fields | post metadata only (title, score, author, dates, flags, media) — no body/ratio |
| Speed / cost | one extra request per post | metadata only → **much faster & cheaper** |
| Best for | full analysis | high-volume monitoring, dashboards |

> Comments are a separate switch — turn on **`scrapeComments`** to extract them (each comment is a billed result and its own row). See the Comments section below.

### Input

#### Scraping sources (use one or combine)

| Field | Type | Description |
|-------|------|-------------|
| `subreddits` | string\[] | Subreddit names (without `r/` prefix) |
| `searchTerms` | string\[] | Keywords to search across Reddit |
| `usernames` | string\[] | Reddit usernames (without `u/` prefix) |
| `startUrls` | URL\[] | Direct Reddit URLs (posts, subreddits, users, search) |

#### Scope, sorting & coverage

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `maxItems` | integer | 100 | Max posts per source (1–10,000) |
| `sort` | string | `hot` | `hot`, `new`, `top`, `rising`, `relevance`, `comments` |
| `timeFilter` | string | `all` | Time range for `top`/search: `hour`, `day`, `week`, `month`, `year`, `all` |
| `maximizeCoverage` | boolean | `true` | For **searches**, gather results more thoroughly and de-duplicate → many more posts per query |

#### Comments

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `scrapeComments` | boolean | false | **Turn ON to extract comments.** Each comment is a **billed result** and its **own row** (linked to its post). OFF = comments are never fetched (no cost) |
| `maxComments` | integer | 100 | Max comments per post (only when `scrapeComments` is ON) |
| `commentDepth` | integer | 3 | Max depth of nested replies, 1–20 (only when `scrapeComments` is ON) |

#### Filters

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `startDate` | string | — | Only posts after this date (`YYYY-MM-DD`) |
| `endDate` | string | — | Only posts before this date (`YYYY-MM-DD`) |
| `minScore` | integer | — | Minimum post score |
| `includeNSFW` | boolean | false | Include NSFW posts |
| `mediaOnly` | boolean | false | Only posts with images, videos, or galleries |

#### Performance & advanced

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `fetchPostDetails` | boolean | true | Fetch full post detail (body, upvote ratio, comments). Turn **off** for fast, cheap metadata-only runs |
| `maxConcurrency` | integer | 5 | How many posts to process in parallel (1–20) |
| `customMapFunction` | string | — | JavaScript to transform each result. Receives `post`, must return an object |

### Output

Each post is one dataset item with 35+ fields:

```json
{
  "id": "1abc123",
  "title": "Post title",
  "text": "Post body text",
  "url": "https://www.reddit.com/r/technology/comments/1abc123/...",
  "author": "username",
  "authorFullname": "t2_abc",
  "subreddit": "technology",
  "score": 15432,
  "upvoteRatio": 0.95,
  "numComments": 892,
  "postType": "image",
  "createdAt": "2026-04-15T10:30:00.000Z",
  "domain": "i.redd.it",
  "isNSFW": false,
  "hasMedia": true,
  "media": [{ "type": "image", "url": "https://i.redd.it/...jpeg" }],
  "linkFlair": "Discussion",
  "comments": [
    { "author": "commenter", "body": "Comment text", "score": 523, "depth": 0, "isOP": false, "replies": [] }
  ]
}
```

**Field groups:** core (`id`, `title`, `text`, `author`, `subreddit`, `permalink`, `createdAt`, `postType`, `domain`, `linkUrl`) · engagement (`score`, `upvoteRatio`, `numComments`, `numCrossposts`, `totalAwards`) · media (`thumbnail`, `media[]`, `hasMedia`, `hasVideo`, `hasImage`, `isGallery`) · flags (`isNSFW`, `isSpoiler`, `isStickied`, `isLocked`, `isArchived`, `isSelf`) · flair (`linkFlair`, `authorFlair`) · metadata (`subredditSubscribers`, `sourceType`, `sourceQuery`, `scrapedAt`).

With `scrapeComments: true`, each comment becomes its own **billed row** (`itemType: "comment"`) carrying `body`, `author`, `score`, `depth`, `isOP`, plus `postId`/`postTitle`/`subreddit` to link it back to its post — ideal for exporting a flat comment list.

### Examples

**Top posts from a subreddit (last week):**

```json
{ "subreddits": ["technology"], "maxItems": 50, "sort": "top", "timeFilter": "week" }
```

**Search Reddit, maximum coverage:**

```json
{ "searchTerms": ["benq monitor"], "maxItems": 300, "sort": "relevance", "maximizeCoverage": true }
```

**A post with its comments (each comment a billed row):**

```json
{ "startUrls": ["https://www.reddit.com/r/AskReddit/comments/1abc123/title/"], "scrapeComments": true, "maxComments": 100 }
```

**Posts + comments as a flat list:**

```json
{ "subreddits": ["buildapc"], "maxItems": 50, "scrapeComments": true, "maxComments": 100 }
```

**Fast, cheap monitoring (metadata only):**

```json
{ "subreddits": ["worldnews"], "maxItems": 500, "fetchPostDetails": false, "sort": "new" }
```

### Tips on speed & cost

- **Don't need body text?** Set `fetchPostDetails: false` — dramatically faster and cheaper (no per-post fetch).
- **Need comments?** Turn on `scrapeComments` — each comment is a billed row. Set `maxComments` sensibly (e.g. `50–200`); cost scales with how many comments you pull.
- **Want more results from a search?** Keep `maximizeCoverage: true` and raise `maxItems`.
- Raise `maxConcurrency` (e.g. 8–10) for more speed, or lower it to be gentler.

### Limitations

- Scrapes **public** content only. Private or quarantined subreddits return an error.
- `upvoteRatio` and post **body text** require `fetchPostDetails: true`; **comments** require `scrapeComments: true`.
- Very large comment threads may not return every single nested reply.
- `subredditSubscribers` and award counts are best-effort and may be `0` when not exposed.

### Disclaimer

This actor accesses publicly available data from Reddit and is provided for research and educational purposes. By using it you agree to comply with [Reddit's User Agreement](https://www.redditinc.com/policies/user-agreement) and all applicable laws. You are solely responsible for how the collected data is used. Always respect rate limits and the privacy of Reddit users.

# Actor input Schema

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

Reddit URLs to scrape: subreddit URLs (r/python), post URLs, user profiles (u/username), or search URLs.

## `searchTerms` (type: `array`):

Keywords to search across Reddit.

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

Subreddit names to scrape posts from (without r/ prefix).

## `usernames` (type: `array`):

Reddit usernames to scrape posts/comments from (without u/ prefix).

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

Maximum number of posts to extract per source.

## `scrapeComments` (type: `boolean`):

Turn ON to extract comments. ⚠️ Each comment is counted as a result (it adds to cost) and appears as its own row in the dataset, linked to its post. Turn OFF and comments are never fetched (no cost, no rows).

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

Maximum comments to extract per post. Only applies when 'Scrape comments' is ON.

## `commentDepth` (type: `integer`):

Maximum depth of nested replies to follow. Only applies when 'Scrape comments' is ON.

## `fetchPostDetails` (type: `boolean`):

Extract full post detail — body text and upvote ratio. More complete data, but slower (one extra request per post). Turn OFF for fast, low-cost runs that return post metadata only (title, score, author, dates, media, flags).

## `maxConcurrency` (type: `integer`):

How many posts to process in parallel. Higher = faster; lower = gentler.

## `maximizeCoverage` (type: `boolean`):

For search terms, gather results more thoroughly and de-duplicate them to return more posts per query. Only affects searchTerms.

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

Sort order for subreddit posts and search results.

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

Time range filter (for 'top' and search sorting).

## `startDate` (type: `string`):

Only include posts after this date (YYYY-MM-DD).

## `endDate` (type: `string`):

Only include posts before this date (YYYY-MM-DD).

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

Only include posts with at least this score.

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

Include NSFW (Not Safe For Work) posts.

## `mediaOnly` (type: `boolean`):

Only include posts that contain media (images, videos, galleries).

## `customMapFunction` (type: `string`):

JavaScript function to transform each post object. Receives 'post' as argument, must return an object.

## Actor input object example

```json
{
  "subreddits": [
    "programming"
  ],
  "maxItems": 100,
  "scrapeComments": false,
  "maxComments": 100,
  "commentDepth": 3,
  "fetchPostDetails": true,
  "maxConcurrency": 5,
  "maximizeCoverage": true,
  "sort": "hot",
  "timeFilter": "all",
  "includeNSFW": false,
  "mediaOnly": false
}
```

# Actor output Schema

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

All scraped items (posts, and comments when enabled) in the default dataset.

## `overview` (type: `string`):

Default dataset rendered with the Overview view (key post fields).

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

Flat comment rows — meaningful when 'Comments as Separate Items' is enabled.

# 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("scrapeforge/reddit-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("scrapeforge/reddit-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 '{
  "subreddits": [
    "programming"
  ]
}' |
apify call scrapeforge/reddit-scraper --silent --output-dataset

```

## MCP server setup

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