Facebook Comments Scraper — Post Comments, Facebook Reactions
Pricing
from $0.60 / 1,000 comments
Facebook Comments Scraper — Post Comments, Facebook Reactions
Facebook reactions and comments for any post, reel, watch or fb.watch link — text, author, date, reply count and the ten-way reaction breakdown (like, love, care, haha, wow, sad, angry). No login, no cookies. Top-level comments only. Exact limit per link. No start fee, nothing undelivered charged.
Pricing
from $0.60 / 1,000 comments
Rating
0.0
(0)
Developer
Steadyfetch Team
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Paste the Facebook post, reel, watch or fb.watch links you want and get the comments underneath them: what was written, who wrote it, when, how many replies sit under it, and the full reaction breakdown — like, love, care, haha, wow, sad, angry, thankful, pride, confused. No login, no cookies, no proxy to configure. Your limit is exact and it is per post — set 100 and you get 100 from each link, and a comment we could not deliver is never charged. Nothing is charged for starting a run. From $0.60 per 1,000 comments on the cheapest paid tier, $2.40 per 1,000 on the Apify free plan, platform usage included.
Using an AI agent? Pin this actor in Apify's MCP server with one link: https://mcp.apify.com?tools=steadyfetch/facebook-comments-scraper
- Actor id:
steadyfetch/facebook-comments-scraper - Input:
{ "postUrls": ["https://www.facebook.com/reel/2430902544051423"] }— the one field you have to set. A post, reel, watch or fb.watch link, as many as you like. Add"resultsLimit": 100for the per-post limit and"maxItems": 1000for the whole run. - Cap the bill: set
maxTotalChargeUsdon the run (a run option, not Actor input), e.g.0.50— the run stops when it reaches it.
Unofficial. Not affiliated with, endorsed by, or sponsored by Facebook or Meta Platforms, Inc.
Replies are counted, not pulled
Read this first, because it is the one thing this actor deliberately does not do. Every comment row carries replyCount, so you can see at a glance which threads are busy — but the replies themselves are not returned. Facebook's own reply feed hands back a subset of a thread rather than the thread: measured on this data, 2 replies came back on a comment declaring 37, and 1 on a comment declaring 5, both reporting no further pages. Selling a subset as a thread would be a lie, so this actor does not sell it at all. Top-level comments are what it delivers, and the only thing it charges for.
What one row looks like
A real delivered row, built by this actor's own parser from a harvested comment page:
{"commentId": "1927177644651092","commentUrl": "https://www.facebook.com/reel/2430902544051423?comment_id=1927177644651092","postUrl": "https://www.facebook.com/reel/2430902544051423","postId": "1389159413245942","text": "Omg the thumbnail makes him look like Moby without glasses 🤣","createdAt": "2026-05-20T18:11:13.000Z","authorName": "…","authorId": "…","authorProfileUrl": "…","reactionCount": 314,"replyCount": 37,"reactionLike": 291,"reactionLove": 9,"reactionCare": 2,"reactionHaha": 12,"reactionWow": 0,"reactionSad": 0,"reactionAnger": 0,"reactionThankful": 0,"reactionPride": 0,"reactionConfused": 0,"source": "facebook","status": "delivered","charged": true}
The three author fields are trimmed for this page; a real row carries the name, the Facebook ID and the profile link. Every column is listed in the table below, and a link that could not be read carries the same columns with null in them plus a status saying why, and no result fee.
What you get
One row per top-level comment, at one price.
| Column | What it holds |
|---|---|
commentId | the comment's own Facebook id |
commentUrl | a permalink to that comment, built on the post link you gave |
text | what they wrote |
authorName · authorId · authorProfileUrl | who wrote it |
createdAt | when it was posted, ISO-8601 UTC |
reactionCount | reactions on the comment, all kinds together |
reactionLike · reactionLove · reactionCare · reactionHaha · reactionWow · reactionSad · reactionAnger · reactionThankful · reactionPride · reactionConfused | the ten-way breakdown, one column each |
replyCount | how many replies sit under the comment |
postUrl · postId · source | which post it belongs to (source is always facebook) |
repeat | this account already had this comment and asked for it again |
charged · status · statusReason | whether this row was billed, and why, so your invoice reconciles from the dataset itself |
The ten reaction columns are the reason most people are here: a comment with 40 reactionAnger and 3 reactionLike is a different signal from 43 reactions, and you cannot get that from a total.
Price
One charged event, comment, and it lands only on a comment that was actually delivered.
| Apify plan | Per comment | Per 1,000 comments |
|---|---|---|
| Free plan | $0.0024 | $2.40 |
| Bronze | $0.0014 | $1.40 |
| Silver | $0.0009 | $0.90 |
| Gold and above | $0.0006 | $0.60 per 1,000 |
Platform usage is included in that price — there is no separate compute bill on top, and no start fee, so a run that returns nothing costs nothing. Set maxTotalChargeUsd on the run and it is a hard ceiling: the run stops cleanly under it, delivers everything already in hand, and the last row says what is left.
Honest rows: what "not charged" actually means
Every run closes its own books. A post that returned less than it was asked for leaves an uncharged row saying which of five things happened, and none of them is billed:
post_not_found— Facebook has nothing at that link: the link is wrong, the post was deleted, or it sits behind a login. A definitive answer about your link.no_comments— the post gave no more. Either Facebook had no next page for it (comments turned off, or nobody has commented — a definitive answer, not a failure), or this run reached one of the actor's own bounds: 500 pages of comments on one link, or three pages in a row that held only comments you already have. The row says which of the three it was, and whose bound it was.stopped_at_limit— one of your own limits, or the run clock, stopped it first. The row names which.vendor_unavailable— the read did not go through. Temporary, says nothing about your post, and a re-run is the fix.vendor_budget— this actor reached its own monthly collection allowance and stopped rather than collecting more.
The last row of every run is a receipt: delivered, asked for, skipped, what stopped it, and the charged-event totals. A cost cap or a time limit ends the collecting, never the delivering — comments already in hand are always written out.
maxItems also answers to limit and count, the names other Facebook comment scrapers use, and the smallest limit present binds. One uncharged note row says which name was read and what it was read as, so a limit typed under the wrong name never quietly runs up a bill. Asking for more than the actor serves is never a refusal: up to 5,000 comments per post and 100,000 rows per run, with a run clock between 30 and 3,600 seconds — ask past any of those and the run still starts, continues at the nearest end of the range, and one uncharged row names what you asked for and what bound it.
How often this data changes
Comments keep arriving on a Facebook post for days after it goes up, and the busiest hours are the first few. So the useful pattern here is not one run — it is the same links again tomorrow. Re-running would otherwise re-buy the comments you already have, so it does not: every run remembers what it delivered to your account, in the key-value store fb-comments-account in your own Apify account, and a later run skips those. Not delivered again, not charged, and the slot goes to the next new comment instead, so you still get the number you asked for. That makes a daily watch on the same posts cost only what is new. A run started with a scoped API token in restricted-access mode needs key-value store Read, Write and Create permission on that store (or Actor runs set to Full access); without it the run says so on its status line and cannot skip what you already have (Write is what lets the run remember what it delivered; without it every run pays again).
Switch Include comments you already have on to get them back anyway, marked repeat: true and still uncharged, and use Skip comments in this dataset to carry the same memory across accounts.
Reliability
The comments come from a licensed data feed rather than from scraping Facebook's own pages, which is why there is nothing to log into and nothing to configure. When that feed cannot answer, the run says so on an uncharged row and finishes successfully — a failed read is never billed and never dressed up as a post with no comments.
Related actors
- The ads an advertiser is running right now: Meta Ad Library rows
- The spoken words inside a Facebook video ad: Facebook ad transcripts
- The same job on Instagram, replies included: Instagram comments
Limits and good manners
Only public posts are returned — a post behind a login, an age gate or a private group is an uncharged post_not_found row, not a workaround. Facebook serves comments in its own ranked order rather than strictly newest-first, so a deep ask on a busy post walks that order and eventually runs out; the run says so instead of padding. This actor may stop working if Facebook changes how the data is served; if it does, items that fail are never charged.
Support
Something off, or a column you need that is not here? Open an issue on the Issues tab — we usually reply within a couple of hours.
If it earned its keep, a rating helps other buyers find it, and saving the actor keeps it one click away.