Facebook Comments Scraper: Export Comments & Replies, No Login avatar

Facebook Comments Scraper: Export Comments & Replies, No Login

Pricing

from $1.25 / 1,000 comments

Go to Apify Store
Facebook Comments Scraper: Export Comments & Replies, No Login

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

Hyperbach

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

8 hours ago

Last modified

Security

Limited permissions

Share

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.

ActorRowsFirst rowRun timeCostFieldsFailures
this Actor5015 s30 s$0.1332none
apify/facebook-comments-scraper503.9 s9.4 s$0.1017none
dami_studio/facebook-comments-scraper504.5 s6.3 s$0.01326none

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_page false), reads that end a second time from a fresh connection, and the post's row says LIST_END with both figures, never a silent short list and never COMPLETE under 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 toward resultsLimit like a comment, so the limit you set is the rows you get.
  • The date window is free. onlyCommentsNewerThan and onlyCommentsOlderThan (a date, a time or 7 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.php and story.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-scraperthis Actorwhat to know
startUrlsstartUrlsPost, reel, video, photo, share or page links; the leader's [{"url": …}] objects and plain strings alike.
resultsLimitresultsLimitRows per post, replies included; empty or 0 = the whole list.
includeNestedCommentsincludeNestedCommentsEvery reply as its own row after its comment (depth 1 and 2), each with its real parent.
viewOptionsortOrderRANKED_UNFILTERED → all, RECENT_ACTIVITY → newest, RANKED_THREADED → relevant (Facebook's filtered list).
onlyCommentsNewerThanonlyCommentsNewerThanA date, a time or a span (3 days, the leader's format); free here.

What differs:

  • resultsLimit counts 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.
  • viewOption is read as sortOrder: 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); likesCount is a number (the total of every reaction), and reactionsByType splits it.
  • The leader's raw author object is not delivered: it carries the commenter's gender. The verified flag is isVerified; the badges are authorBadges.
  • Replies are rows after their comment, never a nested comments list; each names parentCommentId and threadRootCommentId.
  • The date window is free (the leader sells it as an add-on per post), and onlyCommentsOlderThan is 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.

fieldmeaning
recordTypecomment on a comment or reply row (charged); post on a post's free row; page on a page or profile link's free row.
statusok, 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).
inputUrlThe value you gave that this row answers (a post, reel, video, photo, share or page link).
commentIdFacebook's numeric id of the comment or reply.
idFacebook's node id of the comment (base64 of comment:<post id>_<comment id>).
feedbackIdThe comment's own feedback id (Facebook's key of its reactions and replies).
commentUrlThe comment's link as Facebook serves it (a reply's carries reply_comment_id).
textThe comment's whole text, emoji and names kept; empty for a sticker, GIF or photo alone.
dateWhen the comment was posted (UTC).
languageFacebook's language code of the comment (en_XX, vi_VN, …); null when it has no text.
likesCountThe comment's reactions, every type together.
reactionsByTypeThe reactions by type: like, love, care, haha, wow, sad, angry.
commentsCountThe comment's reply count as Facebook shows it.
threadingDepth0 on a top-level comment, 1 on a reply, 2 on a reply to a reply (Facebook shows two levels).
parentCommentIdOn a reply: the id of the comment or reply it answers.
threadRootCommentIdOn a reply: the id of the top-level comment whose thread it is in.
profileNameThe commenter's public name, as the comment shows it.
profileIdThe commenter's Facebook id, as the comment's answer serves it.
profileUrlThe commenter's profile link, only where Facebook serves it (about half of the comments); never built from an id.
profilePictureThe commenter's picture (a signed link that stops working after some days).
isVerifiedtrue when Facebook marks the commenter verified.
authorBadgesThe badges Facebook shows beside the name (Top fan, Author, …).
isPostAuthortrue when the post's own page or profile wrote the comment (Facebook's Author badge).
isEditedtrue when the comment was edited (Facebook shows its edit history).
isAiGeneratedtrue when the commenter disclosed the comment as AI-generated.
attachmentsThe comment's attachments: each {type, url, imageUrl, sourceUrl, label} with type gif, photo, sticker, link or video.
mentionsThe profiles and pages the text tags: each {type, name, url}.
linksThe external links in the comment's text.
facebookUrlThe post's own link (Facebook's canonical URL).
facebookIdThe post's numeric id.
pageNameThe page or profile that published the post.
pageIdThat page's or profile's id.
postTitleThe post's text (with includePostDetails).
postDateWhen the post was published (UTC; with includePostDetails).
postReactionsCountThe post's reactions (with includePostDetails).
postSharesCountThe post's shares (with includePostDetails; a reel's page carries none).
postCommentsCountFacebook's count of the post's top-level comments, in the order read.
postCommentsTotalFacebook's count of the post's comments and replies.
sortOrderOn 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.
verdictOn 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).
commentsDeliveredOn a post row: the top-level comments delivered.
repliesDeliveredOn a post row: the replies delivered.
commentsReadOn a post row: the top-level comments read from the list (the filters can leave some out).
postsFoundOn a page row: the newest posts read from the page.
noteWhy a post or page row has the status or the verdict it has, with what was read against Facebook's count.
scrapedAtWhen 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.

eventunitFreeStarterScaleBusiness
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>/): its maxPostsPerPage newest 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 — resultsLimit caps each post's rows, replies included (empty or 0 = the whole list); maxRepliesPerComment caps each thread; maxItems caps 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, or maxItems for the post it stopped); WINDOW_END, the date window's bound; PARTIAL, stopped early with the reason in note).
  • Orders, the date window and filters — sortOrder: all (default: the whole list in Facebook's ranking), newest, oldest, or relevant (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 in sortOrder and note. A date window reads each post newest first (oldest first for onlyCommentsOlderThan alone) and stops at the bound. textContains keeps 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

fieldtypedefaultwhat it does
startUrlsarray[]One per line. A post link in any form (https://www.facebook.com/
resultsLimitintegerThe 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.
includeNestedCommentsbooleanfalseAlso 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).
maxRepliesPerCommentintegerWith replies on: the most replies to deliver under each comment. Empty or 0 = every reply of the thread.
sortOrderall / 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.
onlyCommentsNewerThanstringOnly 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).
onlyCommentsOlderThanstringOnly comments up to this time: a date, a time or a span back from now. Free.
textContainsarray[]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.
includePostDetailsbooleantrueRead 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.
maxPostsPerPageinteger5For a page or profile link: how many of its newest posts to read (1–20, from one read of the page).
failOnEmptybooleanfalseEnd 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.
maxItemsinteger0The most charged rows (comments and replies) of the whole run; 0 = no cap beyond your charge limit.
proxyUrlstringYour 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 ERROR holds 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 ApifyClient
client = 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.