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

Scrape Reddit posts and comments without an API key or login: subreddit listings (new, hot, top, rising), searches site-wide or inside one subreddit, and single posts with their comment tree. Score, flair, links, media, dates. Only-new mode for monitoring.

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

## Pricing

from $1.05 / 1,000 post or comments

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?

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: posts and comments from any subreddit, search or post link

Scrape **Reddit** without an API key, an app registration or a Reddit account. Read the posts of any public subreddit (new, hot, top or rising), search all of Reddit or one subreddit, or open single posts, and get clean structured data: title, text, score, upvote ratio, comment count, flair, author name, links, image and video URLs and exact timestamps. Turn on **Include comments** to get the comment tree of every post as separate records, down to depth 10 (deeper branches are skipped), with the depth of each reply and the id of its parent.

Run it on a schedule with **Only new items** turned on and you get just the posts and comments that appeared since your last run.

**Pay per result** · **No login, no API key** · **Public data only** · **LLM-ready JSON for AI agents (MCP)**

### 🛠️ What does Reddit Scraper do?

- 📰 **Subreddit posts.** New, hot, top (with a time range) or rising, for one subreddit or several at once. Join subreddits with a plus sign (`python+learnpython`) to read them as one feed.
- 🔎 **Search.** Search all of Reddit or only inside one subreddit, sorted by relevance, new, top, hot or most comments, with a time range.
- 🔗 **Single posts.** Paste post links and get the post, and its comments if you want them.
- 💬 **Comment trees.** Every comment is its own record with `postId`, `parentId` and `depth`, in thread order, down to depth 10 (deeper branches are skipped).
- 🆕 **Only new items mode.** Schedule it and get just what was not returned before.
- 🔒 **No user profile data.** Only the public username shown next to a post or comment is saved. Profiles, karma and posting history are never collected.
- 🛡️ **Built to get through blocking.** Requests go out with a real browser fingerprint through rotating proxies, and a blocked request is retried from a fresh IP. A result that could not be completed is never charged.

#### What people use it for

- **Market and product research.** See what people ask, complain about and recommend in the subreddits of your market.
- **Brand and keyword monitoring.** Schedule a search for your brand or product name with "Only new items" and send new mentions to Slack, Google Sheets or your CRM.
- **Trend and topic analysis.** Collect top posts of a period and compare score, comment counts and flairs across communities.
- **Datasets for AI and NLP.** Build text datasets of questions, answers and discussions with timestamps, scores and thread structure.
- **Lead and idea discovery.** Find posts where people look for a tool, a service or a solution like yours.

### 📊 What data can you extract?

Every result is one JSON object (one row in CSV or Excel). The `type` field says whether it is a `post` or a `comment`.

**Post fields**

| Field | Meaning |
|---|---|
| `type`, `id`, `url` | `post`, Reddit's post id and the link to the post |
| `subreddit`, `title` | The community and the post title |
| `text` | The post body as Reddit markdown, `null` for link and image posts without text. For a crosspost it is the body of the original post |
| `createdAt` | When the post was created (UTC) |
| `score`, `upvoteRatio`, `numComments` | Net score, share of upvotes (0 to 1) and number of comments |
| `flair` | The post flair, if it has one |
| `isNsfw`, `isSpoiler`, `isStickied`, `isVideo` | Post flags |
| `linkUrl`, `domain` | The outside link of a link post as a full address and its domain (`self.<subreddit>` for text posts) |
| `thumbnailUrl`, `imageUrls`, `videoUrl` | Thumbnail, image links (single image or whole gallery) and the Reddit-hosted video link. For a crosspost they come from the original post |
| `isCrosspost`, `crosspostParentId`, `crosspostParentSubreddit` | Whether the post is a crosspost, and the id and subreddit of the original post |
| `author` | The public username of the poster (`[deleted]` for deleted accounts) |
| `searchQuery` | The search that found the post, `null` for subreddit listings and post links |
| `scrapedAt` | When the record was collected (UTC) |

**Comment fields** (with **Include comments**)

| Field | Meaning |
|---|---|
| `type`, `id`, `url` | `comment`, Reddit's comment id and the link to the comment |
| `postId`, `parentId`, `depth` | The post it belongs to, the post or comment it replies to, and its depth (0 for top-level comments) |
| `text` | The comment as Reddit markdown |
| `createdAt`, `score` | When it was written (UTC) and its score (`null` while Reddit hides the score of new comments) |
| `isSubmitter` | `true` when the author of the post wrote it |
| `author`, `subreddit` | The public username and the community |
| `scrapedAt` | When the record was collected (UTC) |

