Facebook Comments Scraper — Posts & Reels
Pricing
from $0.28 / 1,000 saved comment or replies
Facebook Comments Scraper — Posts & Reels
Extract public Facebook post and Reel comments with optional replies. Set separate comment and reply limits, preserve thread links, and collect text, dates, authors and reactions when available. Export JSON, CSV or Excel with Apify for your own analysis.
Pricing
from $0.28 / 1,000 saved comment or replies
Rating
5.0
(1)
Developer
Data Wan
Maintained by CommunityActor stats
3
Bookmarked
2
Total users
2
Monthly active users
20 hours ago
Last modified
Categories
Share
Facebook Comments Scraper for posts and Reels
Collect comments and optional replies from direct public Facebook post and Reel links. Set separate limits for conversation coverage and reply detail, then export structured data for your own analysis.
Why choose this Actor?
- Choose breadth and detail separately. Set independent limits for top-level comments and replies per parent, choosing wider coverage or more detail in each conversation.
- Follow the discussion. Parents and replies stay grouped, with thread and direct-parent links when known, so related responses are easier to interpret.
- Get context for your analysis. Author details, dates, reactions, and media links accompany the text when available; missing information stays
null. - Start with public post links or post IDs. Run through Apify without a Facebook account, login cookies, or proxy configuration.
For one post, the controls work like this:
| Top-level comments | Replies | Maximum rows |
|---|---|---|
| 20 | Off | 20 |
| 20 | Up to 3 per parent | 80 |
| 20 | Up to 10 per parent | 220 |
The reply allowance counts all selected descendants under each top-level comment across nesting levels. These are ceilings; Facebook may expose fewer results. Public group and event posts are supported; private groups and other private content are not, and the Actor never logs in.
Use cases
- Review audience and campaign feedback, including recurring questions.
- Examine online conversations and audience engagement using observed thread links and reactions.
- Supply comment text to your own sentiment-analysis tools; this Actor collects data, while your tool performs the analysis.
For recurring collection, configure an Apify schedule with your chosen post links and limits. The Actor does not discover posts or monitor them automatically.
Quick start
- Add direct public post links to Post URLs, numeric post IDs to Post IDs, or both: 1–100 inputs in total.
- Choose Maximum comments per post and a sorting option. Start with a small selection to inspect the results.
- The prefilled example enables Include replies. Turn it off for top-level comments only, or keep it enabled and set Maximum replies per comment.
- Start the run. Open Output → Comments to inspect the dataset and Run summary to check its outcome.
- Use Export to download JSON, CSV, or Excel. Choose JSON to retain the nested reaction and attachment data.
Use links to individual posts, Reels, videos, or photos: /posts/..., /permalink.php?story_fbid=..., /story.php?story_fbid=..., /reel/..., /videos/..., /watch?v=..., /photo?fbid=..., or /photos/..., and public group or event post links with a numeric post ID: /groups/<group>/posts/<id>, /groups/<group>/permalink/<id>, or /events/<event>/?post_id=<id>. Paste the full URL, including its query parameters. Page/profile home links, group links with a pfbid post ID, and share/short links are not supported inputs. Put bare numeric post IDs in Post IDs, not in Post URLs.
Top-level comments only
This collects up to 20 top-level comments from one public Reel. Replies are excluded.
{"postUrls": ["https://www.facebook.com/reel/1038785062517728"],"maxCommentsPerPost": 20,"sort": "all","includeReplies": false}
By post ID
This collects up to 100 top-level comments from each of two posts named by their numeric IDs.
{"postIds": ["9000000000000001", "9000000000000002"],"maxCommentsPerPost": 100}
Comments with bounded replies
This selects up to 20 top-level comments and up to 10 replies under each: at most 220 rows per post. The reply allowance includes nested descendants across all levels of that thread; it does not reset for each level or nested comment.
{"postUrls": ["https://www.facebook.com/reel/1038785062517728"],"maxCommentsPerPost": 20,"sort": "all","includeReplies": true,"maxRepliesPerComment": 10}
Input options
| Field | Default | What to set |
|---|---|---|
postUrls | [] | Array of public post URLs. Together with postIds: 1–100 inputs. |
postIds | [] | Array of numeric post IDs as strings (digits only). Together with postUrls: 1–100 inputs. |
maxCommentsPerPost | 100 | Integer 1–10,000. Maximum top-level comments per post; replies do not count toward it. |
sort | "all" | "all", "newest", or "most_relevant" for Facebook's top-level comment ordering. |
includeReplies | false | Set true to include selected replies after each parent. |
maxRepliesPerComment | 10 | Integer 1–10,000. Maximum unique descendants under each top-level comment when replies are enabled. |
Apify checks each field before the run starts, including at most 100 items per field and digits-only post IDs. A run with no inputs at all, or more than 100 inputs across both fields, starts and then fails at once with "Input is invalid; check the input fields." without collecting anything.
Limits are ceilings, not promised result counts or measured collection capacity. Sorting changes the requested selection; even all does not guarantee every comment counted by Facebook.
Output data
Each dataset row represents one comment or reply. It includes string IDs and links, text, a UTC date, author information, reaction totals and types, and attachment links when available. Unavailable values stay null. commentId is the numeric comment ID, unique within its post; graphqlId is Facebook's comment node ID, unique across posts. For a post ID input, postUrl is https://www.facebook.com/<post ID>, a reference to the requested post that may not open in a browser.
The following three rows are entirely synthetic, illustrating a parent, its reply, and a reply to that reply. The example URLs and people do not represent collected data.
[{"commentId": "7001","graphqlId": "Y29tbWVudDo5MDAwMDAwMDAwMDAwMDAxXzcwMDE=","commentUrl": "https://www.facebook.com/ExamplePage/posts/9000000000000001?comment_id=7001","rootCommentId": "7001","parentCommentId": null,"threadDepth": 0,"postId": "9000000000000001","postUrl": "https://www.facebook.com/ExamplePage/posts/9000000000000001","text": "Will there be an evening session?","createdAt": "2026-10-20T10:00:00Z","authorId": "8001","authorName": "Example Author","authorUrl": null,"authorAvatarUrl": null,"authorIdIsStable": true,"reactionsCount": 2,"reactionsDisplay": "2","reactionsCapped": false,"repliesCount": 2,"reactions": [{"typeId": "1635855486666999", "typeName": "like", "count": 2}],"attachments": []},{"commentId": "7002","graphqlId": "Y29tbWVudDo5MDAwMDAwMDAwMDAwMDAxXzcwMDI=","commentUrl": "https://www.facebook.com/ExamplePage/posts/9000000000000001?comment_id=7002","rootCommentId": "7001","parentCommentId": "7001","threadDepth": 1,"postId": "9000000000000001","postUrl": "https://www.facebook.com/ExamplePage/posts/9000000000000001","text": "The timetable has an evening option.","createdAt": "2026-10-20T10:05:00Z","authorId": "8002","authorName": "Example Responder","authorUrl": null,"authorAvatarUrl": null,"authorIdIsStable": true,"reactionsCount": null,"reactionsDisplay": null,"reactionsCapped": false,"repliesCount": 1,"reactions": [],"attachments": []},{"commentId": "7003","graphqlId": "Y29tbWVudDo5MDAwMDAwMDAwMDAwMDAxXzcwMDM=","commentUrl": null,"rootCommentId": "7001","parentCommentId": "7002","threadDepth": 2,"postId": "9000000000000001","postUrl": "https://www.facebook.com/ExamplePage/posts/9000000000000001","text": "Thank you!","createdAt": "2026-10-20T10:06:00Z","authorId": null,"authorName": null,"authorUrl": null,"authorAvatarUrl": null,"authorIdIsStable": null,"reactionsCount": null,"reactionsDisplay": null,"reactionsCapped": false,"repliesCount": null,"reactions": [],"attachments": []}]
Rows follow each parent, then its selected direct replies, then deeper known levels, before the next parent. Within a level, replies keep the order Facebook returned them. rootCommentId identifies the thread; parentCommentId identifies the observed direct parent; threadDepth is the resolved level. A real reply can have unknown parent linkage or depth, or refer to a parent absent from the output. Replies with an unknown level follow those with known levels.
Author details use the flat fields authorId, authorName, authorUrl, authorAvatarUrl, and authorIdIsStable. All five are null when the author is unavailable. authorIdIsStable is true for numeric IDs and false for opaque IDs, which may change between sessions.
repliesCount is Facebook's reported count, available even when replies are excluded. It is not the number of replies saved by this run or a guarantee of accessible or direct replies; unknown counts stay null.
Reactions contain type IDs, names, and counts. reactionsCount is null when an exact total is unavailable or capped; reactionsDisplay preserves the source's display text. When reactionsCapped is true, individual reaction counts are lower bounds. Attachments contain kind, links, dimensions, and description when available; media files are not downloaded.
Run summary
Each run also saves a Run summary: the key-value store record OUTPUT, shown under Output → Run summary. It is not a dataset row and is not charged. It holds:
status: the run's result (see below).savedCount, split intosavedCommentsCountandsavedRepliesCount: unique rows saved in the run.warning:"partial_results"when the status ispartialand some input ended with a warning, otherwisenull.warningCountscounts those inputs perreason.items: one entry per input, in order (postUrlsfirst, thenpostIds). Each hasinputIndex;inputUrl(the accepted link,nullfor a post ID or a refused link);inputPostId(nullfor a link);resolvedPostId(the post whose comments were fetched; for a photo's ID, the photo itself or the container post its feedback identifies);duplicateOf; its own saved counts; anoutcome; and areason.
outcome | reason | Meaning and what to do |
|---|---|---|
complete | null | Every available comment within your selection was saved. |
limit_reached | null | Maximum comments per post was reached. More comments may exist; raise the limit to get them. |
duplicate | null | The same post as the earlier input in duplicateOf; its comments are saved once. |
incomplete | no_progress, page_budget, replies_unavailable, no_page_mode, time_budget | Saved rows are valid, but further comments or replies could not be confirmed and may exist. |
incomplete | budget_reached | The run's spending limit was reached; collection stopped. Raise the limit and start a new run for the rest. |
incomplete | interrupted | The run was aborted during this input. |
invalid_url | invalid_url | Not a supported public post link. Fix the input. |
failed | not_public, not_allowed | Anonymous access was unavailable. This does not prove the post is private or has no comments. Check the input and try a fresh run later if access may have changed. |
failed | blocked | Facebook blocked anonymous access; the run stopped. Try again later. |
failed | invalid_cursor, protocol_error, retries_exhausted, stale_doc_id, stale_session, source_error | Comments could not be read. Try again later in a new run; report a failure that repeats. |
failed | storage_failure, internal_error | Saving or processing failed; the run stopped. Start a new run. |
skipped | not_started, blocked, budget_reached, failed | Not processed because the run stopped first; the reason names the stop. Include these inputs in a new run. |
While the run is in progress, the input being collected shows incomplete with collecting, and inputs not reached yet show skipped with not_started. After an abort or a timeout, the summary may still show that state.
The collection status is completed when every input ended complete, limit_reached, or duplicate; partial when some input ended incomplete, failed, or invalid_url but at least one ended complete, limit_reached, or incomplete; failed when none did, or the run itself failed; otherwise a run-wide stop: budget_reached, blocked, or interrupted.
A successful collection with no saved comments reports “Collection completed successfully. 0 comments saved.” A numeric photo can complete with zero rows when Facebook explicitly confirms zero for that photo's own comments. A group or numeric profile post can also complete with zero rows when Facebook supplies consistent evidence that the requested post has no comments. This does not add a dataset row or a result charge. An uncertain empty result stays incomplete. Photo URL resolution is unchanged, so a numeric photo ID can succeed where the corresponding URL cannot be resolved.
For a numeric photo ID, the Actor can confirm a successful zero-comment result from
matching anonymous photo metadata when its normal verification page redirects to login.
It does not log in or follow that redirect. Missing or inconsistent evidence stays
incomplete/no_page_mode, even with zero saved rows. That result does not prove there
are no comments. Photo URLs still require ordinary page resolution; a photo whose
comments belong to another post may remain incomplete on this path. Check each input's
outcome before treating empty rows as a completed collection.
A run can finish SUCCEEDED in Apify while its collection summary says failed: the Actor finished handling the inputs, but comments were unavailable. This includes the access and source failures listed above, with or without saved rows. The final message says “Finished processing inputs. N rows saved; see the run summary for per-input results.” Each failed input keeps its original reason and counts; warningCounts records those reasons even when warning is null. Invalid links may accompany a handled source failure. Check the summary on every run; success alone does not mean a post has no comments or that all its comments were collected.
When anonymous access is unavailable, the diagnostic says “This run could not access the post's comments anonymously.” It describes this attempt and does not establish the post's privacy.
A block, invalid overall input, a selection containing only invalid links, storage or processing failure, or interruption still prevents successful completion. A run can also fail while closing after its summary was saved, so check its status in Apify as well. Acknowledged rows remain available; warnings and failed-input summaries are not comment rows and are not billed as results. Starting another run can collect and bill some of the same rows again.
Export and automate with Apify
Use the data to review campaign responses, identify recurring questions, or supply your own reporting and analysis tools. Sentiment analysis and post discovery are separate from this Actor's collection.
Apify provides saved Tasks and schedules for reusing input and starting recurring runs. Its API can start runs and retrieve results; the Actor's API tab provides usage examples. Integrations and webhooks let you configure workflows with tools such as Make, Zapier, or n8n. Configure these Apify tools to send results to your chosen destination.
Pricing
The result unit is one unique saved comment or reply, with replies counted equally. Invalid links, warnings, and run summaries are not dataset rows. Check the current price and run budget displayed in Apify Console before starting.
Common questions
Why are there fewer results than expected?
Facebook may expose fewer comments than its displayed counter, limit anonymous access, or refuse a post. The prefilled example enables replies; API input that omits includeReplies defaults to false. Your selected limits also affect the total. The Actor stops the batch on a block; it does not log in to recover access.
What happens if collection is partial or fails?
Check Output → Run summary (described under "Run summary" above) for saved totals, warnings, and each input's outcome. A partial collection or a collection with handled source failures can finish successfully while some data is unavailable. A failed run can also contain saved rows. Acknowledged rows remain in the dataset; the summary may be incomplete after abrupt interruption. Other inputs continue after an individual post fails, but a block, a reached run budget, or a storage failure stops later inputs. Before starting a large selection, check the run's time and spending limits in Apify Console; reaching those limits can stop collection.
Support
For help, open an issue in the Actor's Issues tab. Include the run link, input settings, and what you expected compared with what happened.