Reddit Scraper — Posts, Comments, Search, Subreddit Monitoring avatar

Reddit Scraper — Posts, Comments, Search, Subreddit Monitoring

Pricing

from $2.00 / 1,000 posts

Go to Apify Store
Reddit Scraper — Posts, Comments, Search, Subreddit Monitoring

Reddit Scraper — Posts, Comments, Search, Subreddit Monitoring

Subreddit listings, keyword search and full comment trees, no login and no proxy to configure. Posts with full text, score, flair and media; comments with depth and parent. Schedule it with onlyNew to get just what appeared since the last run. Pay per row, no start fee.

Pricing

from $2.00 / 1,000 posts

Rating

0.0

(0)

Developer

Moxlade

Moxlade

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

2 days ago

Last modified

Share

Subreddit listings, keyword search and full comment trees — no Reddit login, no proxy to set up, no start fee. Give it subreddits, search queries or post URLs and get posts with their full text, score, upvote ratio, flair and media, and comments with author, score, depth and parent. Turn on onlyNew and schedule it: each run returns only what appeared since the last one, and a run with nothing new costs nothing. Pay per delivered row — $2.00 per 1,000 posts, $1.00 per 1,000 comments.

What you get

  • Three ways in, one row shape. subreddits walks a listing by new, hot, top (with a time range) or rising; searches runs Reddit's own post search, sitewide or inside each subreddit you name; postUrls fetches specific posts. Every row is the same 27 typed fields, kind = post or comment, found_by says which input produced it.
  • Full text on every post, not a preview. Listing posts carry the complete body as Reddit renders it (body_text with paragraph breaks, body_html with links), the score, upvote ratio, comment count, flair, type, media URLs, language, stickied/locked flags. Search hits are filled with author and body (fetchBodies, on by default).
  • Comment trees with structure. includeComments delivers each post's comments right after it — depth, parent_id, post_id, author, score, permalink — in Reddit's Best/Top/New/… order, deep branches expanded up to maxCommentsPerPost.
  • Monitoring that remembers. onlyNew keeps the ids it delivered in a named store and, on a chronological walk, the newest post it delivered per source; the next run stops at that point. Schedule a task and each run is the delta — the same lever as postedSince (12h, 7d, 2w, a date) for a one-off window.
  • Nothing to configure, nothing to babysit. No cookies, no account, no proxy field. Reddit is read from a maintained residential exit that rotates on any wall and waits out the rate limit; a page that fails is retried before the run is failed, and the failure reason is in the status message.
  • Measured, not promised. The acceptance suite runs the deployed build before every release. On the release runs: 25 listing rows with score, ratio, counts, type, flags and language on 25 of 25; 20 search rows with author and body on 20 of 20; a thread of 40 comments with a resolved parent on 22 of 22 nested comments; the second monitoring run at 0 rows and $0.00.

Who it's for

  • Community and brand monitoring — watch the subreddits and keywords that matter, on a schedule, and get only the new posts — with the text, not a link to click.
  • Research and content teams — pull a subreddit's top posts of the month with their comment trees, or every post matching a query since a date, into one typed dataset.
  • Product and lead-gen builders — a stable id (id), permalink, created_utc and found_by on every row, so deduplication, joins and incremental pulls are one line each.
  • Data pipelines and AI agents — one call, JSON rows with full text and structure, no browser and no login to keep alive.

Quick start

Newest posts in a subreddit

{
"subreddits": [
"Upwork"
],
"sort": "new",
"maxItems": 50
}

Top posts of the month with their comments

{
"subreddits": [
"ClaudeCode"
],
"sort": "top",
"time": "month",
"includeComments": true,
"maxCommentsPerPost": 50,
"maxItems": 25
}

Search a topic across Reddit since a date

{
"searches": [
"claude code"
],
"searchSort": "new",
"postedSince": "7d",
"maxItems": 100
}

Search inside chosen subreddits

{
"subreddits": [
"ClaudeCode",
"ChatGPTCoding"
],
"searches": [
"hooks",
"mcp server"
],
"maxItems": 100
}

Specific posts with every comment