A field that does not exist for a record is `null`.

### 🚀 How to use Reddit Scraper

1. Create a free [Apify](https://apify.com) account and open this Actor.
2. Add **subreddits** (`python`, `r/AskReddit` or a link), **search queries**, **post links**, or any mix of the three.
3. For subreddits, pick the **sort order** (and a **time range** for Top). For searches, pick the **search sort** and, if you like, a subreddit to search in.
4. Set **max posts per subreddit or search**.
5. Turn on **Include comments** and set **max comments per post** if you need the discussions.
6. Run it and download the results as JSON, CSV or Excel, or read them through the API.

### 📥 Input example (JSON)

```json
{
  "subreddits": ["python", "learnpython"],
  "sort": "top",
  "timeFilter": "week",
  "searchQueries": ["web scraping"],
  "searchInSubreddit": "",
  "includeNsfw": false,
  "searchSort": "new",
  "postUrls": ["https://www.reddit.com/r/Python/comments/1wu3r86/suggesting_ppl_to_go_from_unmaintainted_library_x/"],
  "includeComments": true,
  "maxCommentsPerPost": 50,
  "maxItemsPerQuery": 100,
  "onlyNew": false
}
```

### 📤 Sample output (JSON)

![Sample output table of Reddit Scraper](https://api.apify.com/v2/key-value-stores/GkJnrNz6YWKHQYnZr/records/reddit-scraper-output.png)

A post:

```json
{
  "type": "post",
  "id": "1ww2uny",
  "url": "https://www.reddit.com/r/Python/comments/1ww2uny/tuba_python_cli_pyside6_gui_for_ytdlpffmpeg_video/",
  "subreddit": "Python",
  "title": "Tuba: Python CLI & PySide6 GUI for yt-dlp/FFmpeg video processing",
  "text": "Hi r/Python!\n\nI wanted to share \\*\\*Tuba\\*\\*, an open-source Python tool I built for downloading, trimming, and re-encoding videos from YouTube and Instagram.\n\n👉 \\*\\*GitLab Repository\\*\\*: [https://gitlab.com/bdemircan/tuba](https://gitlab.com/bdemircan/tuba)\n\nThe core motivation was to build a clea...",
  "createdAt": "2026-10-02T19:29:05+00:00",
  "score": 1,
  "upvoteRatio": 0.67,
  "numComments": 2,
  "flair": "News",
  "isNsfw": false,
  "isSpoiler": false,
  "isStickied": false,
  "isVideo": false,
  "linkUrl": null,
  "domain": "self.Python",
  "thumbnailUrl": null,
  "imageUrls": null,
  "videoUrl": null,
  "isCrosspost": false,
  "crosspostParentId": null,
  "crosspostParentSubreddit": null,
  "author": "ozzyburak",
  "searchQuery": null,
  "scrapedAt": "2026-10-02T20:47:46+00:00"
}
```

A comment:

```json
{
  "type": "comment",
  "id": "pdh4aww",
  "postId": "1ww2uny",
  "parentId": "1ww2uny",
  "depth": 0,
  "text": "Cool tool, I been messing with yt-dlp scripts lately and the dual interface thing is smart, most of these projects just pick one or the other\n\n  \nThe stream-copy default is nice touch, ffmpeg re-encod...",
  "createdAt": "2026-10-02T19:38:22+00:00",
  "score": 1,
  "isSubmitter": false,
  "author": "Aggravating-Line2390",
  "subreddit": "Python",
  "url": "https://www.reddit.com/r/Python/comments/1ww2uny/tuba_python_cli_pyside6_gui_for_ytdlpffmpeg_video/pdh4aww/",
  "scrapedAt": "2026-10-02T20:47:47+00:00"
}
```

### 🤖 Use it with AI agents, MCP and the API

The output is clean JSON with stable field names, ready for LLM pipelines, RAG and agent tools without extra parsing.

- **AI agents and MCP (Claude, ChatGPT, Cursor and others).** Add the Apify MCP server with this Actor as a tool: `https://mcp.apify.com?tools=akatra/reddit-scraper`. The agent can then run it and read the results by itself.
- **API.** Start a run and get the results in a single call:

```bash
curl -X POST "https://api.apify.com/v2/acts/akatra~reddit-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"subreddits": ["python"], "sort": "new", "maxItemsPerQuery": 50, "includeComments": true, "maxCommentsPerPost": 20}'
```

- **No-code tools and SDKs.** Works with Make, n8n, Zapier and LangChain through Apify's integrations, and with the Apify clients for Python and JavaScript. Schedule it and send the results to a webhook, Google Sheets or your own database.

### 💰 Pricing: pay per result

You pay per result: every post and every comment saved to the dataset is one result. See the price on the Pricing tab. Runs that return nothing cost only a tiny start fee. There is no subscription or rental fee. New to Apify? The free plan includes $5 of platform credit every month, enough for about 3,300 posts or comments with this Actor, and no credit card is needed.

### 🚦 Run status and error messages

Every run ends with a plain status message, so automated workflows (API, Make, n8n, AI agents) can tell what happened without reading the log:

| Situation | What you get |
|---|---|
| Finished normally | `Saved N posts and M comments.` |
| Nothing matched | The run succeeds with `No results saved. Check the spelling of the subreddit, try another sort or time range, or turn off 'Only new items'.` You pay only the start fee. |
| Missing or invalid input | The run fails at once with `Invalid input: …` naming the field to fix, for example a search by username (`author:`, `user:`, `u/`). Nothing is scraped. |
| Private, quarantined or restricted subreddit | `r/name is private or restricted (reason).` The other sources are still read. |
| Subreddit does not exist or is banned | `r/name was not found (it may not exist or may be banned).` |
| Post link not available | `Post abc123 is not available (it may be deleted, removed or private).` |
| Search inside an 18+ community without the 18+ option | `r/name is an 18+ community, so Reddit hides its posts from searches; turn on includeNsfw to search it.` |
| Reddit blocked every request | The run succeeds with `Reddit blocked the requests for …, so nothing was saved. You were not charged. Please try again later.` |
| Some pages or comments stayed blocked | `Results may be incomplete for: …` naming the source. Run again to get the rest. |
| Comments of some posts could not be loaded | `Skipped N posts whose comments could not be loaded (not charged).` |
| Your maximum charge is reached | Stops cleanly with `Stopped at your maximum charge limit.` Everything saved so far stays in the dataset. |

### ℹ️ Good to know

- **Max posts per subreddit or search** applies to each subreddit and each search query. Reddit ends a listing after about 1000 posts for New and Hot, and earlier for Top and for searches (about 500 and 250 in our tests), so higher numbers return what Reddit gives. Comments are limited separately, per post.
- **Time range** applies to the Top listing and to searches. New, hot and rising ignore it.
- Searches return what Reddit's own search returns for the same words, sort and time range. Reddit matches the words in titles, post texts and communities, so a result does not always have the exact phrase in its title.
- Comments come in thread order, a comment followed by its replies, and **Max comments per post** counts in that order. Replies nested deeper than 10 levels are skipped. Deleted and removed comments are skipped and not charged. The comment `text` and the post `text` are Reddit markdown as the author wrote it.
- A post that several of your sources would return (for example a subreddit and a search) is returned once per run, with its comments.
- With **Include comments**, a post whose comments cannot be loaded is skipped and not charged; the status message tells you how many.
- **Only new items** remembers each source (subreddit and sort, search, or post link) between runs. The first run returns everything up to your limits. Later runs return only posts and comments that were not returned before and were created since 15 minutes before the previous run started; older items that were never returned (for example because of your limit) stay out. In a subreddit or search, new posts come with their comments and the comments of posts returned in earlier runs are not fetched again. With a post link you also get the comments written since the last run.
- Searches leave out 18+ posts, as Reddit does by default. Turn on **Include 18+ posts** (`includeNsfw`) to get them, and to search inside an 18+ community (without it the run tells you). Subreddit listings and post links return 18+ posts as they are, with `isNsfw: true`.
- A crosspost keeps its own title, score, comment count, author and link, but its text, outside link, domain, images and video are filled in from the original post.
- Searching by username is not supported: queries with `author:`, `user:` or `u/` are rejected.
- **How it reads Reddit:** the Actor does not use Reddit's official API. It reads the public pages Reddit shows to any visitor who is not logged in, with an anonymous visitor session, through residential IPs. Reddit's robots.txt disallows automated access, and Reddit can change or close this way of reading without notice. If that happens the run ends with a status message that Reddit blocked the requests, and you are not charged.
- If you set a maximum charge for a run, the scraper stops as soon as that limit is reached.
- **Privacy:** only content and the public username shown next to it are collected. User profiles, karma, account age and posting history are never read, and there is no search by username.

### 📝 Changelog

- **2026-10-02** First release: subreddit listings, search, post links, comment trees and only-new mode.

### ⚖️ Legal and privacy

This scraper is an independent tool and is not affiliated with, endorsed by, or sponsored by Reddit. Reddit and its logo are trademarks of their owner and are used here only to describe which website the tool works with. Reddit's robots.txt disallows automated access and Reddit's terms of use restrict it; the Actor is not an official Reddit tool and does not use Reddit's API. Your use of the data is subject to Reddit's terms and to the laws that apply to you.

The Actor reads only pages that are public without logging in. Posts and comments are written by Reddit users under pseudonyms and can contain personal information their authors chose to publish. How you store and use the data is your responsibility: follow the laws that apply to you, such as GDPR and CCPA.

### 🔗 More scrapers from Akatra

- [Indeed Jobs Scraper](https://apify.com/akatra/indeed-jobs-scraper): 💼 job ads from Indeed in 30 countries, with yearly salary and only-new mode.
- [Google News Scraper](https://apify.com/akatra/google-news-scraper): 📰 news by keyword or topic in 50 editions, with the real article URLs.
- [Google Trends Scraper](https://apify.com/akatra/google-trends-scraper): 📈 interest over time, by region, and rising related queries.
- [Google Ads Transparency Scraper](https://apify.com/akatra/google-ads-transparency-scraper): 🔎 every ad a company runs on Google, with regions and dates.
- [Airbnb Listings Scraper](https://apify.com/akatra/airbnb-listings-scraper): 🏠 Airbnb listings with prices, ratings and map coordinates.
- [YouTube Transcript Scraper](https://apify.com/akatra/youtube-transcript-scraper): 🎬 video transcripts as clean text and timestamped lines.

### 💬 Support

Found a bug or need a field that is missing? Open an issue on the Issues tab and we usually reply within a day.

# Actor input Schema

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

Communities to read, one per line: a name (python), r/python or a link (https://www.reddit.com/r/python/). Join several with a plus sign (python+learnpython) to read them as one feed. Private, quarantined and banned communities cannot be read.

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

Which listing of each subreddit to read.

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

Applies to the Top listing and to searches: only posts from this period. Ignored for New, Hot and Rising.

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

Words or phrases to search for, one per line. Each line is a separate search across all of Reddit, or inside one subreddit if you set it below. Searching by username (author:, user:, u/) is not supported.

## `searchInSubreddit` (type: `string`):

Optional. A subreddit name or link; the searches above then look only inside it. Leave empty to search all of Reddit.

## `searchSort` (type: `string`):

Order of the search results.

## `includeNsfw` (type: `boolean`):

Reddit leaves 18+ posts out of search results unless asked. Turn this on to include them, and to search inside an 18+ community. Subreddit listings and post links always return 18+ posts as they are, flagged with isNsfw.

## `postUrls` (type: `array`):

Single posts to read, one link per line (https://www.reddit.com/r/python/comments/abc123/title/ or https://redd.it/abc123). Add comments with the option below.

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

Also save the comments of every post, one record per comment, down to depth 10 (deeper branches are skipped). Needs one or more extra requests per post, so runs take longer. Every comment counts as a result.

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

Stop after this many comments for each post. Comments come in thread order: a comment, then its replies, and the limit counts in that order. Deleted and removed comments are skipped.

## `maxItemsPerQuery` (type: `integer`):

Stop after this many posts for each subreddit and each search query. Reddit ends a listing after about 1000 posts (earlier for Top and searches). Comments are limited separately.

## `onlyNew` (type: `boolean`):

Remember the posts and comments of previous runs of the same source and return only items not seen before and created since 15 minutes before the previous run started. Made for scheduled runs.

## Actor input object example

```json
{
  "subreddits": [
    "python"
  ],
  "sort": "new",
  "timeFilter": "week",
  "searchSort": "relevance",
  "includeNsfw": false,
  "includeComments": false,
  "maxCommentsPerPost": 50,
  "maxItemsPerQuery": 100,
  "onlyNew": false
}
```

# Actor output Schema

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

All scraped posts and comments, shown in the overview table.

## `resultsFull` (type: `string`):

All scraped posts and comments with every field.

# 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": [
        "python"
    ]
};

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

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

```

## MCP server setup

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