Facebook Group Posts & Details Scraper : Comment & Engagement
Pricing
$19.99/month + usage
Facebook Group Posts & Details Scraper : Comment & Engagement
Scrape Facebook Group posts and full post details at scale. Collect text, images, timestamps, reactions, comments, authors, and engagement metrics. Ideal for community research, sentiment analysis, lead generation, and trend tracking. Export structured data in JSON, CSV, or Excel.
Pricing
$19.99/month + usage
Rating
0.0
(0)
Developer
Scraper Engine
Maintained by CommunityActor stats
2
Bookmarked
9
Total users
0
Monthly active users
4 days ago
Last modified
Categories
Share
Facebook Group Posts Scraper — Comments, Replies and Analytics
Facebook Group Posts Scraper extracts public Facebook group posts, group profile details, threaded comments and replies, and locally-computed engagement analytics — all returned as clean, structured JSON. Each run captures post text, author, timestamp and permalink alongside group name, privacy and member count, then goes one level deeper into comment threads and per-group posting activity. No login, cookies, or Facebook API key required. Add a group URL below and start a run to see it in action.
❓ What is Facebook Group Posts Scraper?
Facebook Group Posts Scraper is an Apify Actor that pulls posts, group profile details, comments, and reply threads from public Facebook groups, then adds a locally computed engagement-analytics summary per group. It reads directly from Facebook's public, logged-out group and post pages — no Facebook account, login, or API token is needed. It outputs typed JSON rows, built for developers, market researchers, and community managers who need structured Facebook group data without manually clicking through group feeds.
🔓 What Facebook group data is publicly available to scrape?
Anyone can view a public Facebook group's posts, comments, and basic profile details without logging in — that public surface is exactly what Facebook Group Posts Scraper reads.
| Data Category | Publicly available (no login) | Gated behind group membership / login |
|---|---|---|
| Group name, description, cover photo | Yes | — |
| Rounded member count (e.g. "6.0M members") | Yes, rounded only | Exact member count — never exposed to anonymous viewers |
| Group founding/creation date | Not exposed on the anonymous group page | — |
| Posts in a public group — text, author, permalink | Yes | Posts inside private/closed groups |
| Comments and nested replies on a public post | Yes — what Facebook server-renders to an anonymous viewer | Full comment history beyond what's rendered/paginated |
| Member list / individual member profiles | No | Yes — group membership |
| Group chat / direct messages | No | Never publicly accessible |
Facebook Group Posts Scraper only returns publicly visible data — what any logged-out visitor sees. Nothing behind a login wall.
📚 What data can I extract with Facebook Group Posts Scraper?
Facebook Group Posts Scraper writes four kinds of rows into one dataset — group posts, group profile fields (piggybacked on each post row), threaded comments/replies, and a per-group engagement-analytics summary — each tagged with a type field so they're easy to filter.
📝 Post and group profile fields
| Field Name | Description |
|---|---|
id | Facebook's internal post ID, used to build the permalink and as the parentId for that post's comments |
type | Row type — "post" for a group post row |
isChild | false for a post row (only true for comment/reply rows) |
parentId | null for a post row |
postText | The post's own text/body |
postAuthor | Display name of the post's author |
postAuthorId | Facebook's internal profile ID for the author (numeric, or a privacy-preserving pfbid… ID) |
postAuthorUrl | Best-effort profile URL, built from postAuthorId or the author's short name |
firstName / lastName | Best-effort split of the author's display/short name |
image | First image URL found on the post (typically the author's profile picture or an attached photo) |
postUrl | Full permalink to the post |
publishedAt | ISO-8601 UTC timestamp the post was published |
groupUrl | Canonical URL of the source group |
groupName | Group's display name |
groupVanity | Group's vanity URL/address, if any |
groupPrivacy | The privacy label shown on the group page (e.g. "Public group") |
groupMemberCountText | Rounded member-count string exactly as Facebook shows it |
groupMemberCountApprox | Best-effort integer parsed from groupMemberCountText |
groupDescription | Group's public description |
groupCreatedAt | ISO-8601 date the group was founded, when Facebook exposes it — null otherwise, never guessed |
groupCoverPhotoUrl | URL of the group's cover photo |
scrapedAt | ISO-8601 UTC timestamp the row was scraped |
💬 Comment and reply fields
| Field Name | Description |
|---|---|
id | Facebook's internal comment/reply ID |
type | "comment" for a top-level comment, "reply" for a nested reply |
isChild | Always true for comment/reply rows |
parentId | The post ID for a top-level comment, or the parent comment's ID for a reply |
postId | ID of the post the comment belongs to |
postUrl | Permalink of the parent post |
groupUrl | Canonical URL of the source group |
threadingDepth | Nesting depth (0 = top-level comment, 1+ = nested reply) |
feedbackId | Facebook's internal feedback-object ID for the comment |
date | ISO-8601 UTC timestamp the comment/reply was posted |
text | Comment or reply body text |
profilePicture | URL of the commenter's profile picture |
profileId | Facebook's internal profile ID for the commenter |
profileName | Commenter's display name |
profileUrl | Commenter's profile URL, when Facebook exposes one |
likesCount | Number of reactions on the comment/reply |
repliesCount | Number of replies Facebook reports for that comment |
facebookId | Legacy numeric Facebook ID for the comment, when present |
scrapedAt | ISO-8601 UTC timestamp the row was scraped |
📈 Engagement analytics fields (one summary row per group)
| Field Name | Description |
|---|---|
id | Stable hash-based ID for the group's analytics row |
type | Always "analytics" |
groupUrl / groupName | The group the analytics row summarizes |
totalPostsAnalyzed | Number of posts collected this run for the group |
topContributors | Up to 5 authors ranked by post count this run — [{authorId, authorName, postCount}] |
postingCadenceEstimate | Posts/day implied by the timestamp spread of posts collected this run; null if fewer than 2 timestamped posts or the span is zero |
totalCommentsCollected | Total comments + replies collected this run for the group |
commentsPerPost | totalCommentsCollected / totalPostsAnalyzed, rounded to 3 decimals; null if there are no posts |
scrapedAt | ISO-8601 UTC timestamp the row was built |
🤖 Add-on: Need additional Facebook or community data?
If you also need public Facebook event listings, pair this with Facebook Events Scraper, which turns search keywords into structured event data (names, dates, locations, attendance signals). For a similar "who's active in this community" question on a different platform, Reddit Subreddit Members Scraper surfaces active subreddit participants the same way this Actor surfaces active Facebook group contributors via topContributors.
🛠️ Why not build this yourself?
Facebook's own Graph API does not offer a public, unauthenticated endpoint for arbitrary group posts and comments — group content access is limited to app-reviewed permissions scoped to groups your app manages, so it isn't a substitute for reading public content across many independent groups you don't administer.
Building this yourself means reverse-engineering Facebook's internal contracts and keeping up with their drift: this Actor resolves each group's internal ID and GraphQL query ID (doc_id) directly from the page's own HTML and JS bundles, because Facebook doesn't publish them; a secondary "load more comments" GraphQL pass is attempted for deeper comment coverage but can fail with Facebook's missing_required_variable_value error when Facebook's own variable contract shifts — a real, live-observed schema-drift condition, not a bug in the request. On top of that, every request needs a residential-proxy-backed session with retry and backoff logic to avoid anti-bot blocking. Facebook Group Posts Scraper maintains all of that so you don't have to.
🚀 How to use Facebook Group Posts Scraper
Run it directly from the Apify Store — no separate signup or API key beyond your Apify account is required.
- Open the Actor's page in Apify Console and click Try for free / Start.
- Add at least one entry to
startUrls— a full group URL or a bare group identifier (required). - Optionally set
maxPosts,sortOrder,startDate,monitoringMode, and the comment/analytics toggles. - Start the run.
- Download or stream results as JSON, CSV, Excel, or XML from the run's dataset, or pull them via the Apify API.
How to scale to bulk group extraction
startUrls accepts an array — add as many group URLs or identifiers as you need in a single run. maxPosts is one global cap: it's split evenly across every group in startUrls (with any remainder distributed one-by-one), each group's posts are collected against its own share, and the combined results are merged and capped again at your maxPosts value.
💡 What can you do with Facebook group data?
- 📊 Community managers monitoring group health use
topContributorsandpostingCadenceEstimateto see who's actually driving activity and how often the group posts, without opening it in a browser. - 🔬 Researchers studying group discourse use
postText,text, andthreadingDepthto reconstruct full comment trees for qualitative analysis. - 📈 Marketing teams use
groupMemberCountApproxandcommentsPerPostacross multiple groups in onestartUrlsrun to compare engagement levels before deciding where to run a campaign. - 🕵️ Lead researchers use
postAuthor,postAuthorId, andpostAuthorUrlto identify the members most active in a niche public group. - 🤖 AI engineers feed
postText,text, andgroupDescriptioninto a RAG pipeline or an LLM summarizer to generate a digest of what a community group has been discussing.
🛡️ How does Facebook Group Posts Scraper handle rate limits and blocking?
Every request — group pages, post permalinks, and comment fetches — routes through Apify Proxy, defaulting to the residential proxy group; if a managed proxy session can't be created, the Actor retries up to 3 times before falling back to a direct connection with a logged warning. GraphQL and HTML requests retry up to 3 times with increasing backoff on connection errors and on retryable HTTP status codes (408, 429, 500, 502, 503, 504). Feed pagination for a group gives up after 8 consecutive pages produce no new posts or cursor movement, and group-metadata resolution (the group's internal ID and GraphQL query ID) is retried up to 4 times across Facebook's www/m/bare-domain URL variants before that group is treated as unreachable.
⚠️ One real limitation worth knowing: if a group's metadata can't be resolved after those retries, that failure is not isolated per group — it can end the whole run's post collection and gets logged as a temporary issue, since group fetching runs concurrently and an unhandled error from one group propagates to the run. Per-post comment fetches, by contrast, are isolated — a failed comment fetch just yields zero comments for that post, never a failed run.
⬇️ Input
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
startUrls | Yes | array | Facebook group URLs or bare group identifiers. Add multiple to scrape several groups in one run. | ["https://www.facebook.com/groups/cheapmealideas"] |
maxPosts | No | integer | Global post cap across the whole run (minimum 10, default 10). With multiple startUrls, split across groups and the merged result is capped at this value. | 50 |
sortOrder | No | string (enum: RECENT_POSTS, TOP_POSTS, RECENT_ACTIVITY, CHRONOLOGICAL) | Sorting strategy for the group feed. Default RECENT_ACTIVITY. | "RECENT_ACTIVITY" |
startDate | No | string (date, YYYY-MM-DD) | Only scrape posts newer than this date. Leave empty to scrape all available posts. | "2026-02-20" |
monitoringMode | No | boolean | When true, remembers seen post IDs (via the Apify Key-Value Store) and skips duplicates on future runs. Default false. | false |
includeComments | No | boolean | Fetch each post's comments + nested replies into a separate child dataset. Default true. | true |
maxCommentsPerPost | No | integer | Cap on top-level comments collected per post (minimum 0, default 20). 0 disables comment fetching even if includeComments is on. | 20 |
maxRepliesPerComment | No | integer | Cap on nested replies collected per top-level comment (minimum 0, default 5). Ignored when includeComments is off. | 5 |
commentsSortOrder | No | string (enum: all, newest, most_relevant) | Order applied to top-level comments before the maxCommentsPerPost cap. Default all (original order). Nested reply order is not re-sorted — it follows Facebook's own rendering order. | "all" |
includeEngagementAnalytics | No | boolean | Add one locally-computed analytics summary row per group. Default true. | true |
proxyConfiguration | No | object | Apify Proxy settings, used for every request this Actor makes. Defaults to residential. | {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} |
Example input
{"startUrls": ["https://www.facebook.com/groups/cheapmealideas","germtheory.vs.terraintheory"],"maxPosts": 50,"sortOrder": "RECENT_ACTIVITY","startDate": "2026-02-20","monitoringMode": false,"includeComments": true,"maxCommentsPerPost": 20,"maxRepliesPerComment": 5,"commentsSortOrder": "most_relevant","includeEngagementAnalytics": true,"proxyConfiguration": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"]}}
⬆️ Output
Every row is typed, normalized JSON with a consistent schema across runs. Posts, comments, replies, and per-group analytics all land in the same default dataset (tagged by type and isChild), and comment/reply rows are additionally mirrored into a separate per-run child dataset. Results can be exported as JSON, CSV, Excel, XML, or RSS directly from the run's dataset in Apify Console, or pulled programmatically via the Apify API.
Every row pushed to the dataset — post, comment, reply, or analytics — is charged as one row_result event. Rows that fail to save due to a transient error are not written to the dataset at all, so there is no separate uncharged/error row type to filter out.
Example output
Post row:
{"id": "28288689954096804","type": "post","isChild": false,"parentId": null,"postText": "Ground turkey cooked in a pan and then you add stir fry veggies...","postAuthor": "Jane Doe","postAuthorId": "100048765312428","postAuthorUrl": "https://www.facebook.com/profile.php?id=100048765312428","firstName": "Jane","lastName": "Doe","image": "https://scontent.xx.fbcdn.net/v/t39.30808-6/example.jpg","postUrl": "https://www.facebook.com/groups/cheapmealideas/posts/28288689954096804/","publishedAt": "2026-07-31T14:23:03Z","groupUrl": "https://www.facebook.com/groups/cheapmealideas","groupName": "Cheap Meal Ideas","groupVanity": "cheapmealideas","groupPrivacy": "Public group","groupMemberCountText": "6.0M members","groupMemberCountApprox": 6000000,"groupDescription": "This group is open for anyone to join or share with others...","groupCreatedAt": null,"groupCoverPhotoUrl": "https://scontent.xx.fbcdn.net/v/t39.30808-6/cover.jpg","scrapedAt": "2026-08-02T09:00:00Z"}
Comment row (also written to the child dataset):
{"id": "Y29tbWVudDoyODI4ODY4OTk1NDA5NjgwNF8yODMwMzk0MzM3NTkwNDc5NQ==","type": "comment","isChild": true,"parentId": "28288689954096804","postId": "28288689954096804","postUrl": "https://www.facebook.com/groups/cheapmealideas/posts/28288689954096804/","groupUrl": "https://www.facebook.com/groups/cheapmealideas","threadingDepth": 0,"feedbackId": "ZmVlZGJhY2s6MjgyODg2ODk5NTQwOTY4MDQ=","date": "2026-07-31T22:14:15Z","text": "Ground turkey cooked in a pan and then you add stir fry veggies...","profilePicture": "https://scontent.xx.fbcdn.net/v/t1.6435-1/profile.jpg","profileId": "100093827465210","profileName": "CarefreeLlama2513","profileUrl": null,"likesCount": 2,"repliesCount": 0,"facebookId": "","scrapedAt": "2026-08-02T09:00:05Z"}
Analytics row (one per group):
{"id": "analytics-7f3a91c2b6d4e8a1","type": "analytics","isChild": false,"parentId": null,"groupUrl": "https://www.facebook.com/groups/cheapmealideas","groupName": "Cheap Meal Ideas","totalPostsAnalyzed": 30,"topContributors": [{ "authorId": "100048765312428", "authorName": "Jane Doe", "postCount": 4 }],"postingCadenceEstimate": 6.2,"totalCommentsCollected": 187,"commentsPerPost": 6.233,"scrapedAt": "2026-08-02T09:04:11Z"}
⚙️ How does it work?
Facebook Group Posts Scraper sends requests through Apify Proxy (residential by default) directly to Facebook's own public GraphQL endpoint and public HTML pages, using headers that mirror a real browser session — no headless browser rendering is used. Because Facebook doesn't publish stable identifiers for its internal group-feed and comment-pagination queries, the Actor resolves each group's internal ID and GraphQL query ID by scanning the group page's own HTML and linked JS bundles at request time, the same way a browser's own client would load them. Group profile fields (name, description, member count, cover photo) come from the same page fetch, parsed from Facebook's own embedded metadata rather than guessed. Only what an anonymous, logged-out visitor could see is ever returned, and the output field names stay the same run to run — they're derived from Facebook's own data structures, not from whatever the page happens to render visually.
🔌 Integrations
Facebook Group Posts Scraper runs on the Apify platform, so it works with everything already built around the Apify API.
Calling Facebook Group Posts Scraper programmatically
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_API_TOKEN>")run_input = {"startUrls": ["https://www.facebook.com/groups/cheapmealideas"],"maxPosts": 30,"includeComments": True,}run = client.actor("<your-username>/facebook-group-posts-and-details-scraper-comments-analytics").call(run_input=run_input)for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item)
Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request.
No-code tools (n8n, Make)
In n8n, use the HTTP Request node (or the Apify node) pointed at this Actor's run endpoint on the Apify API to trigger a run and pull dataset items into your workflow. In Make, use Apify's HTTP module the same way — call the run endpoint, then fetch the resulting dataset items as the next step in your scenario.
⚖️ Is it legal to scrape Facebook groups?
Scraping publicly accessible Facebook group posts and comments is generally legal — this Actor only reads pages Facebook already serves to a logged-out, anonymous visitor, the same content anyone can see without an account. Facebook Group Posts Scraper returns only that publicly available data.
Because group posts and comments carry personal data about named individuals — post authors, commenters, and their profile links — storing or reusing this data can fall under data-protection law such as the EU/UK GDPR and the California CCPA, which require a lawful basis for collecting and retaining personal data regardless of whether the source was public. Facebook's Terms of Service separately restrict automated data collection. Consult legal counsel if your use case involves bulk storage of personal data.
❓ Frequently asked questions
What Facebook group post fields does Facebook Group Posts Scraper return?
The top fields are postText, postAuthor, postAuthorUrl, publishedAt, and groupMemberCountApprox — see What data can I extract for the full list across posts, comments, and analytics rows.
Does Facebook Group Posts Scraper require a Facebook account or login?
No. It reads public, logged-out group and post pages — no Facebook account, cookies, or API token are needed. The only credential involved is your Apify account for running the Actor.
How many posts can I extract in one run?
maxPosts has a minimum of 10 but no fixed maximum in the input schema. Internally, the Actor paginates a group's feed for at least 120 pages (scaling higher for larger requests) before giving up, and in monitoringMode it deliberately over-fetches — up to 2,500 raw posts per group — to reliably find unseen posts before applying your cap.
What happens if a group URL is private, invalid, or can't be resolved?
The Actor retries resolving that group's metadata up to 3 times before giving up on it. If it still can't be resolved, that error is not isolated to the failed group — because groups are fetched concurrently, it can end the entire run's post collection and gets logged as a temporary issue. Double-check that each startUrls entry points to a public group before running with several groups at once.
Can I scrape multiple Facebook groups at once?
Yes — add multiple entries to startUrls. maxPosts is a single total shared across all of them, split evenly (with remainders distributed one-by-one) before the merged results are capped again.
Does Facebook Group Posts Scraper work with Claude, ChatGPT, and other AI agent tools?
It's not exposed through a dedicated MCP server, but it's callable as a plain HTTP endpoint via the Apify API from any agent framework, tool-use setup, or client library that can make a request.
What makes this different from a basic Facebook group post scraper?
Unlike a scraper that only returns the post feed, Facebook Group Posts Scraper also fetches each post's comment thread — including nested replies — into a linked child dataset, and computes engagement analytics (topContributors, postingCadenceEstimate, commentsPerPost) locally from that same run's data, with no separate AI step or paid enrichment call.
Does Facebook Group Posts Scraper return data in a format LLMs can use directly?
Yes. Output is typed, normalized JSON with consistent field names across runs — no HTML parsing or CSS selectors required. Pass it directly to an LLM, index it into a vector store, or feed it to an agent tool.
What happens when Facebook changes its layout or anti-bot system?
Facebook Group Posts Scraper is actively maintained, and the output schema is designed to stay stable across Facebook's UI changes. No specific update turnaround time is published or guaranteed.
Can I use Facebook Group Posts Scraper without managing proxies or browser infrastructure?
Yes. Apify Proxy (residential by default) and retry/backoff logic are handled automatically. No browser is launched — requests go directly to Facebook's public GraphQL and HTML endpoints.
Which fields work best for AI training data and RAG indexing?
For RAG, index postText, text (comment/reply body), and groupDescription — the highest-information free-text fields. For training data, postAuthorId, likesCount, publishedAt, and threadingDepth return as consistently typed primitives across every row.
🔗 Related scrapers
| Scraper | What it extracts |
|---|---|
| Facebook Events Scraper | Public Facebook events — names, dates, locations, attendance signals |
| Threads Search Post Scraper: Posts, Quotes & Replies | Threads posts, quotes, reposts, and nested reply threads |
| LinkedIn Profile Post Scraper | Posts published on a LinkedIn profile, with likes/comments/shares |
| Reddit Subreddit Members Scraper (Active Participants) | Active subreddit participants and commenters |
| Twitter (X.com) Tweets & Profiles Scraper | Tweets and profile data from X/Twitter |
💬 Your feedback
Found a bug or missing a field? Let us know via the Actor's Issues tab in Apify Console, or through Apify's support chat — reports like this are exactly how the output schema stays accurate as Facebook's own group pages change.