Reddit Post Comments Scraper — Full Comment Tree, Any Post URL avatar

Reddit Post Comments Scraper — Full Comment Tree, Any Post URL

Pricing

$1.50 / 1,000 per comment returneds

Go to Apify Store
Reddit Post Comments Scraper — Full Comment Tree, Any Post URL

Reddit Post Comments Scraper — Full Comment Tree, Any Post URL

Reddit comments scraper: paste post URLs (permalinks, redd.it, share links, comment links) and get every comment as flat rows with parent id, depth, thread path, reply and descendant counts, author, score, timestamps. Expands 'load more' stubs. No login or API key.

Pricing

$1.50 / 1,000 per comment returneds

Rating

0.0

(0)

Developer

Scrapers Delight

Scrapers Delight

Maintained by Community

Actor stats

0

Bookmarked

9

Total users

5

Monthly active users

10 days ago

Last modified

Security

Limited permissions

Share

Paste Reddit post URLs and get every comment under them as flat rows that still carry the tree. One row per comment: body, author, score, depth, parent_comment_id, thread_path, reply_count, descendant_count, position, created_iso, edited, permalink, is_deleted and the post context on every row (post_title, post_url, post_score, post_num_comments, tree_complete). Reddit shows a big thread in pieces — the first 25 comments, then "N more replies", "View more comments" and "Continue this thread" links. This Actor opens every one of them, so a big thread comes back whole. No login. No Reddit API key. No CAPTCHA solving.

{
"postUrls": ["https://www.reddit.com/r/programming/comments/luq9oz/how_i_cut_gta_online_loading_times_by_70/"],
"commentSort": "top",
"maxCommentsPerPost": 200
}

Click Try for free and hit Start — that block is the input the Actor ships with: the first 200 comments of that thread in top order, for $0.30.


What makes it different

  1. Tree fields that are computed, not copied. Every row has parent_comment_id and depth, plus thread_path (root-first list of ancestor comment ids, so one JOIN rebuilds any branch), reply_count (direct replies present), descendant_count (whole subtree size), is_top_level and position (delivery order). "Which top-level comment started the biggest argument" is ORDER BY descendant_count DESC WHERE is_top_level — no recursion on your side.
  2. The hidden part of the thread, expanded. With expandMoreComments on (default) every "more replies" loader and every "Continue this thread" cut is opened, at any depth, until the tree is complete or your cap is hit.
  3. tree_complete on every row, and post_num_comments to check it against. You never have to guess whether a thread was cut by a cap, the time budget or a loader that would not open — the row says so, and the log prints delivered of N reddit counts per post.

Also: any URL shape Reddit produces is accepted — desktop permalinks, redd.it short links, the mobile app's /r/sub/s/AbCdEfG share links (resolved live from Reddit's redirect), profile post links (/user/name/comments/…), old. / new. / np. subdomains, bare ids, and comment permalinks: paste a link to one comment and you get that comment's thread only (scope: "comment-thread", focus_comment_id set).


Read this before you buy rows

  1. post_num_comments is Reddit's counter, not a promise. It is kept separately from the tree and drifts both ways: deleted comments that still have replies stay in the tree as [deleted] rows, while deleted comments with no replies are not shown at all. tree_complete: true means every loader Reddit offered was opened.
  2. The per-post cap cuts after the tree math. With maxCommentsPerPost: 200 you get the first 200 rows in the order Reddit's page serves them (the top-level comments of the first page and their replies first), and each row still carries the reply_count / descendant_count of everything fetched. thread_path can name an ancestor that is not in your rows — it is an id, not a join failure.
  3. [deleted] and [removed] rows are real rows. Reddit keeps them so the tree stays connected. They come with is_deleted: true, body "[deleted]" / "[removed]", and usually no score; they are billed like any other row. Set includeDeleted: false to drop them unbilled.
  4. Score is a snapshot. Re-run later if you need settled scores.
  5. Big trees take calls. Reddit's page opens about 10 comments per "more replies" loader, so the whole tree of a ~1,000-comment thread is several hundred Reddit calls and a few minutes; the shipped 200-comment cap is about 25 calls.

What you get

One row per unique comment, deduplicated on Reddit's fullname (t1_…) across the whole run. Timestamps are ISO-8601 UTC plus the raw created_utc epoch. edited is false, or the ISO time of the edit.