{
"postUrls": [
"https://www.reddit.com/r/Upwork/comments/1wd745i/here_are_my_tips_for_upwork_newcomers/"
],
"includeComments": true,
"maxCommentsPerPost": 500
}

Monitor: only what is new since the last run

{
"subreddits": [
"Upwork",
"freelance"
],
"sort": "new",
"onlyNew": true,
"maxItems": 200
}

Output

One row per post or comment (kind says which):

fieldmeaning
kindpost or comment.
idReddit's own id: t3_… for a post, t1_… for a comment. Stable; deduplicate and join on it.
subredditSubreddit name without the r/.
titlePost title. Null on comment rows.
authorUsername without the u/. Null when the account is deleted.
created_utcWhen it was posted, ISO 8601 UTC.
scoreNet upvotes as Reddit showed them at fetch time. Null on a post reached by URL alone — Reddit's post page carries no score for a visitor; a post reached through a subreddit listing or a search has it.
upvote_ratioShare of upvotes, 0–1. Subreddit listings only.
comment_countComments on the post as Reddit counts them (a comment row carries the count of its post).
post_typetext, image, gallery, video, multi_media, crosspost, link or poll. Subreddit listings only.
flairThe post's flair text, when it has one.
urlWhat the post links to: the external URL, the media, or the crossposted post. For a text post this is its own permalink.
domainDomain of url as Reddit labels it (self.<sub> for text posts, i.redd.it, youtube.com, …).
permalinkThe post's or comment's own URL on reddit.com.
body_textFull text of the post or comment, paragraphs separated by blank lines. Empty for a link post.
body_htmlThe same body as Reddit's rendered HTML, links kept.
mediaMedia URLs the post carries (images, galleries, video).
nsfwMarked NSFW. Known on search hits; null where Reddit did not say.
stickiedPinned by the moderators. Subreddit listings only.
lockedComments locked. Subreddit listings only.
languageReddit's language tag for the post (en, de, …). Subreddit listings only.
award_countAwards on the post. Subreddit listings only.
post_idComment rows: the t3_… id of the post the comment belongs to.
parent_idComment rows: the id of the parent comment (t1_…), or null for a top-level comment.
depthComment rows: 0 for a top-level comment, 1 for a reply to it, and so on.
found_byHow the row was reached: r/<sub>/<sort> for a subreddit listing, search:<query> (with @r/<sub> when scoped), url for a post given by URL, and comments:<post id> for a comment.
fetched_atWhen this row was read from Reddit, ISO 8601 UTC.

Example record:

