Facebook Comments Scraper: Export Comments & Replies, No Login
Pricing
from $1.25 / 1,000 comments
Facebook Comments Scraper: Export Comments & Replies, No Login
Facebook comments scraper, no login: post, reel, video, photo or page links in, one row per comment and reply out. Text, time, reactions by type, reply count, the commenter's public name and link. Reads the list to its end, names it against Facebook's count. Date window free. Misses free.
Pricing
from $1.25 / 1,000 comments
Rating
0.0
(0)
Developer
Hyperbach
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
8 hours ago
Last modified
Categories
Security
Limited permissionsShare
Every comment and reply of a Facebook post, reel, video or photo, as data, logged out. Give post links (any form: a pfbid link, a numeric link, a share link, a group post, a reel, a video, a photo), a page's link or a public group's link and get one row per comment — the whole text, the time, the reactions by type, the reply count, the commenter's public name, id and profile link where Facebook serves it, the badges, attachments and mentions, and the post's own text and counts — and, when you ask, every reply as its own row with its real parent. Facebook counts more comments than its logged-out list serves; this Actor reads the list to its own end, reads that end twice, and each post gets a free row with what was read against Facebook's count. No login, no cookie, proxies handled for you.
$2.50 per 1,000 comment rows on the Free plan, $2.00 on Starter. A run start is $0.0035. The default input returns about 51 rows for about $0.1285. A missing, hidden or comments-off post, a post with no comment or a value that names nothing is a free row that says why.
Tested head-to-head on 2026-11-04
The job: the first 50 comments of one Facebook post by URL (Humans of New York's post, the leader's own default job), no replies. Every Actor ran on it the same day from the same harness; a rival's cost is what a buyer account paid, this Actor's is its list price on the Free plan. Fields counts the filled fields of a typical row. The lane's #2 by users/30d (memo23/facebook-public-group-posts-scraper, 650) reads a public group's posts with their comments, not one post's comments by URL: left out; the next post-comments seller by users/30d is dami_studio (360). Re-measured monthly.
| Actor | Rows | First row | Run time | Cost | Fields | Failures |
|---|---|---|---|---|---|---|
| this Actor | 50 | 15 s | 30 s | $0.13 | 32 | none |
apify/facebook-comments-scraper | 50 | 3.9 s | 9.4 s | $0.10 | 17 | none |
dami_studio/facebook-comments-scraper | 50 | 4.5 s | 6.3 s | $0.013 | 26 | none |
Why this Facebook comments scraper
- The list's real end, named against Facebook's count. Facebook's comment count is larger than the list it serves a logged-out reader: on 8 ordinary posts walked to the end the list held 66 to 95 % of the count. This Actor reads each post's list to its own end (
has_next_pagefalse), reads that end a second time from a fresh connection, and the post's row saysLIST_ENDwith both figures, never a silent short list and neverCOMPLETEunder the count. - Replies as rows, linked to their real parent. Each thread is read to its end; a reply is its own row with its
threadingDepth(1 or 2), its real parent (parentCommentId, a reply to a reply names that reply) and its thread's top comment (threadRootCommentId). A reply counts towardresultsLimitlike a comment, so the limit you set is the rows you get. - The date window is free.
onlyCommentsNewerThanandonlyCommentsOlderThan(a date, a time or7 days) cost nothing extra here: the walk reads the post newest first and stops at the bound, and no row outside the window is charged. - Four orders, checked. All comments (Facebook's ranking, the default), newest first, oldest first, or Most relevant (Facebook's filtered list: 23 to 50 % of the list on our test posts, and the post row says so). The post row names the order Facebook served, and a run is never charged for an order it did not get.
- Every link form. Post links with a pfbid or a numeric id,
?comment_id=links, group posts,permalink.phpandstory.php(read without the login page they redirect to),/share/p/and/share/r/links, reels, videos, watch links and photos (/photo/?fbid=too), a bare post id, and a page's, a profile's or a public group's link for its newest posts. A public group's post is read too: Facebook answers its comment list to a logged-out reader as turned off and serves it on the post's own page, so the list is read from there, oldest first. - Only what the comment shows. The commenter's public name, id, picture, verified flag and badges (Top fan, Author); the profile link only where Facebook itself serves it, never built from an id; the commenter's gender, which Facebook's answer carries, is never delivered.
- Free rows, not charged ones. A missing or hidden post (checked on a second connection first), comments turned off, no comment, an id Facebook calls invalid, a post given twice in two link forms: one free row each. A comment is delivered and charged once a run.
- Plain HTTP, no browser, no account. Facebook's own logged-out answers, no cookie, nothing of yours. On 14 runs of version 0.1.6 on Apify (2026-11-03 and 2026-11-04, 512 MB) the first comment came 2.4 to 14.8 seconds after the start (the first rows wait up to 10 seconds for the post's own page, which carries the post's text and counts); 50 comments of one post were out by 4.8 to 26.9 seconds (24.9 and 26.9 when that page was slow), 300 comments of three news posts by 27.3 seconds, ten posts with one comment each by 12.3 to 13.2 seconds, and a time-limited walk of eight large posts delivered 1,752 comments in 40 seconds. A slow connection is left after three slow answers and the walk goes on where it was.
Who it's for
- Brand and social media teams — every comment on their own and their competitors' posts and reels, with the reactions and the commenters' public names.
- Researchers and analysts — a post's whole comment list and its replies for sentiment, topic or audience work, with the time, the language code and the thread on every row.
- Agencies and community managers — the replies under a page's own posts, the page's own answers (
isPostAuthor), the top fans' comments, the comments with links or GIFs. - Developers and data teams — typed rows keyed by the comment id, the leader's field names, one free row per post with the verdict and Facebook's counts, a run summary to check a pipeline against.
Quick start
The first 50 comments of one post
{"startUrls": ["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"],"resultsLimit": 50}
Every comment and reply of a post, newest first
{"startUrls": ["https://www.facebook.com/9gag/posts/1610591477773546"],"resultsLimit": 0,"includeNestedComments": true,"sortOrder": "newest","maxItems": 2000}
The comments of a page's 5 newest posts from the last 7 days
{"startUrls": ["https://www.facebook.com/bbcnews/"],"maxPostsPerPage": 5,"onlyCommentsNewerThan": "7 days","resultsLimit": 200}
A reel's comments that mention a word
{"startUrls": ["https://www.facebook.com/reel/1306448491672610/"],"textContains": ["goal","messi"],"resultsLimit": 100}
Switching from apify/facebook-comments-scraper?
Your input works as it is. Each name in the left column is read as this Actor's own field and the run log says so (read <theirs> as <ours>); a name marked not read is ignored with a note. A value in the other Actor's shape, an object list or its own date form, is read too.
| apify/facebook-comments-scraper | this Actor | what to know |
|---|---|---|
startUrls | startUrls | Post, reel, video, photo, share or page links; the leader's [{"url": …}] objects and plain strings alike. |
resultsLimit | resultsLimit | Rows per post, replies included; empty or 0 = the whole list. |
includeNestedComments | includeNestedComments | Every reply as its own row after its comment (depth 1 and 2), each with its real parent. |
viewOption | sortOrder | RANKED_UNFILTERED → all, RECENT_ACTIVITY → newest, RANKED_THREADED → relevant (Facebook's filtered list). |
onlyCommentsNewerThan | onlyCommentsNewerThan | A date, a time or a span (3 days, the leader's format); free here. |
What differs:
resultsLimitcounts every row of a post, replies included (a reply is a row here, as with the leader); the leader's replies can pass its limit.viewOptionis read assortOrder: RANKED_UNFILTERED → all (the default), RECENT_ACTIVITY → newest, RANKED_THREADED → relevant. Oldest first is added.- The field names are the leader's where it serves the field (
facebookUrl,inputUrl,commentUrl,commentId,id,feedbackId,text,date,likesCount,commentsCount,threadingDepth,profileName,profileId,profilePicture,profileUrl,facebookId,postTitle);likesCountis a number (the total of every reaction), andreactionsByTypesplits it. - The leader's raw
authorobject is not delivered: it carries the commenter's gender. The verified flag isisVerified; the badges areauthorBadges. - Replies are rows after their comment, never a nested
commentslist; each namesparentCommentIdandthreadRootCommentId. - The date window is free (the leader sells it as an add-on per post), and
onlyCommentsOlderThanis added. - Each post gets a free row with the verdict and Facebook's counts; a missing post is a free row, not a charged item.
Output
One row per comment or reply, and one free row per post and per page.
| field | meaning |
|---|---|
recordType | comment on a comment or reply row (charged); post on a post's free row; page on a page or profile link's free row. |
status | ok, or why a value gave no comment: not_found, comments_disabled, no_comments, invalid_input, duplicate, failed (Facebook refused every connection, or the post's answer could not be read), not_read (the run ended first). |
inputUrl | The value you gave that this row answers (a post, reel, video, photo, share or page link). |
commentId | Facebook's numeric id of the comment or reply. |
id | Facebook's node id of the comment (base64 of comment:<post id>_<comment id>). |
feedbackId | The comment's own feedback id (Facebook's key of its reactions and replies). |
commentUrl | The comment's link as Facebook serves it (a reply's carries reply_comment_id). |
text | The comment's whole text, emoji and names kept; empty for a sticker, GIF or photo alone. |
date | When the comment was posted (UTC). |
language | Facebook's language code of the comment (en_XX, vi_VN, …); null when it has no text. |
likesCount | The comment's reactions, every type together. |
reactionsByType | The reactions by type: like, love, care, haha, wow, sad, angry. |
commentsCount | The comment's reply count as Facebook shows it. |
threadingDepth | 0 on a top-level comment, 1 on a reply, 2 on a reply to a reply (Facebook shows two levels). |
parentCommentId | On a reply: the id of the comment or reply it answers. |
threadRootCommentId | On a reply: the id of the top-level comment whose thread it is in. |
profileName | The commenter's public name, as the comment shows it. |
profileId | The commenter's Facebook id, as the comment's answer serves it. |
profileUrl | The commenter's profile link, only where Facebook serves it (about half of the comments); never built from an id. |
profilePicture | The commenter's picture (a signed link that stops working after some days). |
isVerified | true when Facebook marks the commenter verified. |
authorBadges | The badges Facebook shows beside the name (Top fan, Author, …). |
isPostAuthor | true when the post's own page or profile wrote the comment (Facebook's Author badge). |
isEdited | true when the comment was edited (Facebook shows its edit history). |
isAiGenerated | true when the commenter disclosed the comment as AI-generated. |
attachments | The comment's attachments: each {type, url, imageUrl, sourceUrl, label} with type gif, photo, sticker, link or video. |
mentions | The profiles and pages the text tags: each {type, name, url}. |
links | The external links in the comment's text. |
facebookUrl | The post's own link (Facebook's canonical URL). |
facebookId | The post's numeric id. |
pageName | The page or profile that published the post. |
pageId | That page's or profile's id. |
postTitle | The post's text (with includePostDetails). |
postDate | When the post was published (UTC; with includePostDetails). |
postReactionsCount | The post's reactions (with includePostDetails). |
postSharesCount | The post's shares (with includePostDetails; a reel's page carries none). |
postCommentsCount | Facebook's count of the post's top-level comments, in the order read. |
postCommentsTotal | Facebook's count of the post's comments and replies. |
sortOrder | On a post row: the order the list was read in (all, newest, oldest, relevant). It differs from your sortOrder when Facebook showed no comment in yours; note says so. |
verdict | On a post row: COMPLETE, LIST_END (the list's own end under Facebook's count, read twice), CAPPED, WINDOW_END or PARTIAL (note says why). |
commentsDelivered | On a post row: the top-level comments delivered. |
repliesDelivered | On a post row: the replies delivered. |
commentsRead | On a post row: the top-level comments read from the list (the filters can leave some out). |
postsFound | On a page row: the newest posts read from the page. |
note | Why a post or page row has the status or the verdict it has, with what was read against Facebook's count. |
scrapedAt | When this row was read (UTC). |
Example record:
{"recordType": "comment","status": "ok","inputUrl": "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl","commentId": "481627996424606","id": "Y29tbWVudDo2Mzc1MjE5MzQyNTUyMTEyXzQ4MTYyNzk5NjQyNDYwNg==","feedbackId": "ZmVlZGJhY2s6cGZiaWQwTGZaUmVTNzc4ekxIeTVURVFmU1VNN05kWEFtU0JzSk1qRkQyZlVzNmdRZm1SczUxQk5QUXVjUzYzNlpxN1FjQm9VUlcycW5vYXI2c3poUHVRb2o3TGt2eE15YlM0WkRFdWw=","commentUrl": "https://www.facebook.com/humansofnewyork/posts/pfbid02Eq8ypRwEZLtnoY5Dw765K211q9qppjYyBJdxd6T3CAHAxc1t4A2fV5d7eXARdQetl?comment_id=481627996424606","text": "This is one of my favorite stories to date. Good nutrition is at the heart of so many solutions. 💚","date": "2021-08-15T20:01:24Z","language": "en_XX","likesCount": 442,"reactionsByType": {"like": 368,"love": 71,"care": 3,"haha": 0,"wow": 0,"sad": 0,"angry": 0},"commentsCount": 8,"threadingDepth": 0,"parentCommentId": null,"threadRootCommentId": null,"profileName": "[name]","profileId": "i_e6194b99dd","profileUrl": null,"profilePicture": "https://scontent.xx.fbcdn.net/v/t39.30808-1/[picture].jpg","isVerified": false,"authorBadges": [],"isPostAuthor": false,"isEdited": false,"isAiGenerated": false,"attachments": [],"mentions": [],"links": [],"facebookUrl": "https://www.facebook.com/humansofnewyork/posts/pfbid02Eq8ypRwEZLtnoY5Dw765K211q9qppjYyBJdxd6T3CAHAxc1t4A2fV5d7eXARdQetl","facebookId": "6375219342552112","pageName": "Humans of New York","pageId": "100050429952420","postTitle": "(2/3) “I knew nothing about gardening. But I knew how to google, so I looked up some easy stuff to plant. Turns out it’s hard to mess up herbs. So I went to the clearance rack at Home Depot and got some herbs. All of the soil was contaminated, so I backed up a dump truck full of organic soil. Nevaeh’s kindergarten class came out and planted the first seedlings. There wasn’t much structure in the beginning. A lot of times I’d just sit around with the kids and look at clouds. But over time the garden became a sort of outdoor science classroom. All of us were learning together. If something died, we’d just try a new spot. We learned about worms, and lady bugs, and praying mantises. Then we learned about food systems. I couldn’t help but notice the diets of these kids: all sugar and processed food. Some of them couldn’t name a single vegetable. But how could you blame them? There are 55 fast food restaurants in this community, but not a single supermarket. So we started growing vegetables in our garden. Not all of the kids were into it. But in every class there would be two or three— who were always around, and involved. Nevaeh was one of those kids. She came to all the camps. She came on the nature walks. She just stuck to me. At first her mother was skeptical, but she could see the consistency. And soon she was bringing Nevaeh to work with me in the garden on weekends. In the beginning Nevaeh was sorta quiet, and off to the side. But over time she took ownership of the garden. Those became her plants, not mine. Whenever volunteers came to help with composting-- Nevaeh would take the lead. And if you were doing it wrong, she’d grab that rake right out of your hands. Ten years have passed since we planted that first garden. And Harlem Grown has expanded to 12 different urban farms. 6,000 lbs of organically grown products have been given to the community free of charge. But the plants are just a byproduct. We’re trying to grow healthy children. But not just children. All of us are learning together. Today our most important employee is Nevaeh’s mom. She’s learned more about gardening than any of us. And she’s the Agricultural Director of all our farms.”","postDate": "2021-08-15T19:50:37Z","postReactionsCount": 181806,"postSharesCount": 9182,"postCommentsCount": 2806,"postCommentsTotal": 3215,"sortOrder": null,"verdict": null,"commentsDelivered": null,"repliesDelivered": null,"commentsRead": null,"postsFound": null,"note": null,"scrapedAt": "2026-11-03T16:24:23Z"}
Pricing
Pay per comment delivered, plus one run start; no platform usage and no proxy traffic is billed to you.
| event | unit | Free | Starter | Scale | Business |
|---|---|---|---|---|---|
Comment (comment) | per 1,000 | $2.50 | $2.00 | $1.70 | $1.25 |
Run start (start) | per run | $0.0035 | $0.0035 | $0.0035 | $0.0035 |
A comment is $2.50 per 1,000 on the Free plan ($0.0025 a comment) and $2.00 on Starter. A reply is a comment: with includeNestedComments each reply is its own row at the same price. Everything the row carries is inside that price: the text, the time, the reactions by type, the reply count, the commenter's public name, id and profile link where Facebook serves it, the badges, attachments and mentions, and the post's own text and counts. The date window is free: no add-on for onlyCommentsNewerThan / onlyCommentsOlderThan, and none for textContains. Each run that delivers a charged row also pays the run start, $0.0035 once; a run that delivers none pays nothing at all. So one comment costs $0.006 on the Free plan and $0.0055 on Starter; the first 50 comments of a post $0.1285 and $0.1035; 1,000 comments $2.5035 and $2.0035; Humans of New York's post of our tests to the end of its list (2,729 comments) $6.826 and $5.4615. Free: every post's and page's summary row, a missing or hidden post, comments turned off, a post with no comment, a hashtag or a value that is not a link, a post given twice, a comment a filter or the date window leaves out, and a post left unread at maxItems, your charge limit or the time limit. A run that stops early (a timeout, an abort) is charged for the comments it delivered. maxItems counts the charged rows across posts. Before the first request the log names the price of a comment at your plan, the run start and the most the run can cost when resultsLimit or maxItems bounds it (under your charge limit). With resultsLimit 0 and no maxItems there is no such bound: the cost follows each post's list, and each post row gives Facebook's own count. The list a logged-out reader is served ends under that count (66 to 95 % of it on 8 ordinary posts walked to the end; 35 of 43 and 83 of 102 on two news posts of our last test), and a large post's list is long (2,729 comments on the Humans of New York post above; a post with 36,718 comments was walked past 10,000), so set resultsLimit, maxItems or a charge limit for a deep walk. Enterprise plans have their own rates — the Actor's Pricing tab shows the price for your plan.
Usage patterns
- What to give —
startUrls: post links in any form (/<page>/posts/<pfbid or id>/,?comment_id=links,/groups/<group>/posts/<id>/,permalink.php,story.php,/share/p/…), reel, video, watch and photo links (/reel/<id>/,/<page>/videos/<id>/,/watch/?v=<id>,/share/r/…,/<page>/photos/<id>/,/photo/?fbid=<id>), a bare post id, a page's or profile's link, or a public group's link (/groups/<group>/): itsmaxPostsPerPagenewest posts (1 to 20). A reel, video or photo is read through its own page for the post it belongs to. A group post's comments are read from the post's own page, oldest first (Facebook answers their list to a logged-out reader as turned off). A hashtag or a search is not read and gets a free row that says so. - How many comments —
resultsLimitcaps each post's rows, replies included (empty or 0 = the whole list);maxRepliesPerCommentcaps each thread;maxItemscaps the whole run's charged rows. All three are exact. With replies on and a limit set, each comment's thread is read before the next comment, so the limit holds a comment with its replies before the later comments. The post row says how many comments were read and delivered, Facebook's own counts (postCommentsCount, the top-level comments;postCommentsTotal, with the replies) and why the walk stopped (verdict: COMPLETE, the list's end with every comment Facebook counts; LIST_END, the list's own end under Facebook's count, read twice; CAPPED, your limit (resultsLimit, ormaxItemsfor the post it stopped); WINDOW_END, the date window's bound; PARTIAL, stopped early with the reason innote). - Orders, the date window and filters —
sortOrder:all(default: the whole list in Facebook's ranking),newest,oldest, orrelevant(Facebook's Most relevant list, which leaves comments out by Facebook's own choice). When Facebook shows no comment in your order while it counts some (some profiles' posts, in All comments and Most relevant), the post is read newest first, or oldest first, and its post row says so insortOrderandnote. A date window reads each post newest first (oldest first foronlyCommentsOlderThanalone) and stops at the bound.textContainskeeps the comments and replies that hold any of the words, case-insensitive; the rest is read and left out, never charged. A filtered walk reads at most 100 pages of a post plus 5 for each row it keeps, and the post row says so when that ends it. - What a logged-out reader is not shown — Facebook counts comments its logged-out list does not serve (hidden, filtered or restricted ones): the list ended at 66 to 95 % of the count on our test posts, the same from five countries. The commenter's profile link is served on about half of the comments (202 of 408 in our study), and only those rows carry it. A translation of a comment is not served logged out; the comment's language code is (
language). A private group's posts are not readable at all.
Input configuration
| field | type | default | what it does |
|---|---|---|---|
startUrls | array | [] | One per line. A post link in any form (https://www.facebook.com/ |
resultsLimit | integer | The most rows to deliver from each post, replies included (a reply is a row, as with the leader). Empty or 0 = every comment the post's list serves, to its end. Over the API, send this number: the form's 50 is a prefill, not a default. | |
includeNestedComments | boolean | false | Also deliver the replies to every comment read, each right after its comment, with its real parent and its thread's top comment named (replies to replies included: Facebook shows two levels). Each reply is a row and counts toward Comments per post; with a limit set, each comment's thread is read before the next comment. A comment Facebook shows 0 replies under is asked too (Facebook counts 0 on some threads it serves). |
maxRepliesPerComment | integer | With replies on: the most replies to deliver under each comment. Empty or 0 = every reply of the thread. | |
sortOrder | all / newest / oldest / relevant | "all" | The order Facebook lists the comments in. All comments (default, the leader's RANKED_UNFILTERED): the whole list in Facebook's ranking. Newest first, Oldest first: the whole list by time. Most relevant: Facebook's filtered list (some comments left out by Facebook). A date window reads each post newest first. The leader's viewOption values are read too. |
onlyCommentsNewerThan | string | Only comments from this time on: a date (2026-10-01, 00:00 UTC), a time (2026-10-01T12:00:00Z) or a span back from now (7 days, 7d, 24h, 30m, 2 months, yesterday, today). The walk reads newest first and stops at the first older comment. Free (no add-on price). | |
onlyCommentsOlderThan | string | Only comments up to this time: a date, a time or a span back from now. Free. | |
textContains | array | [] | Deliver only the comments and replies whose text contains any of these words, case-insensitive. A filtered walk reads at most 100 pages of a post plus 5 for each row it keeps, and its post row says so. |
includePostDetails | boolean | true | Read each post's own page once for its text, time, reactions and shares, on every row (postTitle, postDate, postReactionsCount, postSharesCount). The post's id, URL, page and comment counts are on every row either way. |
maxPostsPerPage | integer | 5 | For a page or profile link: how many of its newest posts to read (1–20, from one read of the page). |
failOnEmpty | boolean | false | End the run FAILED (instead of SUCCEEDED with the free post rows) when no comment row was delivered. For pipelines that alert on a failed run. |
maxItems | integer | 0 | The most charged rows (comments and replies) of the whole run; 0 = no cap beyond your charge limit. |
proxyUrl | string | Your own proxy (scheme://user:pass@host:port) for every call instead of ours. Leave empty: the Actor brings its own connections at no cost to you. |
Errors
A run does not fail because of your input. When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends Succeeded, charges nothing, and says what to change:
- the status message starts with
INPUT REJECTED; - the dataset holds one row,
{"error": true, "code": "…", "message": "…"}, and no results; - the key-value store record
ERRORholds the same object.
From code, check error on the first row before reading results.
A post that does not exist or a logged-out reader cannot see, a post with its comments turned off or with no comment, or a value that names nothing (a hashtag, a search, another site) is not an error: it gets one free row with its status and the reason, and the run goes on with the others. A run that ends Failed is a fault on our side, never your input; it charges nothing, and we are alerted.
FAQ
Why do I get fewer comments than the post's comment count?
Facebook's count includes comments its logged-out list does not serve. On 8 ordinary posts walked to the end, the list held 66 to 95 % of the top-level count (the same list from the US, GB, DE, BR and IN). This Actor reads the list to its own end, reads that end once more from a fresh connection, and the post row names what was read against Facebook's count (LIST_END).
Does it get replies?
Yes, with includeNestedComments: each comment's thread is read to its own end, every reply is its own row right after its comment, with its threadingDepth (Facebook shows two levels), its real parent and its thread's top comment. Each reply is charged like a comment and counts toward resultsLimit.
Does it need my Facebook login or cookies?
No. It reads only what Facebook shows to anyone without an account, over plain HTTP, with its own connections. You never give a password, a cookie or a session, so no account of yours can be blocked.
What happens with a deleted or private post, or one with comments off?
Each gets one free row: not_found (the post does not exist or a logged-out reader cannot see it, checked on a second connection first), comments_disabled, no_comments, or invalid_input for an id Facebook calls invalid. Nothing is charged for them, and the run goes on.
Is the same comment ever delivered twice?
No. A comment is delivered and charged once a run by its id, across pages and inputs; a post given twice (a pfbid link and a numeric link) is read once and the other value gets a free duplicate row.
How long do the picture and GIF links work?
Facebook signs its CDN links (the commenter's picture, a photo or GIF in a comment); they stop working after some days. Download what you keep.
Integration
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('hyperbach/facebook-comments-scraper').call({"startUrls": ["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"], "resultsLimit": 50, "maxItems": 500});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python
from apify_client import ApifyClientclient = ApifyClient('YOUR_TOKEN')run = client.actor('hyperbach/facebook-comments-scraper').call(run_input={'startUrls': ['https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl'], 'resultsLimit': 50, 'maxItems': 500})items = client.dataset(run['defaultDatasetId']).list_items().items
CLI
$apify call hyperbach/facebook-comments-scraper --input '{"startUrls": ["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"], "resultsLimit": 50, "maxItems": 500}'
REST
curl -X POST "https://api.apify.com/v2/acts/hyperbach~facebook-comments-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H 'Content-Type: application/json' -d '{"startUrls": ["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"], "resultsLimit": 50, "maxItems": 500}'
AI agents and MCP
Apify's MCP server offers this Actor as a tool to Claude, Cursor, VS Code and any other MCP client. Connect https://mcp.apify.com?tools=hyperbach/facebook-comments-scraper and ask, for example: "Get the comments and replies of these Facebook posts with each commenter's name, the time, the reactions and the reply count". The agent fills the input from the table above and reads the rows from the run's dataset. A field under the name another Actor gives it is read as this Actor's own: urls, url, links, postUrls as startUrls; maxComments, commentsLimit, maxCommentsPerPost, commentsPerPost as resultsLimit; includeReplies, replies, scrapeReplies, withReplies as includeNestedComments; maxReplies, repliesLimit, repliesPerComment as maxRepliesPerComment (and more).
n8n, Make and Zapier
The Apify node in n8n, the Apify app in Make and the Apify integration in Zapier run this Actor on a schedule or from a trigger and read its dataset. A webhook on the run's end (Integrations on the Actor page) sends the rows on to your own endpoint. Nothing to install on our side.
Support
Disagree with a charge? Write to apify@hyperbach.com with the run ID. We will ask Apify to compensate you, and the charge comes back to your Apify account as platform credit.
Did it do the job? A short review on the Store, at any rating, helps the next buyer choose.
This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.