GroupFieldsExample
Identityid, name, post_id, permalink, subreddit, subreddit_idgp8beoa · t1_gp8beoa · luq9oz
Treeparent_id, parent_comment_id, is_top_level, depth, position, reply_count, descendant_count, thread_path[]depth 2 · 7 replies · 53 descendants
Authorauthor, author_fullname, author_flair_text, author_is_opderuke
Contentbody, body_length, is_deleted, edited, distinguished, stickied, locked, collapsed, collapsed_reason525 chars
Votesscore, ups, score_hidden, total_awards_received3034
Timecreated_utc, created_iso2021-02-28T21:35:00.233Z
Post contextpost_title, post_url, post_author, post_subreddit, post_score, post_upvote_ratio, post_num_comments, post_created_iso, post_link_flair_text, post_is_self, post_external_url, post_selftext_preview, post_over_18, post_locked, post_archived992 comments · ratio 0.97
Provenancesource (listing / more-children / continue-thread), scope, focus_comment_id, comment_sort, tree_complete, comments_delivered_for_post, comments_absent_at_source, input_url, scraped_at

body is the comment as plain text: paragraphs on their own lines, list items as - item, quotes as > line, code blocks verbatim, links as their text.

Fields Reddit does not show logged-out visitors (measured on 1,006 rows of the thread above, 2026-10-27): author_fullname 0.8% (only where a subreddit renders user flair), author_flair_text 0% on r/programming, collapsed_reason always null, stickied / locked null unless set, comments_absent_at_source always 0. Every other field is filled on every row it applies to: score 96.4% (deleted rows carry none), edited holds the edit time on the 3.9% of rows that were edited, distinguished on moderator comments.

Every run prints a measured fill line in the log for the 12 fields most likely to vary by subreddit, so you can check your own subreddit.

The dataset ships with a Comments table view (post, depth, author, score, body, replies, thread size, posted, tree complete, link).


How to run it

1. One or many post URLs (the usual choice)

{
"postUrls": [
"https://www.reddit.com/r/programming/comments/luq9oz/how_i_cut_gta_online_loading_times_by_70/",
"https://redd.it/1xgauuz",
"https://www.reddit.com/r/AskReddit/s/AbCdEfGhIj",
"t3_luq9oz"
],
"commentSort": "top",
"maxCommentsPerPost": 0
}

maxCommentsPerPost: 0 = the whole tree. Share links are resolved to the canonical permalink from Reddit's own redirect and the log prints the resolution.

2. One comment's thread only

{ "postUrls": ["https://www.reddit.com/r/programming/comments/luq9oz/comment/gp8beoa/"] }

A comment permalink scopes the scrape to that comment and everything under it. Rows carry scope: "comment-thread" and focus_comment_id: "gp8beoa"; the linked comment is depth 0.

3. Top-level comments and their direct replies

{ "postUrls": ["https://redd.it/luq9oz"], "maxDepth": 1, "maxCommentsPerPost": 0 }

maxDepth filters on the 0-based depth field, so maxDepth: 1 returns depths 0 and 1. It filters after the tree math, so each row still carries reply_count and descendant_count for the branch you did not buy. Filtered rows are never billed.

4. First page only, fastest and cheapest

{ "postUrls": ["https://redd.it/luq9oz"], "expandMoreComments": false }

One page per post (25 comments). tree_complete is honest about what you skipped.

Scheduling and integrations

Save the input as a Task, attach a Schedule to re-pull a thread as the discussion grows, and read the dataset over the REST API or the standard integrations (Zapier, Make, n8n, webhooks, MCP). Starting a run from the API:

curl -X POST "https://api.apify.com/v2/acts/scrapersdelight~reddit-post-comments-scraper/runs?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"postUrls":["https://redd.it/luq9oz"],"maxCommentsPerPost":0}'

Input

Fields in the order the Console shows them.

