Reddit Scraper - Posts, Comments, Subreddits & Media
Pricing
from $1.00 / 1,000 results
Reddit Scraper - Posts, Comments, Subreddits & Media
Scrape Reddit posts, comments and media from any subreddit or user profile. Search by keyword, sort by hot, new, top or rising, and optionally extract full comment threads and media URLs. Fast, resource-efficient and requires no login or API keys.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
19
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Features
Share
Reddit Scraper: Posts, Comments and Media from Any Subreddit or User
Reddit Scraper turns Reddit into a clean data feed. Point it at any subreddit or any user profile, pull posts sorted by new, hot, top or rising, optionally fetch available comment-thread entries under each post, and collect image and video links, or download the files themselves. Export the results to JSON, CSV or Excel, or read them straight through the API.
Why This Scraper?
- Two targets, one actor. Scrape any public subreddit's listing, or switch to username mode and pull one user's posted history instead.
- Posts with context. Collect post text, author, timestamps, media links and post type together in each post record.
- Comments on demand. Turn on comment scraping to read each post's public comment-thread feed. Reddit currently exposes few or no comment entries in those feeds, so comment output can be empty (disclosed up front, never silently billed).
- Media without extra tooling. Image and video links come straight from the post data, and can optionally be downloaded to storage instead of just linked.
- Reliable connection. Reddit refuses most ordinary datacenter connections, so the actor reads the feeds over Apify's result-unblocking connection, with your own selected connection tried first and a backup connection taking over automatically if it is refused.
- Built for schedules. Resume continues one interrupted pull without re-collecting or re-charging posts it already has, and incremental mode returns only new and changed posts on recurring runs.
- Optional extra work. Comment scraping and media downloads are off by default. Media URLs can be collected without downloading files; recurring monitoring can suppress unchanged posts.
Use Cases
- Market research and brand monitoring: track product mentions and competitor discussion across chosen subreddits.
- Sentiment and NLP research: build labeled text datasets from post titles, self text and comment threads.
- Content curation: collect trending posts and their media for aggregation or a content pipeline.
- Academic and social research: gather subreddit or user activity for longitudinal studies.
- Lead generation: find users discussing a relevant topic or product across a community.
- Recurring monitoring: schedule the actor with incremental mode to track a subreddit or user's new activity without re-collecting what you already have.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
The dataset also ships three ready-made views (Posts Overview, Comments, Media URLs) selectable from the dataset's view tabs.
| Field | Example |
|---|---|
type | "post" (also "comment") |
id | "1hj2abc" |
title | "What's your favorite Python library?" |
author | "pythonista123" |
subreddit | "python" |
created_utc | "2024-12-20T15:30:00" |
permalink | "https://reddit.com/r/python/comments/1hj2abc/..." |
url | "https://reddit.com/r/python/comments/1hj2abc/..." (media link or destination link where the post has one; the post's own address for text posts) |
score | null (not published in the public feeds) |
upvote_ratio | null (not published in the public feeds) |
num_comments | null (not published in the public feeds) |
num_crossposts | null (not published in the public feeds) |
selftext | "I've been exploring different libraries..." (text posts) |
post_type | "text" (also "image", "video", "link") |
is_nsfw | null (not published in the public feeds) |
is_spoiler | null (not published in the public feeds) |
flair | null (not published in the public feeds) |
total_awards | null (not published in the public feeds) |
has_media | false |
media_urls | { "images": [], "videos": [], "galleries": [] } (when Extract Media URLs is on) |
media_downloaded | true (when Download Media Files is on) |
changeType | "NEW" (incremental mode only) |
changedFields | [] (incremental mode only) |
firstSeenAt / lastSeenAt | "2026-07-30T03:00:00Z" (incremental mode only) |
Reddit publishes scores, vote ratios, comment counts, flair and NSFW/spoiler flags only through interfaces that are closed to unauthenticated readers, so those fields are null in every row rather than a fabricated zero. Everything else (titles, authors, text, timestamps, permalinks, media links) is complete.
Comment records use a separate shape carried under type: "comment": comment_id, post_permalink, post_title, parent_id, author, body, score, created_utc, depth (entries in the public thread feed are flat, so depth is always 0) and is_submitter. Reddit's public comment feeds currently expose few or no entries, so comment output can be empty; comments never carry changeType or the other incremental fields, and incremental mode only classifies posts.
How to Use
- Enter a target: a subreddit name (e.g.
python) or, with Is Username on, a Reddit username. - Set Post Limit and Sort By (
new,hot,toporrising); pick a Timeframe if sorting bytop. - Turn on Scrape Comments and/or Extract Media URLs (and Download Media Files) for the extra data you need.
- Click Start. Results are saved to the dataset as they are scraped.
Subreddit, hot posts with media URLs and no comments:
{"target": "python","limit": 100,"sort": "hot","scrapeComments": false,"extractMediaUrls": true}
User profile, latest submitted posts:
{"target": "spez","isUser": true,"limit": 50}
Recurring subreddit monitor with incremental mode:
{"target": "askreddit","limit": 200,"sort": "new","incrementalMode": true,"emitExpired": true}
Continue an interrupted large pull:
{"target": "python","limit": 1000,"sort": "new","resumeFromRunId": "abCdEfGhIjKlMnOpQ"}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/reddit-scraper").call(run_input={"target": "python", "limit": 50, "sort": "hot"})for post in client.dataset(run["defaultDatasetId"]).iterate_items():if post.get("type") == "post":print(post["title"], post["score"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/reddit-scraper').call({ target: 'python', limit: 50, sort: 'hot' });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Resume and recurring updates
Two different features, both opt-in:
- Resume (
resumeFromRunId) continues one specific interrupted run: paste its run or dataset ID and this run skips posts it already collected there, so you don't pay twice. - Incremental mode (
incrementalMode) is for scheduling this actor on the same subreddit or user, sort and timeframe again and again. State is kept separately per target, sort, timeframe and media-toggle combination, or under one name you choose withstateKey. Each post is classifiedNEW,UPDATED(withchangedFields),UNCHANGED,REAPPEAREDorEXPIRED.NEWandUPDATEDare always returned.UNCHANGEDis suppressed (not returned or billed) unlessemitUnchangedis on.EXPIREDis only produced whenemitExpiredis on and the run scanned the whole listing to its natural end, which a Post Limit cap orresumeFromRunIdprevents; without that, previous state is left untouched.REAPPEAREDcan therefore only happen for a post that a pastemitExpiredrun already tombstoned asEXPIREDand that later shows up again; turningemitExpiredon is what makesREAPPEAREDpossible at all. With incremental mode off, output is exactly as before. - A vote or a new comment alone never marks a post
UPDATED. Score, upvote ratio and comment count drift on their own within minutes, and together with the other fields the public feeds do not publish they are excluded from change detection;UPDATEDmeans the title, text, URL, type or media actually changed. The first run after the November 2026 update may classify existing tracked postsUPDATEDonce while baselines adjust to the change in field availability, then suppress normally again.
Caps and media limits
Post Limit stops a run after that many posts are scanned (a suppressed UNCHANGED post still counts against it). Comments Per Post caps the comments returned per post; Reddit's public comment feeds currently expose few or no entries, so comment output can be empty. Comment rows are additional to Post Limit. When Download Media Files is on, downloads are capped per post: up to 5 images, up to 10 gallery items and up to 2 videos (YouTube links are kept as URLs only, never downloaded).
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
target | string | none (example: python) | Subreddit name or username (required). |
isUser | boolean | false | Set true if target is a username instead of a subreddit. |
limit | integer | 10 | Maximum posts to scrape, up to 1000. |
sort | string | new | new, hot, top, or rising. Applies to subreddit listings; username mode returns the user's submitted posts in Reddit's own order. |
timeframe | string | all | Time filter used with top sort: hour, day, week, month, year, all. |
scrapeComments | boolean | false | Read each post's public comment-thread feed; each returned comment is a separate billable result row. Reddit currently exposes few or no entries there, so comment output can be empty. |
commentsLimit | integer | 100 | Maximum comments returned per post, up to 500. Reddit's public comment feeds currently expose few or no entries, so the returned count can be lower. |
extractMediaUrls | boolean | true | Extract image, video and gallery URLs from posts. |
downloadMedia | boolean | false | Download media files to the Key-Value Store; requires extractMediaUrls: true and adds transfer/storage work. |
proxy | object | Apify Proxy, result-unblocking connection group | Connection settings. Reddit serves its public post feeds only through Apify's result-unblocking connection group, which the actor selects by default; a backup connection takes over automatically if your selected connection is refused. |
resumeFromRunId | string | none | Continue one specific interrupted run without re-collecting or re-charging its posts. |
incrementalMode | boolean | false | Turn on for recurring monitoring: classify each post as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED against the previous run. |
stateKey | string | none | Name a monitoring campaign explicitly; otherwise the state key is derived automatically from target, sort, timeframe and media toggles. |
emitUnchanged | boolean | false | Also return (and bill) UNCHANGED posts every run. |
emitExpired | boolean | false | Also return (and bill) posts no longer found, once a run fully scans the listing. |
mcpConnectors | array | none | Optional: send a summary of each record to apps you authorized under Integrations. |
notionParentPageUrl | string | none | Notion connector only: page under which item pages are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. Does not affect the dataset. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
Example post record:
{"type": "post","id": "1hj2abc","title": "What's your favorite Python library?","author": "pythonista123","subreddit": "python","created_utc": "2024-12-20T15:30:00","permalink": "https://reddit.com/r/python/comments/1hj2abc/","url": "https://reddit.com/r/python/comments/1hj2abc/","score": null,"upvote_ratio": null,"num_comments": null,"num_crossposts": null,"selftext": "I've been exploring different libraries and wanted to hear what everyone's using...","post_type": "text","is_nsfw": null,"is_spoiler": null,"flair": null,"total_awards": null,"has_media": false,"media_urls": {"images": [],"videos": [],"galleries": []}}
Plan Requirement
Check the Pricing tab for current actor charges and your Apify plan for available connection resources. Choose limits and optional data appropriate to your workload.
FAQ
How much does it cost?
The Pricing tab shows the current actor-start charge and per-result rate. Each post and each comment returned is a result. Post Limit caps scanned posts, not comment rows or total charges. Connection usage and downloaded files can add transfer and storage costs.
For a lower-workload starting point, keep Scrape Comments and Download Media Files off, keep Extract Media URLs on if you need media links, and choose a Post Limit that covers your needs. For recurring monitoring, enable incremental mode and leave Emit unchanged and Emit expired off unless you need those rows. Incremental mode still scans the source and still fetches comments when enabled; it reduces post output, rather than eliminating request work or the actor-start charge.
Is it legal to scrape Reddit?
This actor collects publicly available posts and comments. Follow Reddit's terms, applicable privacy laws and regulations, and use a lawful basis when processing personal data. Obtain legal advice for your intended use where needed.
Can I get only new or changed posts on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental changes for scheduled runs. Later runs then return only NEW and UPDATED posts by default, and unchanged posts are not returned or billed unless you turn on Emit unchanged. When Scrape Comments is enabled, comments can still be fetched and returned as separate billable rows for an unchanged post.
What's the difference between Resume and Incremental mode?
Resume (resumeFromRunId) continues one specific interrupted run from a pasted run or dataset ID, so a large one-off pull can finish without starting over. Incremental mode is for scheduling the actor repeatedly against the same subreddit or user, sort and timeframe, so each run returns only what's new or changed since the last one. They solve different problems and can be combined for a first bootstrap run.
Why did my run fail instead of returning an empty dataset?
This actor fails the run for a configuration problem (a missing target, a resumeFromRunId that doesn't resolve to a run or dataset you own, or turning on incremental mode with resumeFromRunId while that state key already has saved history) or an unexpected internal error. If Reddit itself refuses requests during the scrape, the run still finishes and simply returns fewer posts, or none, rather than failing; try again in a few minutes, and keep the default connection selection (see the Connection input), which reads the feeds over the connection Reddit serves.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
🔗 Want more social media data?
Pair this actor with these related scrapers from the same team:
| 📱 Lemon8 Feed Scraper Scrape Lemon8 feeds across 22 categories and 10+ regions. Extract posts, images, videos... | 📱 Lemon8 Search Scraper Scrape Lemon8 posts by keyword across multiple regions. Extract posts, images, videos... |
| 📱 Lemon8 Profile Scraper Scrape Lemon8 user profiles with automated multi-profile discovery. Extract profile data... | 📱 Lemon8 Media Scraper Lightweight Lemon8 scraper for extracting image and video URLs from posts, with optional... |
| 🧩 Pikabu Scraper Scrape Pikabu (Пикабу): keyword search, hot/new/best feeds, communities, tags, full story... | 📱 Mastodon Scraper Scrape trending Mastodon profiles and related posts from any Mastodon instance. Extract... |
💬 Support
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email contact@abotapi.com.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.