Facebook Page Posts & Comments Scraper
Pricing
Pay per usage
Facebook Page Posts & Comments Scraper
Automate Facebook page post scraping for text, media, engagement stats, and publish times. Designed for social listening, competitor analysis, and content performance tracking.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
SimpleAPI
Maintained by CommunityActor stats
0
Bookmarked
20
Total users
5
Monthly active users
4 days ago
Last modified
Categories
Share
Facebook Page Posts Scraper — Comments, Reactions and Author Links
Facebook Page Posts Scraper pulls every public post from one or more Facebook Pages and attaches each post's comment thread — and optional replies — as child rows in the same dataset. Each record carries the post message, reactions_count, comments_count, author name and URL, and postCreatedAt, plus likesCount and threadingDepth per comment. Brand teams, social-listening agencies, and researchers use it to see how a Page's audience reacts to specific posts without stitching two tools together. Point it at a Page and the full thread comes back structured.
What is Facebook Page Posts Scraper?
Facebook Page Posts Scraper is an Apify Actor that reads a public Facebook Page's timeline and, for every post it finds, fetches that post's top-level comments and Depth-1 replies. It runs logged out — there is no login, session cookie, or Facebook API key in the input schema; requests go through Facebook's public GraphQL endpoints over residential proxy IPs. Output is a single normalized Apify dataset: one row per post, one child row per comment/reply placed directly after its parent, and one summary row per Page.
- Discovers posts by full Page URL or bare Page handle (
pageUrls) — no page ID lookup required - Returns core post identity:
post_id,message,url,postCreatedAt, authorid/name/url/profile_picture_url - Attaches the comment thread per post, with an independent ceiling on top comments (
maxCommentsPerPost) and on Depth-1 replies (maxRepliesPerComment) - Captures post media:
image,video+video_filesquality variants,album_preview,video_thumbnail,external_url,attached_event,attached_post - Filters posts by date window (
postsFrom/postsUntil) and comments by their own date floor (onlyCommentsNewerThan) - Every comment and reply is also mirrored into a per-run child dataset (
comments-<runId>); the main dataset exports to JSON, CSV, Excel, XML or HTML directly from the Apify Console
What data can I extract with Facebook Page Posts Scraper?
The dataset mixes three row shapes — post content, comment/reply engagement, and a per-page run summary — all in one place so nothing needs to be joined manually.
| Field | Row type | Example value | Use case |
|---|---|---|---|
recordType | all | "post" / "comment" / "page_summary" | Split the dataset into its three row shapes |
post_id | post, comment | "122096543210987654" | Link comments back to their post |
type | post, comment | "photo" / "comment" / "reply" | Segment by media type or comment vs. reply |
url | post, comment | "https://www.facebook.com/RealMadrid/posts/pfbid02Xy7K9dQmN3vLPz" | Direct link to the live post or comment |
message | post, comment | "FULL TIME! Another three points..." | Post or comment text for content/sentiment work |
postCreatedAt | post, comment | "2026-07-20T18:32:04Z" | Chronological sort or freshness check |
postCreatedAtUnix | post | 1784658724 | Numeric timestamp for date-math pipelines |
comments_count | post, comment | 812 | Engagement volume (reply count on comment rows) |
reactions_count | post, comment | 15420 | Reaction volume (like count on comment rows) |
reshare_count | post | 340 | Share/virality signal |
reactions | post | {"like":9200,"love":5900,...} | Reaction-type breakdown (angry/care/haha/like/love/sad/wow) |
author | post, comment | {"id":"104958279561410","name":"Real Madrid C.F.","url":"...","profile_picture_url":"..."} | Author/commenter identity |
image | post | {"uri":"...","height":720,"width":1280} | Single-photo attachment |
video | post | {"id":"","uri":""} | Video attachment reference |
album_preview | post | {"count":1,"images":[...]} | Multi-photo carousel preview |
video_files | post | {"hd":"...","sd":"..."} | Direct video file URLs by quality |
video_thumbnail | post | {"uri":"...","height":720,"width":1280} | Thumbnail for video/album preview |
external_url | post | null | Outbound link shared in the post |
attached_event | post | {"id":"","name":"","url":""} | Linked Facebook Event, when present |
attached_post | post | {"post_id":"","url":"","message":""} | Linked/shared post, when present |
attached_post_url | post | "" | Direct link to the shared post |
isChild | comment | true | Marks a comment/reply row vs. a post row |
isReply | comment | false | Distinguish top-level comments from Depth-1 replies |
parentId | comment | "122096543210987654" | Rebuild the post/comment/reply hierarchy |
commentId | comment | "Y29tbWVudDoxMjIw..." | Unique id per comment/reply |
feedbackId | comment | "ZmVlZGJhY2s6MTIy..." | Internal thread id used for pagination |
commentUrl | comment | "https://www.facebook.com/.../?comment_id=..." | Direct link to the comment |
text | comment | "Vamos Madrid!" | Comment/reply body |
commentCreatedAt | comment | "2026-07-20T19:02:11Z" | When the comment/reply was posted |
likesCount | comment | 214 | Comment-level engagement |
repliesCount | comment | 6 | How many replies a comment has |
authorName | comment | "Jane Doe" | Commenter display name |
threadingDepth | comment | 0 | Nesting level — 0 comment, 1 reply |
profileUrl | post, comment, summary | "https://www.facebook.com/RealMadrid/" | Which Page the row came from |
scrapedAt | post, comment | "2026-07-26T09:12:00Z" | Extraction timestamp for freshness audits |
postsCollected | page_summary | 20 | How many posts were saved for this Page |
maxPostsPerProfile | page_summary | 20 | The post cap that was applied |
startDate / endDate | page_summary | "7 days" / "" | Which date window was requested |
error | page_summary | null | Whether the page failed, and why |
Comment and reply engagement data
Every comment and reply lands as a child row directly beneath its post, carrying commentId, feedbackId, likesCount, repliesCount, threadingDepth and parentId. Top-level comments have isReply: false and parentId equal to the post's post_id; Depth-1 replies have isReply: true and parentId equal to their parent comment's commentId, so the full tree reconstructs from those two fields alone. A common use is sorting a post's comments by likesCount to surface the top comment, or comparing comments_count against reactions_count on the post row to spot posts drawing disproportionate reply volume — a common signal for controversy or high engagement.
Targeting and date-window data
postsFrom/postsUntil scope which posts are pulled by postCreatedAt, independent of onlyCommentsNewerThan, which scopes comments and replies by their own commentCreatedAt — so you can pull a Page's full post history while keeping only this week's comments. maxPostsPerPage, maxCommentsPerPost and maxRepliesPerComment control volume, and profileUrl lets downstream steps segment rows back out by source Page when multiple Pages are scraped in one run.
How does Facebook Page Posts Scraper differ from the official Facebook API?
Meta's own documentation states that "Page access tokens are unique to each Page, admin, and app combination" (developers.facebook.com/docs/pages/access-tokens/, checked 2026-07-26) — Graph API access to a Page's posts and comments is tied to that specific Page, admin, and app, not open access to any public Page you don't manage.
| Feature | Facebook Graph API | Facebook Page Posts Scraper |
|---|---|---|
| Access to a Page's own posts/comments | Requires a token tied to that Page, admin, and app | Reads any public Page from just its URL or handle, no token |
| Setup | Facebook Developer app + Page token (App Review for extended permissions) | Paste a Page URL/handle in pageUrls and run |
| Comment thread depth | Bounded by whatever the token's granted permissions expose | maxCommentsPerPost + maxRepliesPerComment set independently, per run |
| Output shape | Raw Graph API JSON per the fields your permissions allow | Normalized post + comment/reply child rows in one Apify dataset |
| Post/comment date scoping | Left to the caller to implement | Built-in postsFrom/postsUntil and onlyCommentsNewerThan filters |
| Credentials needed | Facebook Developer account + app + Page token | None — no Facebook login or key |
Why does the Graph API require Page-token ownership?
Because a Page access token is minted per Page-admin-app combination, pulling posts and comments from a Page you don't administer means its admin must grant your app access, or your app must pass Meta's App Review for broader public content permissions — a real barrier for monitoring competitor or industry Pages at scale. Facebook Page Posts Scraper covers that gap by reading only what the Page already renders publicly over logged-out requests, so no token, app registration, or admin relationship is needed.
Use the Graph API when you manage the Page and need to publish or moderate through your own app. Use this Actor when you need structured posts and comments from public Pages you don't administer.
How to use data extracted from Facebook?
Brand and Page monitoring
Point pageUrls at your own Page (or a competitor's), set postsFrom to the last week or month, and turn includeComments on. Each run returns every post's message, reactions_count and comments_count alongside the comment thread's text and likesCount, so a marketing team can see which posts are drawing engagement and what the audience is actually saying underneath, without opening Facebook manually. The dataset exports straight to CSV or Excel for a weekly report.
Social listening agencies
Agencies running the same extraction across a client roster set one pageUrls entry per client Page and re-run on a schedule. Comparing postCreatedAt, reactions_count and comments_count across runs surfaces which client posts are outperforming, and authorName/text on comment rows shows recurring themes in audience feedback — useful for a recurring engagement digest delivered to each client.
Market research and intelligence
Aggregating reactions_count and comments_count across a Page's post history, segmented by type (photo vs. video) and by the postsFrom/postsUntil window, shows which content format and posting cadence a Page's audience responds to best — useful for planning a competitor's content calendar or benchmarking category norms before launching a similar Page.
AI agents and automated pipelines
message and comment text feed directly into summarization or RAG pipelines that need current, real public-Page conversation as context. An agent framework can call the Actor as a tool, request the latest posts for a watchlist of Pages, and pass back structured JSON — reactions_count, comments_count, and comment sentiment context — for automated reporting without any scraping code of its own.
🔼 Input sample
All 9 parameters are optional — the Actor runs with defaults if you provide nothing but pageUrls.
| Parameter | Required | Type | Description | Example value |
|---|---|---|---|---|
pageUrls | No | array | Full Page link or bare Page handle, one per entry. | ["https://www.facebook.com/RealMadrid/"] |
maxPostsPerPage | No | integer | Post threads to open per Page (1–5000). Default 20. | 20 |
postsFrom | No | string | Earliest post to include — calendar date or relative (7 days, 2 weeks). | "7 days" |
postsUntil | No | string | Latest post to include — calendar date or relative (0 days = today). | "" |
includeComments | No | boolean | Attach the comment thread to each post. Default true. | true |
maxCommentsPerPost | No | integer | Top comments per post; 0 = unlimited. Default 10. | 10 |
maxRepliesPerComment | No | integer | Depth-1 replies per comment; 0 = none. Default 0. | 0 |
onlyCommentsNewerThan | No | string | Keep only comments/replies posted on or after this date/window. | "" |
proxyConfiguration | No | object | Apify residential proxy by default; your URLs first with residential fallback. | {"useApifyProxy": true} |
{"pageUrls": ["https://www.facebook.com/RealMadrid/", "NASA"],"maxPostsPerPage": 20,"postsFrom": "7 days","postsUntil": "","includeComments": true,"maxCommentsPerPost": 10,"maxRepliesPerComment": 3,"onlyCommentsNewerThan": "","proxyConfiguration": { "useApifyProxy": true }}
Common pitfall: maxRepliesPerComment defaults to 0, which means replies are silently skipped even when includeComments is on and maxCommentsPerPost is high. If you need nested replies, set maxRepliesPerComment explicitly — comments and replies are both additional to maxPostsPerPage, never subtracted from it.
🔽 Output sample
Each run pushes typed, normalized JSON rows to one dataset: a post row, its comment/reply child rows right after it, and a page_summary row per Page. Export from the Apify Console as JSON, CSV, Excel, XML or HTML.
Post row:
{"recordType": "post","post_id": "122096543210987654","type": "photo","url": "https://www.facebook.com/RealMadrid/posts/pfbid02Xy7K9dQmN3vLPz","message": "FULL TIME! Another three points at the Bernabéu. Thanks for the support, Madridistas!","postCreatedAt": "2026-07-20T18:32:04Z","postCreatedAtUnix": 1784658724,"comments_count": 812,"reactions_count": 15420,"reshare_count": 340,"reactions": {"angry": 12, "care": 45, "haha": 8, "like": 9200, "love": 5900, "sad": 5, "wow": 250},"author": {"id": "104958279561410","name": "Real Madrid C.F.","url": "https://www.facebook.com/RealMadrid/","profile_picture_url": "https://scontent.xx.fbcdn.net/v/t39.../profile.jpg"},"image": {"uri": "https://scontent.xx.fbcdn.net/v/t39.../photo.jpg", "height": 720, "width": 1280},"video": {"id": "", "uri": ""},"album_preview": {"count": 1, "images": [{"uri": "https://scontent.xx.fbcdn.net/v/t39.../photo.jpg", "height": 720, "width": 1280}]},"video_files": {},"video_thumbnail": {"uri": "https://scontent.xx.fbcdn.net/v/t39.../photo.jpg", "height": 720, "width": 1280},"external_url": null,"attached_event": {"id": "", "name": "", "url": ""},"attached_post": {"post_id": "", "url": "", "message": ""},"attached_post_url": "","profileUrl": "https://www.facebook.com/RealMadrid/","scrapedAt": "2026-07-26T09:12:00Z"}
Comment child row (pushed immediately after its post):
{"recordType": "comment","type": "comment","isChild": true,"isReply": false,"parentId": "122096543210987654","post_id": "122096543210987654","commentId": "Y29tbWVudDoxMjIwOTY1NDMyMTA5ODc2NTRfMTIzNDU2Nzg5","feedbackId": "ZmVlZGJhY2s6MTIyMDk2NTQzMjEwOTg3NjU0","url": "https://www.facebook.com/RealMadrid/posts/pfbid02Xy7K9dQmN3vLPz?comment_id=123456789","commentUrl": "https://www.facebook.com/RealMadrid/posts/pfbid02Xy7K9dQmN3vLPz?comment_id=123456789","message": "Vamos Madrid!","text": "Vamos Madrid!","postCreatedAt": "2026-07-20T19:02:11Z","commentCreatedAt": "2026-07-20T19:02:11Z","reactions_count": 214,"comments_count": 6,"likesCount": 214,"repliesCount": 6,"author": {"id": "618203945712","name": "Jane Doe","url": "https://www.facebook.com/jane.doe.984","profile_picture_url": "https://scontent.xx.fbcdn.net/v/t39.../jane.jpg"},"authorName": "Jane Doe","threadingDepth": 0,"profileUrl": "https://www.facebook.com/RealMadrid/","scrapedAt": "2026-07-26T09:14:32Z"}
Pay-per-event note: post and comment/reply rows are each charged once as row_result. The per-page page_summary row is informational only and is not charged — filter it out with recordType !== "page_summary" if you're reconciling row counts against your charge history.
How do you filter and target specific posts/comments?
Two independent date windows do most of the targeting work here: postsFrom/postsUntil scope which posts come back, while onlyCommentsNewerThan separately scopes which comments and replies come back — you can pull a Page's entire post history while keeping only recent comments, or vice versa. For Page identity, a full URL (https://www.facebook.com/RealMadrid/) is more precise than a bare handle, since a handle resolves against whatever vanity slug the Page currently uses; profile.php?id=... links are also accepted and resolved as-is.
Volume is controlled at three levels: maxPostsPerPage (1–5000) caps posts per Page, maxCommentsPerPost caps top-level comments per post (0 = unlimited), and maxRepliesPerComment caps Depth-1 replies per comment (0 = none, the default). These three multiply — a high comment cap with replies enabled on a Page with many posts will produce a large run, so raise them deliberately. Pagination between requests follows Facebook's own cursor tokens under the hood, so increasing maxPostsPerPage walks further back through the timeline automatically instead of requiring you to manage cursors or page tokens yourself. One real limitation to plan around: there's no keyword, rating, or sentiment filter on comments — every comment within your caps is returned regardless of content, so relevance filtering has to happen downstream, not in the input itself.
{ "pageUrls": ["RealMadrid"], "maxPostsPerPage": 50, "postsFrom": "2026-07-01", "postsUntil": "2026-07-25", "maxCommentsPerPost": 5, "maxRepliesPerComment": 0 }
{ "pageUrls": ["https://www.facebook.com/RealMadrid/"], "maxPostsPerPage": 10, "includeComments": true, "maxCommentsPerPost": 0, "maxRepliesPerComment": 10 }
{ "pageUrls": ["RealMadrid"], "maxPostsPerPage": 200, "includeComments": true, "maxCommentsPerPost": 0, "onlyCommentsNewerThan": "7 days" }
▶️ Want to try other Facebook scrapers?
| Scraper | What it extracts |
|---|---|
| Facebook Comments Scraper: Sentiment & Toxicity Analysis | Comments pulled from direct post URLs, enriched with language detection, a moderation flag, and optional AI sentiment/toxicity scoring |
| Facebook Posts Scraper: Performance Analyzer | Multiple Pages' timelines benchmarked against each other — average reactions/comments, engagement score, share-of-voice and growth deltas |
| Facebook Posts Search Scraper | Public posts discovered by keyword search across Facebook, rather than from a known Page |
| Facebook Group Post With Top Contributors Scraper | Group posts aggregated into a per-member leaderboard of post/comment counts and reactions received |
| Facebook Photos Scraper & High-Res Photo Export | Every resolution variant of a public photo, with optional one-click full-resolution download |
| Facebook Marketplace: Listing Location Details Scraper | Marketplace listings mapped by geography, with latitude, longitude, city, state and region per listing |
How to extract Facebook data programmatically
Facebook Page Posts Scraper runs through the standard Apify API — one endpoint call with your API token in the Authorization header returns a run, and its dataset comes back as structured JSON.
Python example
from apify_client import ApifyClientclient = ApifyClient("<APIFY_API_TOKEN>")run = client.actor("SimpleAPI/facebook-page-posts-comments-scraper").call(run_input={"pageUrls": ["https://www.facebook.com/RealMadrid/"],"maxPostsPerPage": 30,"includeComments": True,"maxCommentsPerPost": 10,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():if item.get("recordType") == "post":print(item["post_id"], item["message"][:60], item["reactions_count"])elif item.get("recordType") == "comment":print(" ->", item["authorName"], item["text"][:60], item["likesCount"])
Export to spreadsheets or CRM
Use the Apify Console's export button (or the API's dataset export endpoint) to pull results as CSV or Excel. Map message/text to a Notes column, authorName to Contact Name, reactions_count/comments_count to engagement columns, and url/commentUrl to a Source Link column — the file imports directly into a spreadsheet or CRM without reshaping.
Is it legal to scrape Facebook page posts and comments?
Yes — Facebook Page Posts Scraper only collects public posts and comments that Facebook already renders to any logged-out visitor of a Page, the same content anyone can read without an account. That said, comment rows include commenter names and profile URLs, which are personal data: storing or reusing them commercially falls under GDPR and CCPA, so you need a lawful basis before retaining or processing that data at scale, and reasonable retention/deletion practices. Post-only extraction with includeComments off avoids collecting personal data about individual commenters entirely. Consult legal counsel for commercial applications involving bulk storage of personal data.
❓ FAQ
What happens if a post or comment is edited or deleted after I scrape it?
The Actor has no staleness flag — every run reads whatever Facebook renders publicly at request time. If a post is deleted or a comment is removed between runs, the next run simply won't return it; re-run on a schedule if you need to detect changes over time.
Can I get comment data along with the main post records?
Yes, by default — includeComments is true, so every post is followed by its comment (and, if maxRepliesPerComment is raised, reply) child rows in the same dataset. Coverage from a logged-out session is a subset of what a logged-in view can page through; the Actor reports only what Facebook's public GraphQL actually returns, capped by maxCommentsPerPost and maxRepliesPerComment.
How accurate is the author and engagement data?
The Actor returns reactions_count, comments_count, likesCount and author fields exactly as Facebook serves them at request time. Accuracy reflects the live state of the Page — reaction and comment counts change continuously, so treat the numbers as a snapshot and re-run for a refresh rather than assuming a single run stays accurate indefinitely.
How many records can I get per run?
maxPostsPerPage accepts 1–5000 posts per Page. maxCommentsPerPost defaults to 10 top comments per post (0 = unlimited), and maxRepliesPerComment defaults to 0 replies per comment. These multiply across however many Pages you list in pageUrls, so total row count scales with all three settings together — there is no separate overall run cap in the input schema.
Can I filter comments to a different date window than the posts?
Yes — postsFrom/postsUntil scope which posts are collected, and onlyCommentsNewerThan is a completely separate date floor applied only to comments and replies. This lets you pull a Page's full post archive while only keeping this week's comments, or any other combination of the two windows.
Does it capture replies nested more than one level deep?
No — maxRepliesPerComment fetches Depth-1 replies only, the single level of replies directly under each top-level comment. Deeper nested reply chains within those replies are not expanded further.
Does Facebook Page Posts Scraper work with Claude, ChatGPT and AI agent frameworks?
Yes, as an HTTP endpoint — the Actor is callable through the standard Apify API from any agent framework capable of making an authenticated API call, passing pageUrls and the other parameters as JSON and reading the dataset back the same way.
How does Facebook Page Posts Scraper compare to other Facebook comment scrapers in this collection?
Facebook Page Posts Scraper is built around a Page (pageUrls) and returns the full post-plus-thread structure in one normalized dataset. Facebook Comments Scraper: Sentiment & Toxicity Analysis instead starts from direct post URLs and adds language/moderation/AI scoring on top of each comment — pick that one when the job is comment moderation and analysis rather than raw thread extraction by Page.
Can I use it without a Facebook API key or developer account?
Yes — there is no Facebook login, session cookie, or API key field anywhere in the input schema. The Actor runs logged out through Apify's residential proxy by default; you only need an Apify account to start the run.
Conclusion
Facebook Page Posts Scraper turns a Facebook Page into a structured dataset of posts and their comment threads in one run, without a Facebook login, developer app, or a second tool for comments. It fits brand monitoring, social-listening agencies, and market research teams who need message, reactions_count, comments_count and author identity fields ready to filter and export. Set pageUrls, tune the post and comment ceilings, and run it directly from the Apify Console or API to get your first dataset.