FieldTypeDefaultWhat it does
postUrlsstring list1 sample postPermalinks, redd.it, /s/ share links, profile-post links, comment permalinks, bare ids. One post pasted twice is fetched once.
commentSortselecttoptop, best, new, controversial, old, qa — decides which rows come first under a cap.
💷 Limits & cost
maxCommentsPerPostinteger200Per post. 0 = the whole tree.
maxTotalCommentsinteger0Hard cap for the run. 0 = none. The run's Max total charge is honoured to the whole row as well.
🌳 Tree depth & filters
expandMoreCommentsbooleantrueOpen "more replies" / "Continue this thread". Off = the first page only.
maxDepthinteger0Keep depth ≤ N (0-based). 0 = unlimited. Filtered rows are never billed.
includeDeletedbooleantrueOff drops [deleted] / [removed] placeholders, unbilled.
⚙️ Proxy & performance
proxyConfigurationproxyApify RESIDENTIAL, country USRecommended as is — Reddit turns most datacenter IPs away.
postsPerSessioninteger40Posts served per session before a fresh one is opened (a session is also replaced when Reddit blocks it or its allowance is used up).
requestDelayMsinteger300Pacing between the expansion calls.

Pricing

$0.0015 per comment returned — $1.50 per 1,000. Charged on the comment-scraped event. No monthly fee from this Actor.

RunCommentsCost
The shipped default (1 post, 200 cap)200$0.30
The whole tree of the sample thread1,006$1.51
5 posts × ~260 comments (a typical VoC pull)1,300$1.95
10,000 comments of a mega-thread10,000$15.00
  • You are charged for rows delivered. Duplicates (same post pasted twice, overlapping comment threads), rows removed by maxDepth / includeDeleted, and posts that failed or were not found are never billed.
  • Rows are charged as they are pushed, one post at a time, so a budget cap or time stop leaves you with whole posts' worth of rows, every one of them billed, none unbilled.
  • maxCommentsPerPost × number of posts is your cost ceiling; maxTotalComments and the run's Max total charge are hard caps on top. A charge cap too low for even one comment fetches nothing and bills nothing.

Honest limits

  • No user profiles, no subreddit listings, no search. This Actor does one thing: post URL → comment tree. Our Reddit Subreddit Scraper lists a subreddit's posts (and can attach comments).
  • Plain text, no media. Images/GIFs in comments appear as their link text inside body.
  • Private, quarantined and banned subreddits, and deleted posts, return nothing. The run names each such URL in its status message and moves on; if every post is like that the run ends SUCCEEDED with 0 rows and nothing charged.

Duplicates

Within a post, Reddit can show the same comment on more than one of its pages; the Actor keeps a per-post set and a run-wide set keyed on the t1_ fullname, drops repeats before billing, and asserts uniqueness across everything it pushed before the run is allowed to succeed. Duplicates from input — the same post pasted as a permalink and a redd.it link, or a comment permalink inside a post you also pasted whole — are dropped and logged, never billed.


When a run ends without rows

  • Input that matches nothing (posts not found, private subreddits, share links that lead nowhere, lines that are not Reddit links) → SUCCEEDED, 0 rows, nothing charged, and the status message names each one.
  • Reddit refuses every request (no session clears its check, or every post is refused on fresh exits) → FAILED with that reason in the status message; nothing is charged. Re-run later.
  • Some posts fail, others deliver → SUCCEEDED with a WARNING: status message counting what was skipped and why.
  • Time budget → stops cleanly with every fetched post pushed and a status message; never TIMED-OUT.

FAQ

Does this need an account, a login or cookies? No. It opens a logged-out session the way a browser does and reads the public pages. No credentials, no account cookies, no CAPTCHA service.

Can I get the whole thread, however big? Yes — maxCommentsPerPost: 0. The sample thread came back as 1,006 rows in 542 Reddit calls; a 10,000-comment thread is thousands of calls across several sessions (the Actor rotates them for you) — set the run timeout accordingly.

Why does the row count not match post_num_comments? Reddit's counter is kept separately from the tree — see Read this before you buy rows. tree_complete: true tells you every loader was opened.

Do I need a residential proxy? It is the default and the recommended setting: Reddit turns most datacenter IPs away.

Will two runs give me duplicates? Within a run, never — asserted. Across runs, the name field is Reddit's permanent id, so dedupe on it.


Feedback

Found a URL shape that does not parse or a field you need? Open an issue on the Issues tab, and if the Actor earns it, a review on the Reviews tab helps other buyers find it.