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

Scrape Reddit posts and comments from any subreddit or search query. Score, upvote ratio, author, flair, awards and full comment threads, with filters for score, date and keywords.

- **URL**: https://apify.com/juanoox/reddit-scraper.md
- **Developed by:** [Juan ignacio Veltri](https://apify.com/juanoox) (community)
- **Categories:** Social media, News, Automation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

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

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 and comment threads from any subreddit or search

Scrape posts from any subreddit or search query, with score, upvote ratio, flair, awards, author and
— optionally — the full comment thread, nested replies included.

Reddit answers JSON on any of its URLs, so this Actor reads its data feed rather than its HTML.
Nothing here depends on markup, which means a Reddit redesign does not break your integration.

***

### Quick start

Everything hot in a subreddit:

```json
{ "subreddits": ["programming"], "sort": "hot" }
```

The best of the week across several communities, only substantial posts:

```json
{
  "subreddits": ["argentina", "devops", "r/webdev"],
  "sort": "top",
  "time": "week",
  "minScore": 50,
  "minComments": 10
}
```

Search all of Reddit, or inside one community:

```json
{
  "searchQueries": ["web scraping", "r/programming: rust vs go"],
  "sort": "top",
  "time": "month"
}
```

Write `r/subreddit: your keywords` to restrict a query to one community.

#### Posts *and* their discussions

```json
{
  "subreddits": ["askprogramming"],
  "maxCommentsPerPost": 50,
  "minComments": 5
}
```

Comments arrive nested inside each post, with `depth` (0 is a reply to the post, 1 a reply to a
comment) and `isOriginalPoster` so you can follow a thread.

**Each post with comments costs one extra request**, so `maxCommentsPerPost: 0` — the default —
keeps a run cheap. Filters are applied **before** those requests: a strict `minScore` makes the run
cheaper, not more expensive.

***

### Monitoring a subreddit

Turn `includeSeen` off and schedule it. Each run then returns only posts it has not returned before:

```json
{ "subreddits": ["startups"], "sort": "new", "includeSeen": false }
```

Use a Schedule so the runs share storage — that is what lets the Actor remember what it already sent
you.

***

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `subreddits` | array | `["programming"]` | Name, `r/name`, or full URL |
| `searchQueries` | array | — | Keywords. `r/sub: terms` restricts to one community |
| `sort` | select | `hot` | `hot`, `new`, `top`, `rising`, `controversial` |
| `time` | select | `week` | Window for Top, Controversial and searches |
| `maxPostsPerSource` | integer | `0` | Cap per subreddit or query. `0` = no cap |
| `maxCommentsPerPost` | integer | `0` | Comments per post. `0` = do not fetch them |
| `minScore` / `minComments` | integer | — | Drop posts below these |
| `keywords` | array | — | Only posts mentioning any of these |
| `postedWithinDays` | integer | — | Only posts newer than N days |
| `onlyTextPosts` | boolean | `false` | Drop link posts |
| `excludeNsfw` | boolean | `false` | Drop posts marked over 18 |
| `excludePinned` | boolean | `true` | Drop moderator-pinned posts, usually subreddit rules |
| `maxItems` | integer | `500` | Total cap. `0` = no cap |
| `includeSeen` | boolean | `true` | Off = only posts not seen in previous runs |

***

### Output

```json
{
  "id": "reddit:1tlh5aj",
  "url": "https://www.reddit.com/r/programming/comments/1tlh5aj/...",
  "platform": "reddit",
  "community": "programming",
  "title": "Announcement: We've Updated The Rules",
  "text": "After temporarily banning LLM-related content over April...",
  "author": "ChemicalRascal",
  "authorUrl": "https://www.reddit.com/user/ChemicalRascal",
  "score": 950,
  "upvoteRatio": 0.94,
  "commentsCount": 181,
  "publishedAt": "2026-05-23T09:54:37.000Z",
  "flair": null,
  "isNsfw": false,
  "isPinned": true,
  "linkUrl": null,
  "linkDomain": null,
  "awardsCount": 0,
  "comments": []
}
```

A few deliberate choices:

- **`linkUrl` is `null` on text posts.** Reddit fills its `url` field with the post's own permalink
  when there is nothing linked, and copying that would fill the column with noise. `linkUrl` is only
  set when the post actually points somewhere else.
- **`thumbnail` is `null` unless there is a real image.** Reddit puts the strings `self`, `default`
  or `nsfw` there otherwise.
- **`author` is `null` for deleted accounts**, not the literal `[deleted]`.

***

### Notes and limits

- **Reddit caps every listing at roughly 1000 posts.** To go further back, change `sort` or `time`
  rather than paginating — the Actor stops when Reddit stops returning a cursor.
- **Private and banned subreddits are reported, not retried.** Reddit answers with a reason instead
  of a listing, and the run logs which subreddit and why, then continues with the rest.
- Posts with no date are dropped by `postedWithinDays`, because claiming they are recent would
  misreport the filter you asked for.

***

### Pricing

Pay per result. You are charged for posts that actually land in your dataset — filtered out and
duplicate rows cost nothing.

# Actor input Schema

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

Subreddits to scrape. Accepts a bare name (programming), r/programming, or the full URL.

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

Keywords to search across Reddit. To search inside one community, write it as r/subreddit: your keywords.

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

Order in which Reddit returns posts. In a search, 'hot' maps to relevance.

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

Only applies to Top and Controversial, and to searches.

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

Cap for each source, so one busy subreddit can't eat the whole run. 0 = no cap.

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

Fetch this many comments for each post, nested replies included. Each post costs one extra request, so 0 keeps the run cheap.

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

Drop posts below this score. Leave empty for no filter.

## `minComments` (type: `integer`):

Drop posts with fewer comments than this.

## `keywords` (type: `array`):

Only posts mentioning any of these, in the title or the body. Ignores case and accents.

## `postedWithinDays` (type: `integer`):

Only posts newer than this many days. Posts with no date are dropped.

## `onlyTextPosts` (type: `boolean`):

Drop posts that are just a link to somewhere else.

## `excludeNsfw` (type: `boolean`):

Drop posts marked as over 18.

## `excludePinned` (type: `boolean`):

Drop posts pinned by moderators, which are usually the subreddit rules rather than content.

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

Total cap for the run, across every subreddit and query. 0 = no cap.

## `includeSeen` (type: `boolean`):

Turn it off to skip posts returned by previous runs. Schedule it this way to monitor a subreddit for new posts only.

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

Parallel requests.

## `maxRequestsPerMinute` (type: `integer`):

Rate ceiling.

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

How many times to retry a failed request before dropping it.

## Actor input object example

```json
{
  "subreddits": [
    "programming"
  ],
  "searchQueries": [],
  "sort": "hot",
  "time": "week",
  "maxPostsPerSource": 0,
  "maxCommentsPerPost": 0,
  "onlyTextPosts": false,
  "excludeNsfw": false,
  "excludePinned": true,
  "maxItems": 500,
  "includeSeen": true,
  "maxConcurrency": 3,
  "maxRequestsPerMinute": 60,
  "maxRequestRetries": 3
}
```

# Actor output Schema

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

No description

## `runSummary` (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 = {
    "subreddits": [
        "programming"
    ],
    "searchQueries": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("juanoox/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"],
    "searchQueries": [],
}

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

```

## MCP server setup

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