# Reddit Scraper - Posts, Comments, Users & Search (`benthepythondev/reddit-scraper`) Actor

Scrape public Reddit posts, comments, user activity, subreddits, and search results through Reddit's app-only OAuth API. Export nested threads, scores, media, Markdown, and token counts to JSON, CSV, or Excel. No Reddit login or user-supplied API key required.

- **URL**: https://apify.com/benthepythondev/reddit-scraper.md
- **Developed by:** [Ben](https://apify.com/benthepythondev) (community)
- **Categories:** Developer tools, Social media, AI
- **Stats:** 179 total users, 17 monthly users, 81.3% runs succeeded, 7 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $2.40 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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, users and search

Extract **Reddit posts, comments, user history and search results** as clean, structured
data, with a selected **Markdown, HTML or plain-text `content` field** on each post,
comment and nested reply. Original text fields and word/token counts remain available. No
Reddit login or user-supplied API key: point it at a subreddit, a post URL, a username or
a search query and get back the available posts and comments with scores, images and nested
comment hierarchies. Source access and complete-thread availability vary. Export to
JSON/CSV/Excel, run on a schedule, call via
API, or connect to Make, Zapier or n8n.

**Transparent pricing:** `$0.003` per dataset row plus a `$0.00005` run-start event
per GB of allocated memory (minimum one). Posts and top-level comments are separate rows;
nested replies stay inside their parent comment's `replies` field. A 10-post run at
1 GB costs **$0.03005** before account discounts.

**Choose the amount of data first:** start with `includeComments: false` for a post list. Enabling comments adds top-level dataset rows and result charges; nested replies remain inside the parent row. Use a small post/comment limit and inspect partial-thread coverage before scheduling a larger run.

### Quick start

Open the [tested Python-posts example](https://apify.com/benthepythondev/reddit-scraper/examples/reddit-top-python-posts-week)
or start with three posts and no comment expansion:

```json
{
  "mode": "subreddit",
  "subreddit": "Python",
  "sort": "top",
  "timeFilter": "week",
  "maxPosts": 3,
  "includeComments": false,
  "outputFormat": "text",
  "includeImages": false
}
```

Use `content` for the selected representation and `content_format` to identify it.
The **Full Content** dataset view displays both fields. The original `selftext`,
`selftext_markdown`, `selftext_html`, `body`, `body_markdown` and `body_html` fields
remain available to existing integrations. A link-only post can have empty content;
its title and destination URL remain separate.

`text` removes markup from source HTML while retaining paragraph/list boundaries.
When source HTML is missing, it preserves the original text, which may still contain
Markdown. `html` decodes Reddit's outer HTML encoding; if HTML is absent, it escapes
the original text inside a paragraph. This field contains source markup, not a
sanitized webpage component. `markdown` uses the existing Markdown representation.

`includeImages: false` clears the `images` array and sets `thumbnail` to null. It
does not rewrite a post's URL or remove links from its original content.

### 🤖 What is the Reddit Scraper?

It turns any Reddit page into a structured dataset. Choose one of four modes — **subreddit**,
single **post + comments**, **user** posts or a Reddit **search** — add optional filters
for sort order, time range, date and result caps, then Run. The Actor reads Reddit's public
OAuth API (no browser or user login needed), paginates automatically, and can expand Reddit's "load
more comments" and "continue this thread" stubs. The returned count may be below
`num_comments` because of your cap, removed content or source limits. Posts and top-level
comments are dataset rows; nested replies retain their hierarchy inside those rows.

#### What data does it extract?

- **Post title, body and content** in `markdown`, `html` or `text` (whichever you pick)
- **Scores & engagement** — `score`, `upvote_ratio`, `num_comments`, total awards
- **Author & subreddit** (with subreddit ID) and the post `permalink` + `url`
- **Nested comment threads** with full hierarchy, depth, scores and timestamps
- **User post history** across any public account
- **Images & media** — image URLs with width/height, plus thumbnails
- **Post type & flags** — self/video, NSFW, spoiler, stickied, locked, post hint, domain
- **Flair** (`link_flair_text`) and **timestamps** (`created_utc`)
- **AI-ready stats** — `word_count` and estimated `token_count` for every post and comment

### ⬇️ Input

Run it four ways — pick a `mode` and fill in the matching field:

| Field | Description |
|-------|-------------|
| `mode` | `subreddit`, `post`, `user`, or `search` |
| `subreddit` | Subreddit to scrape, e.g. `python` or `r/python` (subreddit mode) |
| `postUrl` | Full URL of a Reddit post (post mode) |
| `username` | Reddit username to pull posts from (user mode) |
| `searchQuery` | Search term to find posts (search mode) |
| `searchSubreddit` | Optionally limit a search to one subreddit |
| `sort` | `hot`, `new`, `top`, `rising`, `controversial`, or `relevance` (search) |
| `timeFilter` | `hour`, `day`, `week`, `month`, `year`, `all` (for top/controversial) |
| `maxPosts` | Max posts to scrape, 0 = unlimited (up to 10,000) |
| `maxComments` | Max comments per post, 0 = unlimited |
| `includeComments` | Also scrape comments for each post in subreddit mode |
| `expandMoreComments` | Resolve "load more" / "continue thread" stubs (on by default) |
| `sinceDate` | Subreddit mode only: posts on or after this UTC date (`YYYY-MM-DD`) |
| `outputFormat` | `markdown`, `html`, or `text`, returned in `content` throughout the comment tree |
| `includeImages` | `false` returns `images: []` and `thumbnail: null`; default `true` preserves them |
| `delaySeconds` | Delay between requests to respect rate limits |

#### Example input

```json
{
  "mode": "subreddit",
  "subreddit": "ArtificialInteligence",
  "sort": "top",
  "timeFilter": "week",
  "maxPosts": 100,
  "includeComments": true,
  "maxComments": 200,
  "outputFormat": "markdown",
  "includeImages": true
}
```

### ⬆️ Output

Posts and top-level comments are dataset rows; nested replies remain inside `replies`.
Export JSON to preserve the tree, or CSV/Excel for a flat view of top-level rows.

A **post** has the following shape. This is an illustrative record, not a live result:

```json
{
  "id": "abc123",
  "title": "How I built an AI agent that scrapes Reddit",
  "url": "https://www.reddit.com/r/ArtificialInteligence/comments/abc123/how_i_built_an_ai_agent/",
  "permalink": "/r/ArtificialInteligence/comments/abc123/how_i_built_an_ai_agent/",
  "selftext": "Here's my complete guide to building a scraping agent...",
  "selftext_markdown": "Here's my complete guide to building a **scraping agent**...",
  "content": "Here's my complete guide to building a **scraping agent**...",
  "content_format": "markdown",
  "author": "ai_developer",
  "subreddit": "ArtificialInteligence",
  "subreddit_id": "t5_2qh0y",
  "score": 1250,
  "upvote_ratio": 0.97,
  "num_comments": 89,
  "is_self": true,
  "is_video": false,
  "post_hint": "self",
  "domain": "self.ArtificialInteligence",
  "thumbnail": "https://b.thumbs.redditmedia.com/example.jpg",
  "images": [
    { "url": "https://i.redd.it/example.jpg", "width": 1200, "height": 800, "caption": null }
  ],
  "created_utc": "2026-06-20T10:30:00",
  "total_awards_received": 3,
  "link_flair_text": "Discussion",
  "over_18": false,
  "spoiler": false,
  "stickied": false,
  "locked": false,
  "word_count": 850,
  "token_count": 1200
}
```

An illustrative **comment**, returned in post mode or in subreddit mode with `includeComments`:

```json
{
  "id": "xyz789",
  "post_id": "abc123",
  "parent_id": "t3_abc123",
  "permalink": "/r/ArtificialInteligence/comments/abc123/how_i_built_an_ai_agent/xyz789/",
  "body": "This is brilliant — how do you handle rate limits?",
  "body_markdown": "This is brilliant — how do you handle rate limits?",
  "content": "This is brilliant — how do you handle rate limits?",
  "content_format": "markdown",
  "author": "curious_dev",
  "score": 42,
  "ups": 42,
  "downs": 0,
  "created_utc": "2026-06-20T11:05:00",
  "edited": false,
  "is_submitter": false,
  "stickied": false,
  "depth": 0,
  "replies": [],
  "total_awards_received": 0,
  "word_count": 8,
  "token_count": 11
}
```

### 💡 Use cases

- **🤖 AI & LLM training data:** pull real human conversations and expert Q\&A from any community as clean Markdown with token counts, ready for fine-tuning and RAG pipelines.
- **📊 Market & brand research:** track mentions, pain points and product feedback across subreddits to understand what people actually think.
- **😊 Sentiment analysis:** scrape thousands of comments on a launch, brand or topic and feed scores, text and threads straight into your model.
- **✍️ Content & trend research:** mine top posts in your niche for viral angles, headlines and audience questions worth writing about.

### ❓ FAQ

**How do I scrape a subreddit?** Set `mode` to `subreddit`, enter the `subreddit` name (e.g.
`python`), pick a `sort` and `maxPosts`, then Run. You get every matching post with scores,
flair, images and AI-ready text. Flip on `includeComments` to also pull each post's comments.

**Can I scrape all the comments on a single post?** Use `mode: post`, paste the `postUrl`,
and set `maxComments` (0 removes the requested cap). With `expandMoreComments` on (the default),
the Actor attempts to expand more-comment stubs. A complete thread is not guaranteed.
The cap includes nested replies, while dataset rows and result charges count only posts
and top-level comments. Export JSON to retain the nested `replies` objects.

**Can I search Reddit or scrape a user's posts?** Yes. Use `mode: search` with a `searchQuery`
(optionally limited to one subreddit via `searchSubreddit`), or `mode: user` with a `username`
to pull that account's public post history.

**Do I need an API key?** No. You do not provide a Reddit login, client ID, or secret. The
Actor obtains an anonymous app-only OAuth token internally, then reads public Reddit data.

**Where is my chosen format?** Read `content` and `content_format` on each post,
comment and nested reply. Existing fields retain their original meanings. The word
and token counts describe the original source text, not the selected representation.

**Can I get only recent posts?** Use `sort: top` or `controversial` with a `timeFilter`
(hour/day/week/month/year/all). In subreddit mode, `sinceDate` (`YYYY-MM-DD`) keeps posts
on or after midnight UTC on that date. Old pinned or ranked posts are skipped without
stopping pagination. Invalid calendar dates and `sinceDate` in other modes fail before
scraping. This filter checks the posts Reddit exposes; it does not search a complete archive.

**Can I run it on a schedule or via API?** Yes — schedule recurring runs in Apify, call it via
the API/SDK, or connect it to Make, Zapier or n8n to push fresh Reddit data into your stack.

**Can it scrape private or deleted content?** No. Only public posts and comments are available —
deleted/removed items and private subreddits can't be accessed without authentication.

**How many posts can it return?** Up to your `maxPosts` cap (or unlimited with `0`); it
paginates automatically. For very large jobs, batch with date ranges to keep runs manageable.

**Is scraping Reddit legal?** It extracts publicly available data through Reddit's OAuth
API and paces requests to respect rate limits. Use it responsibly for research and
analysis, and follow applicable laws and Reddit's terms.

**Does this supply a registered app or source approval?** No. If your organization
requires a registered Reddit application or an approved data agreement, confirm that
requirement before adopting the Actor. A successful run does not establish approval
for your intended use.

### 🔗 You might also like

- **[Reddit Archive Scraper](https://apify.com/benthepythondev/reddit-archive-scraper)** — years of historical Reddit posts & comments
- **[Lemmy Scraper](https://apify.com/benthepythondev/lemmy-scraper)** — posts & comments from Lemmy communities
- **[Stock Sentiment Intelligence](https://apify.com/benthepythondev/stock-sentiment-intelligence)** — social sentiment signals for stocks & tickers

***

**Keywords:** reddit scraper, reddit api, scrape reddit, reddit data extraction, reddit comments scraper, subreddit scraper, reddit search api, reddit user scraper, reddit posts, AI training data, LLM training data, sentiment analysis, social media scraping, markdown export, reddit json api, no api key, market research, content research.

# Actor input Schema

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

What to scrape from Reddit

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

Subreddit to scrape (e.g., 'python' or 'r/python'). Required for subreddit mode.

## `postUrl` (type: `string`):

Full URL of Reddit post to scrape (for post mode)

## `username` (type: `string`):

Reddit username to scrape posts from (for user mode)

## `searchQuery` (type: `string`):

Search query to find posts (for search mode)

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

Limit search to specific subreddit (optional for search mode)

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

How to sort posts

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

Time range for top/controversial sort

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

Maximum number of posts to scrape (0 = unlimited)

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

Maximum comments to scrape per post (applies to both post mode and subreddit mode with includeComments, 0 = unlimited)

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

Scrape comments for each post in subreddit mode (slower but more data)

## `expandMoreComments` (type: `boolean`):

When ON (default), resolves Reddit's 'load more comments' stubs via /api/morechildren and follows 'continue this thread' links so the scraped count matches num\_comments. Turn OFF for faster runs that only return the first ~50 comments per post.

## `sinceDate` (type: `string`):

Subreddit mode only: keep posts on or after this UTC date (YYYY-MM-DD). Invalid dates and other modes with this field are rejected.

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

Format returned in content on posts, comments and nested replies. Original text/Markdown/HTML fields remain available. Plain text is extracted from source HTML; original text is retained when HTML is absent.

## `includeImages` (type: `boolean`):

Include extracted image URLs and thumbnails. False returns an empty images array and a null thumbnail; post URLs and links within the original text remain unchanged.

## `delaySeconds` (type: `number`):

Delay between Reddit API requests to respect rate limits

## `debugMode` (type: `boolean`):

Enable detailed logging for debugging

## Actor input object example

```json
{
  "mode": "subreddit",
  "subreddit": "python",
  "postUrl": "https://www.reddit.com/r/python/comments/abc123/example_post/",
  "username": "example_user",
  "searchQuery": "machine learning",
  "searchSubreddit": "python",
  "sort": "hot",
  "timeFilter": "all",
  "maxPosts": 10,
  "maxComments": 50,
  "includeComments": false,
  "expandMoreComments": true,
  "sinceDate": "2025-01-01",
  "outputFormat": "markdown",
  "includeImages": true,
  "delaySeconds": 1,
  "debugMode": false
}
```

# Actor output Schema

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

No description

# 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 = {
    "subreddit": "AskReddit",
    "maxPosts": 10,
    "maxComments": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("benthepythondev/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 = {
    "subreddit": "AskReddit",
    "maxPosts": 10,
    "maxComments": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("benthepythondev/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 '{
  "subreddit": "AskReddit",
  "maxPosts": 10,
  "maxComments": 50
}' |
apify call benthepythondev/reddit-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,benthepythondev/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/lqOcm2Bgsg4LGNATd/builds/2PzOS0bPUq0QRwWEp/openapi.json