{
"kind": "post",
"id": "t3_1wd745i",
"subreddit": "Upwork",
"title": "Here are my tips for Upwork newcomers as a top Freelancer",
"author": "Pierre_Zarokian",
"created_utc": "2026-09-11T05:27:33.222000+00:00",
"score": 47,
"upvote_ratio": 0.7582417582417582,
"comment_count": 66,
"post_type": "text",
"flair": null,
"url": "https://www.reddit.com/r/Upwork/comments/1wd745i/here_are_my_tips_for_upwork_newcomers_as_a_top/",
"domain": "self.Upwork",
"permalink": "https://www.reddit.com/r/Upwork/comments/1wd745i/here_are_my_tips_for_upwork_newcomers_as_a_top/",
"body_text": "My stats: 5 years, $500K+ earned, ~900 jobs completed.\n\nMy #1 tip: Find an uncrowded niche. My core skill set is digital marketing and SEO, but the mainstream lanes such as SEO, Google Ads, social media marketing are too saturated. Instead, I built my practice around Online Reputation Management, PR, and Wikipedia page creation. Wikipedia work was a strong earner for years until Upwork restricted it about a year ago. Since then, I've shifted mainly to ORM and PR, and I've started picking up AEO (Answer Engine Optimization) jobs too — it's far less competitive than SEO, and I've already landed 2 AEO contracts in the past few months.\n\nAdditional tips:\n\nMove fast. Try to be among the first 10–15 applicants on any job post, ideally applying within 15 minutes of it going live. Earlier bids win more often.\n\nSkip overcrowded listings. Don't bother applying once a job already has 20–50 proposals — unless you're confident you're a top-tier fit and the budget justifies it.\n\nBid for visibility. Aim to be the #1 bidder when you can, but set yourself a spending cap (say, 20–30 connects) so you don't overspend chasing hyper-competitive listings.\n\nDon't chase underpriced jobs hoping to negotiate up. Check the client's hiring history and average hourly rate paid. If they've hired 20+ freelancers averaging $10/hour, walk away unless that rate works for you. Personally, I won't bid below $75/hour.\n\nKeyword-optimize your profile. Your headline and overview should reflect the terms clients actually search for.\n\nTarget jobs with your keywords in the title. If a client wants to hire you under a vague or irrelevant job title, ask them to repost with a more specific, keyword-aligned title before accepting.\n\nAlways secure reviews. If a client doesn't leave one after project completion, follow up more than once to ask.\n\nGet direct contact info. Once hired, ask for the client's phone number and email, which will be useful if they go unresponsive, and handy later when requesting a review.\n\nStrengthen your proposals with proof. Attach case studies, testimonials, and a client list (especially if it includes recognizable brands).\n\nFeature your reviews. Include 4 strong job reviews at the bottom of every proposal.\n\nPersonalize every application. Even reused templates should open with a line specific to that client's stated needs, so it doesn't read as copy-paste.\n\nProject confidence. Don't undersell your experience. Use phrases like \"I'm the best candidate for this, look no further.\"\n\nUnderprice early to build your review base. In your first few months, take lower-paying jobs to get hired more often and rack up reviews. Once you hit 10–20 reviews, gradually raise your rates.\n\nApply to small unrelated gigs to increase your reviews. Take on $5–$50 jobs in unrelated categories (survey/review-type gigs, for instance) purely to build your review history, even though some of these may be against Upwork's policies.\n\nGood luck and reach out if you have any questions.",
"body_html": "<p>\n <strong>My stats:</strong> 5 years, $500K+ earned, ~900 jobs completed.\n </p><p>\n <strong>My #1 tip: Find an uncrowded niche.</strong> My core skill set is digital marketing and SEO, but the mainstream lanes such as SEO, Google Ads, social media marketing are too saturated. Instead, I built my practice around Online Reputation Management, PR, and Wikipedia page creation. Wikipedia work was a strong earner for years until Upwork restricted it about a year ago. Since then, I've shifted mainly to ORM and PR, and I've started picking up AEO (Answer Engine Optimization) jobs too — it's far less competitive than SEO, and I've already landed 2 AEO contracts in the past few months.\n </p><p>\n <strong>Additional tips:</strong>\n </p><ul>\n <li>\n <p>\n <strong>Move fast.</strong> Try to be among the first 10–15 applicants on any job post, ideally applying within 15 minutes of it going live. Earlier bids win more often.\n </p>\n </li><li>\n <p>\n <strong>Skip overcrowded listings.</strong> Don't bother applying once a job already has 20–50 proposals — unless you're confident you're a top-tier fit and the budget justifies it.\n </p>\n </li><li>\n <p>\n <strong>Bid for visibility.</strong> Aim to be the #1 bidder when you can, but set yourself a spending cap (say, 20–30 connects) so you don't overspend chasing hyper-competitive listings.\n </p>\n </li><li>\n <p>\n <strong>Don't chase underpriced jobs hoping to negotiate up.</strong> Check the client's hiring history and average hourly rate paid. If they've hired 20+ freelancers averaging $10/hour, walk away unless that rate works for you. Personally, I won't bid below $75/hour.\n </p>\n </li><li>\n <p>\n <strong>Keyword-optimize your profile.</strong> Your headline and overview should reflect the terms clients actually search for.\n </p>\n </li><li>\n <p>\n <strong>Target jobs with your keywords in the title.</strong> If a client wants to hire you under a vague or irrelevant job title, ask them to repost with a more specific, keyword-aligned title before accepting.\n </p>\n </li><li>\n <p>\n <strong>Always secure reviews.</strong> If a client doesn't leave one after project completion, follow up more than once to ask.\n </p>\n </li><li>\n <p>\n <strong>Get direct contact info.</strong> Once hired, ask for the client's phone number and email, which will be useful if they go unresponsive, and handy later when requesting a review.\n </p>\n </li><li>\n <p>\n <strong>Strengthen your proposals with proof.</strong> Attach case studies, testimonials, and a client list (especially if it includes recognizable brands).\n </p>\n </li><li>\n <p>\n <strong>Feature your reviews.</strong> Include 4 strong job reviews at the bottom of every proposal.\n </p>\n </li><li>\n <p>\n <strong>Personalize every application.</strong> Even reused templates should open with a line specific to that client's stated needs, so it doesn't read as copy-paste.\n </p>\n </li><li>\n <p>\n <strong>Project confidence.</strong> Don't undersell your experience. Use phrases like \"I'm the best candidate for this, look no further.\"\n </p>\n </li><li>\n <p>\n <strong>Underprice early to build your review base.</strong> In your first few months, take lower-paying jobs to get hired more often and rack up reviews. Once you hit 10–20 reviews, gradually raise your rates.\n </p>\n </li><li>\n <p>\n <strong>Apply to small unrelated gigs to increase your reviews.</strong> Take on $5–$50 jobs in unrelated categories (survey/review-type gigs, for instance) purely to build your review history, even though some of these may be against Upwork's policies.\n </p>\n </li>\n </ul><p>\n Good luck and reach out if you have any questions.\n </p>",
"media": [],
"nsfw": false,
"stickied": false,
"locked": false,
"language": "en",
"award_count": 0,
"post_id": null,
"parent_id": null,
"depth": null,
"found_by": "r/Upwork/new",
"fetched_at": "2026-09-12T21:29:45Z"
}

