# Reddit Scraper (`modnine/reddit-scraper`) Actor

Scrape Reddit posts, comments, users, and subreddits without login. Native nested comment trees, accurate in-subreddit search, fast direct JSON API. First 100 results free.

- **URL**: https://apify.com/modnine/reddit-scraper.md
- **Developed by:** [Silver](https://apify.com/modnine) (community)
- **Categories:** Social media, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

Scrape Reddit **posts, comments, users, and subreddits** in a single dataset. Built directly on Reddit's `.json` API — no headless browser, no login, no surprises.

✅ **Posts, comments, users, subreddits** — one clean dataset, `type` field discriminates rows
✅ **Native nested comment trees** — `replies[]` filled in, not flat with `parent_id`
✅ **Accurate in-subreddit search** — uses `restrict_sr=on` for scoped, relevant results
✅ **Per-source diagnostics** — clear summary at end of run explains exactly what each input produced
✅ **First 100 results free** — no credit card needed

***

### What you can scrape

Drop in any combination of:

- **Subreddit URLs** (`reddit.com/r/python/`, `reddit.com/r/python/top/`) → posts
- **Post URLs** (`reddit.com/r/python/comments/abc/...`) → post + full comment tree (optionally nested)
- **User URLs** (`reddit.com/user/spez`) → user profile + their submissions
- **Search queries** scoped to a subreddit → relevant posts only

Every result lands in your dataset as one flat JSON record with a `type` field (`post`, `comment`, `user`, `subreddit`).

***

### Quick start

#### Scrape a subreddit's hot posts

```json
{
  "startUrls": ["https://www.reddit.com/r/python/"],
  "maxItems": 100,
  "sort": "hot"
}
```

#### Scrape a post with its full nested comment tree

```json
{
  "startUrls": ["https://www.reddit.com/r/python/comments/1t3x7ba/..."],
  "includeComments": true,
  "nestedComments": true,
  "maxCommentsPerPost": 200
}
```

#### Search relevant posts inside a community

```json
{
  "searches": ["pytest fixtures"],
  "searchSubreddit": "python",
  "sort": "relevance",
  "maxItems": 50
}
```

#### Scrape a user's recent activity

```json
{
  "startUrls": ["https://www.reddit.com/user/spez/"],
  "maxPostsPerSource": 25
}
```

***

### Pricing

| | |
|---|---:|
| Per actor run | $0.001 |
| Per dataset item | $0.00349 ($3.49 / 1,000) |
| Free trial | first 100 results |

Set `maxItems` on any run to cap your spend. The actor stops the moment that limit is reached.

***

### Output schema

Every dataset item has a `type` discriminator: `post`, `comment`, `user`, `subreddit`.

#### `type: "post"`

| Field | Notes |
|---|---|
| `id`, `permalink`, `url`, `subreddit`, `subreddit_id` | Reddit identifiers |
| `author`, `author_id`, `author_flair` | Poster info — `author_id` is `t2_xxx` |
| `title`, `text` | `text` is `selftext`, may be empty for link posts |
| `created_utc` | Unix seconds (not ISO string — easier to filter in code) |
| `score`, `upvote_ratio`, `num_comments` | Engagement |
| `over_18`, `spoiler`, `stickied`, `locked`, `is_video`, `is_ad` | Flags |
| `flair` | Post flair text |
| `media[]` | Structured `{type: image|video, url}` array |

#### `type: "comment"`

| Field | Notes |
|---|---|
| `id`, `permalink`, `post_id`, `parent_id`, `subreddit` | IDs |
| `author`, `body` | |
| `score`, `created_utc`, `is_submitter`, `depth` | |
| `replies[]` | Nested children when `nestedComments=true`, else `[]` |

#### `type: "user"`

| Field | Notes |
|---|---|
| `name`, `id` | Username + Reddit's internal ID |
| `link_karma`, `comment_karma`, `total_karma` | |
| `created_utc` | Unix seconds, account creation |
| `is_employee`, `verified`, `has_verified_email`, `is_mod` | Flags |
| `icon_img` | Avatar URL |

***

### FAQ

**Do I need a Reddit account?** No. All endpoints used are public.

**Will my IP / Apify account get banned?** No. We don't post anything, don't authenticate, and stay well under Reddit's rate-limits. Apify's residential proxies (default) are rotated per run.

**What's the difference between flat and nested comments?** With `nestedComments: false` (default) every comment is a separate dataset row, linked by `parent_id`. With `nestedComments: true` each top-level comment includes its replies inline as a `replies[]` array.

**Can I limit by date?** Yes — set `postsAfter` to `YYYY-MM-DD` (UTC). Posts older than that are skipped.

**My run returned 0 items — why?** Check the run log. The actor emits an end-of-run summary listing every source URL with one of: `OK`, `not_found` (private/banned subreddit), `blocked` (rare), or `error`. If you used `searches`, set `searchSubreddit` to scope it — Reddit's global search is noisy.

**Can I use my own proxy?** Yes — pass it under `proxy.proxyUrls`. Apify's residential proxies (the default) are recommended; datacenter IPs are blocked by Reddit.

***

### Need a more focused tool?

These specialized actors share the same engine but have simpler input forms:

- **Reddit Comments Scraper** — post URLs in, full nested trees out (6 input fields)
- **Reddit User Scraper** — usernames in, profile + activity out (4 input fields)
- **Reddit Search Scraper** — keyword + community in, relevant posts out (8 input fields)

***

### Changelog

#### 0.4.0

- Cleaner schema: 4 specialized actors share this engine
- Added `author_id`, `author_flair`, `is_ad` to post output
- End-of-run summary explains exactly what each source produced
- Input validation catches non-Reddit URLs before consuming budget

#### 0.1.0 — Initial release

- Direct `.json` API (no headless)
- 4 modes: subreddit, post+comments, user, search
- Native nested-comments mode
- Firefox TLS fingerprint with fallback ladder
- `restrict_sr=on` for accurate in-subreddit search

# Actor input Schema

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

Subreddit, post, or user URLs to scrape. Examples:

- https://www.reddit.com/r/python/
- https://www.reddit.com/r/python/top/
- https://www.reddit.com/r/python/comments/abc123/title/
- https://www.reddit.com/user/spez/

Leave empty to use Search instead.

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

Optional Reddit search queries. Each query produces matching posts. Use `searchSubreddit` to scope to one community for relevance.

## `searchSubreddit` (type: `string`):

If set, search runs inside this subreddit only (no leading r/). Strongly recommended — global Reddit search returns noisy results.

## `scrapeMode` (type: `string`):

How to interpret the URLs. `auto` detects each URL's kind (subreddit / post / user). Use the explicit modes only if you want to override that or your URLs are unusual.

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

How to sort subreddit listings and search results.

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

Time filter when sort=top.

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

Hard cap on dataset items across all sources combined. Posts, comments, users count as 1 item each.

## `maxPostsPerSource` (type: `integer`):

How many posts to take from each subreddit, search, or user page before moving on.

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

When scraping posts, also fetch their comment trees. Adds 1 request per post. Comments count toward `maxItems`.

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

Cap on comments per post (top-level + nested). Reddit's default page is ~200.

## `nestedComments` (type: `boolean`):

If true, comments are emitted as nested trees with `replies[]` filled in. If false (default), each comment is a separate flat dataset item with `parent_id`.

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

If false, NSFW posts are filtered out client-side and `include_over_18=false` is sent to Reddit's listing endpoint.

## `postsAfter` (type: `string`):

Only emit posts created on or after this date. Leave empty to include everything. Saves cost on large subreddits.

## `requestDelay` (type: `integer`):

Pause between paginated requests. 0 is fine for residential proxies; raise to 1-2 if you hit rate-limits.

## `proxy` (type: `object`):

Apify Proxy is recommended (RESIDENTIAL group). Datacenter IPs are blocked by Reddit.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.reddit.com/r/python/"
  ],
  "searches": [],
  "scrapeMode": "auto",
  "sort": "hot",
  "time": "week",
  "maxItems": 100,
  "maxPostsPerSource": 25,
  "includeComments": false,
  "maxCommentsPerPost": 50,
  "nestedComments": false,
  "includeNSFW": true,
  "requestDelay": 1,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "startUrls": [
        "https://www.reddit.com/r/python/"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("modnine/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 = {
    "startUrls": ["https://www.reddit.com/r/python/"],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("modnine/reddit-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 '{
  "startUrls": [
    "https://www.reddit.com/r/python/"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call modnine/reddit-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

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