Pricing

Pay per delivered row, nothing else. post — one post row, from a listing, a search or a URL — $2.00 per 1,000. comment — one comment row (includeComments) — $1.00 per 1,000. No start fee, no minimum, and a run that returns nothing costs nothing: on the acceptance runs the charged event count equals the row count on every run, and the zero-row run charged $0.00. A row is charged only after it is in your dataset, so maxItems and maxCommentsPerPost together are your spending cap.

Usage patterns

  • List a subreddit — Set subreddits and a sort. new is chronological — pair it with postedSince for a window or onlyNew for a schedule. top with time gives the period's best. maxPostsPerSource says how far down each listing to look (Reddit itself stops at about 1,000). Ready-made: Newest posts in a subreddit and Top posts of the month, with their comments.
  • Search for posts — Set searches; each query runs across Reddit, or inside each of subreddits when both are given. searchSort is Reddit's own ordering (new, relevance, hot, top, comments). Hits come with author and full text unless you turn fetchBodies off to save the extra request per post. Ready-made: Search Reddit for a topic, last 7 days.
  • Fetch posts by URL, with their comments — Paste post URLs or ids into postUrls, turn on includeComments, set maxCommentsPerPost and commentSort. Comments follow their post in the dataset, each with depth and parent_id. A post reached by URL alone carries no score (Reddit's post page shows a visitor none); posts reached through a listing or a search do.
  • Monitor on a schedule — Turn on onlyNew, save the run as a task, add a schedule. The first run seeds the memory; every later run delivers only what appeared since, or nothing at all — and nothing is charged for nothing. Name the memory with stateStoreName to share it between tasks or to reset it. Ready-made, schedule it: Monitor subreddits: only new posts each run.

Input configuration

fieldtypedefaultwhat it does
subredditsarraySubreddit names or URLs (Upwork, r/Upwork, https://www.reddit.com/r/Upwork/). Each is listed by sort and time. With searches set as well, every search runs inside each of these subreddits instead.
sortnew / hot / top / rising"new"How each subreddit is listed. new is chronological, which is what postedSince and onlyNew walk most cheaply.
timehour / day / week / month / year / all"week"Applies to sort: top only.
searchesarrayKeyword searches for posts, across all of Reddit — or inside each of subreddits when both are given. One row per matching post.
searchSortnew / relevance / hot / top / comments"new"Order of search results, as Reddit's own search offers it.
postUrlsarraySpecific posts to fetch: URLs (https://www.reddit.com/r/Upwork/comments/1w8w2hb/…) or ids (1w8w2hb, t3_1w8w2hb). Each comes back with its full body and, with includeComments, its comment tree.
includeCommentsbooleanfalseFetch the comment tree of every delivered post — one comment row per comment, with author, score, depth and parent, right after its post. Billed as comment per row.
maxCommentsPerPostinteger100Cap on comment rows per post. Deep threads are expanded breadth-first until the cap.
commentSortconfidence / top / new / controversial / old / qa"confidence"Reddit's comment ordering for the tree.
fetchBodiesbooleantrueA search hit alone carries title, score, comment count and date. Leave this on to read each hit's author and full text as well (one extra request per post). Subreddit listings and post URLs always carry the body.
postedSincestringKeep only posts created after this point: a date (2026-09-01), a timestamp, or a window before now — 12h, 7d, 2w, 1m. With sort: new the listing walk stops at the cutoff, so nothing older is fetched.
onlyNewbooleanfalseRemember every post delivered and skip it next time. Schedule the task and each run returns only what appeared since the previous one — a run with nothing new delivers no rows and costs nothing. The memory is a named key-value store (stateStoreName, or one derived from the targets when left empty).
stateStoreNamestringName of the key-value store that keeps the delivered ids for onlyNew. Leave empty to derive one from the subreddits, searches and post URLs; set it to share one memory between tasks or to reset it (a new name starts fresh).
maxItemsinteger100Stop after this many post rows across the whole run. Comment rows are bounded separately by maxCommentsPerPost. With no start fee, this is also your spending cap: posts × $0.002 (+ comments × $0.001).
maxPostsPerSourceinteger100How far down each listing or search to look. Reddit itself stops a listing at about 1,000 posts.

FAQ

Does it need a Reddit account or a proxy?

No. Reddit is read logged out, through an exit we maintain, and nothing is stored on your side. There is no cookie or proxy field because there is nothing for you to supply.

Why does a post fetched by URL have no score?

Reddit's post page renders nothing but a script shell to a visitor; the post's body and its comment tree come from two other endpoints that do not carry the post's score. A post reached through a subreddit listing or a search has its score, upvote ratio and comment count, because those pages do.

How many comments does a post return?

Up to maxCommentsPerPost (default 100, up to 2,000). The first page of a thread holds about 25 top-level comments with their visible replies; deeper branches are expanded breadth-first until the cap. A thread's comment_count is Reddit's total; the delivered count can be lower when comments are deleted or collapsed.

What does a run cost?

One event per row that lands in your dataset — $2 per 1,000 posts, $1 per 1,000 comments — nothing for the run itself and nothing for a zero-row run. Measured on our release runs: 25 listing rows in a 6 s run, 20 search rows with bodies in 26 s, one post with 40 comments in 17 s.

Who makes this, and what else is there?

Moxlade — corpora your agent can ask. Its other actor is the Upwork freelancer census (search by rate, JSS, badge, country; exact earnings; every contract), and its MCP endpoint for Upwork buyer intelligence is buyer.moxlade.com. Working code for the same client calls, in Python, JavaScript and curl: github.com/getmoxlade/upwork-freelancers-examples — this actor takes the same calls with its own input.

Is the data current?

Every row is read from Reddit at run time — fetched_at says when — so scores and comment counts are what Reddit showed at that moment.

Integration

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('moxlade/reddit-scraper').call({"subreddits": ["Upwork"], "sort": "new", "maxItems": 50});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Python

from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('moxlade/reddit-scraper').call(run_input={'subreddits': ['Upwork'], 'sort': 'new', 'maxItems': 50})
items = client.dataset(run['defaultDatasetId']).list_items().items

CLI

$apify call moxlade/reddit-scraper --input '{"subreddits": ["Upwork"], "sort": "new", "maxItems": 50}'

REST

curl -X POST "https://api.apify.com/v2/acts/moxlade~reddit-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' -d '{"subreddits": ["Upwork"], "sort": "new", "maxItems": 50}'

Support

support@moxlade.com

This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.