π Facebook Group Posts Scraper Pro
Pricing
$19.99/month + usage
π Facebook Group Posts Scraper Pro
Facebook Group Post Scraper extracts posts from public Facebook groups, capturing text, images, videos, author details, timestamps, reactions, comments, and share data. Ideal for community research, trend analysis, social listening, and automating structured Facebook group post insights.
Pricing
$19.99/month + usage
Rating
0.0
(0)
Developer
SimpleAPI
Maintained by CommunityActor stats
1
Bookmarked
45
Total users
7
Monthly active users
16 days
Issues response
4 days ago
Last modified
Categories
Share
Facebook Group Scraper β Posts, Comments and Engagement Data
Facebook Group Posts Scraper Pro pulls posts from one or many public Facebook groups and returns them as structured JSON: post text, media attachments, per-reaction-type breakdowns (Like, Love, Care, Haha, Wow, Sad, Angry), share and comment counts, hashtags, mentions, and computed engagement figures. Turn on comment scraping and every comment and reply is pushed as its own linked row. Built for social listening teams, community managers, market researchers, and lead-gen pipelines that need group discussions as clean, queryable data rather than a scrolling feed.
What is Facebook Group Posts Scraper Pro?
Facebook Group Posts Scraper Pro is an Apify Actor that scrapes the public post feed of one or more Facebook groups β by URL, vanity name, or numeric group ID β and returns each post as a dataset row, with an optional second pass that fetches every comment and reply underneath it. No Facebook login is required for public groups; the Actor reverse-engineers Facebook's own web GraphQL feed and impersonates a real Chrome browser's TLS fingerprint to get accepted requests, so results come back in the same shape Facebook's website itself uses internally.
Key capabilities, read from the source:
- Group discovery by URL, vanity name, or numeric ID β
startUrlstakes a list of any of the three; the Actor normalizes each into a canonical group URL before scraping. - Three feed orderings β newest-first (with an early pagination stop once you've paged past your date cutoff), most-relevant, and recent-activity, matching Facebook's own sort options.
- Full comment and reply threads β comments are fetched via Facebook's own paginated comments API, and replies via a separate depth-1 replies query, each capped independently.
- Reaction, share, and comment counts, plus computed engagement β per-type reaction breakdown, total engagement, and (when the group's member count is discoverable) an engagement rate.
- Server-side filtering on parent posts β keyword include/exclude, post type (text/photo/video/link), and a minimum-reactions threshold, all applied before a row is charged.
- Optional session cookie for closed groups you already belong to (experimental; public groups don't need it).
What data can I extract with Facebook Group Posts Scraper Pro?
The Actor pushes two kinds of rows to the same dataset β type: "post" for parent posts and type: "comment" / type: "reply" for child rows β distinguished by the isChild flag. The dataset's default table view surfaces 24 columns, but the Actor pushes a few extra keys per row that aren't in that view; every one is documented below, straight from the row-building functions in src/helper.py.
| Field | Row type | Description |
|---|---|---|
type | all | "post", "comment", or "reply" |
isChild | all | false for posts, true for comments and replies |
postId | post, comment, reply | Facebook's post ID |
feedbackId | post (not in default view) | Internal Facebook feedback token used to paginate that post's comments |
commentId | comment, reply | Facebook's comment ID (falls back to the internal node ID if no legacy ID exists) |
parentId | all | null on posts; the post ID on comments; the parent comment ID on replies |
groupId | all | Facebook's numeric group ID |
groupName | all | Group display name, parsed from the group page's <title> tag |
groupUrl | all (not in default view) | The normalized group URL you supplied as input |
url | post, comment, reply | Post permalink on posts; the comment/reply's direct link on comment rows (can be null) |
postUrl | comment, reply (not in default view) | Direct permalink of the parent post |
createdAt | all | Unix seconds |
publishedAt | all | ISO-8601 UTC, derived from createdAt |
text | all | Post, comment, or reply text |
depth | comment, reply (not in default view) | Facebook's own nesting-depth value for the comment node |
hashtags | post only | Hashtags parsed from the post's message entity ranges (with a regex fallback) |
mentions | post only | { name, id, url, type } for each @-mentioned user, page, or group |
attachments | post only | Parsed media list β see below |
user | all | { id, name, url, type, profilePicture } on posts; { id, name, url, gender, profilePicture } on comments/replies |
reactionCount | all | Total reactions, or null if Facebook didn't return a count |
reactions | all | Per-type breakdown, e.g. { "Like": 51, "Love": 2, "Care": 2 } |
shareCount | post only | Total shares, or null |
commentCount | post only | Total comments Facebook reports for the post, or null |
replyCount | comment, reply | Replies under this comment, or null |
engagementTotal | post only | reactionCount + shareCount + commentCount, summing only the values that are integers |
engagementRate | post only | engagementTotal / group member count, rounded to 6 decimals β null when the member count couldn't be parsed from the group page |
postAgeHours | post only | Hours between the post's createdAt and the moment it was scraped |
scrapedAt | all | ISO-8601 UTC timestamp of the scrape |
Attachments and reactions
Each entry in attachments is { type, url, image, width, height, title, accessibilityCaption, mediaId }, with an optional description key when Facebook returns one. type is photo, video, link, album, or a best-guess fallback derived from Facebook's own style list; multi-photo albums are flattened so each photo in the album becomes its own attachment entry. reactions decodes Facebook's opaque reaction IDs into names using a fixed map of the eight standard reaction types (Like, Love, Care, Haha, Wow, Sad, Angry, Thankful) β any reaction ID outside that map is emitted as reaction_<id> rather than dropped or guessed at.
Filtering fields
postType, minReactions, keywords, and excludeKeywords are applied against text and attachments on parent posts only, before the post is pushed β a post that fails a filter is never charged. Comments and replies are not filtered by these same options; once includeComments is on, every comment (and reply, if maxReplies is set) under a passing post is fetched.
Why not build this yourself?
Facebook does not expose group post content, comments, or reactions through a stable public API that a third-party tool can call with a client ID and get structured JSON back. Building this yourself means reverse-engineering Facebook's internal web GraphQL feed β the same interface src/main.py implements: harvesting LSD and DTSGInitialData tokens from the group's HTML, locating the current persisted-query doc_id values for the feed, comments, and replies queries (which Facebook rotates, so the Actor scans the group's own JS bundles for them when its fallback IDs go stale), and assembling each request with the right Relay variables and headers so it isn't rejected as a bot.
On top of that, Facebook fingerprint-blocks plain HTTP clients on this endpoint β the Actor uses curl_cffi with Chrome TLS/JA3 impersonation specifically because standard requests/aiohttp calls get refused, and it rotates through fresh residential proxy IPs (up to 14 attempts per group) until a group's feed responds with real posts, since Facebook blocks datacenter IPs on group feeds outright. None of this is a one-off script; it's the ongoing maintenance burden the Actor absorbs so you don't have to track Facebook's query IDs and anti-bot behavior yourself.
How to use data extracted from Facebook groups?
Social media and community managers
Set startUrls to the groups you run or watch, sortType: "recent_activity" to surface what's trending, and includeComments: true with a modest maxComments to pull sentiment straight from the thread. The reactions breakdown and engagementTotal field let you rank posts by what's actually resonating, without opening Facebook.
Social listening and brand-monitoring agencies
Point the same run at every group you monitor on a client's behalf, using keywords to isolate brand or competitor mentions and excludeKeywords to drop noise like giveaway posts. Because groupName and groupId are tagged on every row, one run across multiple groups still segments cleanly per client or per community in your downstream reporting.
Market research and intelligence
Use scrapeUntil with a relative value like "7 days" on sortType: "new_posts" to pull a rolling week of discussion from category-relevant groups (parenting groups, niche hobby groups, local buy-sell groups), then aggregate hashtags, postType-filtered subsets, and reactionCount distributions to track what topics and formats a community engages with over time.
AI agents and automated pipelines
Because every row is typed JSON with a stable schema, a scheduled run's dataset can feed directly into a RAG index or an LLM summarization pipeline β text, reactions, and commentCount per post give an agent enough signal to rank or summarize group activity without any HTML parsing on the agent's side.
π½ Input sample
Every field below matches .actor/actor.json exactly β same names, same types, same defaults. Nothing is required; an empty input run will error out (see the pitfall note below).
| Parameter | Type | Default | Constraints | Description |
|---|---|---|---|---|
startUrls | array | β | β | One or more Facebook group URLs, vanity names, or numeric group IDs. Each row is tagged with its source group. |
groupUrl | string | β | β | Optional single-group input, kept for backward compatibility. Merged with startUrls if both are set. |
count | integer | 20 | min 0, max 100000 | Maximum number of parent posts to collect across all groups. Comments/replies don't count against it. 0 = unlimited. |
sortType | string (enum) | "new_posts" | new_posts, most_relevant, recent_activity | How Facebook orders the feed. new_posts is newest-first and enables the date early-stop below. |
scrapeUntil | string (date) | β | absolute (2026-01-15) or relative ("7 days", "2 weeks", "3 months") | Keep only posts created on/after this date, UTC. On new_posts sort, pagination stops early once older posts are reached. |
includeComments | boolean | false | β | Fetch each post's comments as separate child rows, mirrored to a per-run comments dataset. |
maxComments | integer | 0 | min 0, max 1000 | Cap of comments fetched per post. 0 = none, unless includeComments is on, in which case comments are effectively uncapped (see the note below). |
maxReplies | integer | 0 | min 0, max 500 | Cap of replies fetched per comment. 0 = skip replies entirely. |
keywords | array | β | β | Keep only posts whose text contains at least one term (case-insensitive OR). |
excludeKeywords | array | β | β | Drop posts whose text contains any of these terms. |
postType | string (enum) | "any" | any, text, photo, video, link | Keep only posts of this media type. text keeps posts with no attachment at all. |
minReactions | integer | 0 | min 0 | Keep only posts with at least this many total reactions. |
minDelay | integer | 1 | min 0, max 60 | Minimum delay (seconds) between paginated feed requests. |
maxDelay | integer | 3 | min 0, max 120 | Maximum delay (seconds) between paginated feed requests. Auto-raised to match minDelay if you set it lower. |
cookie | string (secret) | β | β | Experimental. Raw Cookie header from a logged-in session ("c_user=...; xs=...; datr=..."), for closed groups you're a member of. |
proxy | object | {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} | β | Proxy configuration. Residential is the default and is strongly recommended β Facebook blocks datacenter IPs on group feeds. |
{"startUrls": ["https://www.facebook.com/groups/cheapmealideas"],"count": 50,"sortType": "new_posts","scrapeUntil": "7 days","includeComments": true,"maxComments": 20,"maxReplies": 5,"keywords": ["recipe", "budget"],"postType": "any","minReactions": 3,"proxy": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Common pitfall: if you leave both startUrls and groupUrl empty, the run logs "No group URL provided. Set 'startUrls' or 'groupUrl'." and exits immediately with zero rows charged. A second one: keywords, excludeKeywords, postType, and minReactions only filter parent posts β they don't filter which comments or replies come back once includeComments is on, so a post that barely clears your minReactions threshold can still bring its full comment thread with it.
πΌ Output sample
Every row lands in the run's default dataset, exportable as JSON, CSV, Excel, or the other formats Apify's Dataset tab offers. When includeComments or maxComments is set, comment and reply rows are also mirrored into a separate per-run dataset named comments-<RUN_ID>, in addition to being interleaved into the default dataset right after their parent post.
A parent post row:
{"type": "post","isChild": false,"parentId": null,"postId": "1234567890123456","feedbackId": "ZmVlZGJhY2s6MTIzNDU2Nzg5MDEyMzQ1Ng==","groupId": "1745271899086274","groupName": "Cheap Meal Ideas","groupUrl": "https://www.facebook.com/groups/cheapmealideas","url": "https://www.facebook.com/groups/1745271899086274/permalink/1234567890123456/","createdAt": 1753500000,"publishedAt": "2026-07-26T09:20:00Z","text": "Made a huge batch of lentil soup for $8 total β recipe in comments!","hashtags": ["budgetmeals"],"mentions": [],"attachments": [{"type": "photo","url": "https://www.facebook.com/photo/?fbid=1234567890","image": "https://scontent.fplu1-1.fna.fbcdn.net/v/example.jpg","width": 960,"height": 720,"title": null,"accessibilityCaption": "A pot of orange soup on a stovetop","mediaId": "1234567890"}],"user": {"id": "10001","name": "Jane Doe","url": "https://www.facebook.com/jane.doe","type": "User","profilePicture": "https://scontent.fplu1-1.fna.fbcdn.net/v/profile.jpg"},"reactionCount": 55,"reactions": { "Like": 51, "Love": 2, "Care": 2 },"shareCount": 3,"commentCount": 12,"engagementTotal": 70,"engagementRate": 0.005833,"postAgeHours": 4.32,"scrapedAt": "2026-07-26T13:32:00Z"}
A child comment row (pushed only when includeComments or maxComments is set):
{"type": "comment","isChild": true,"commentId": "987654321012345","parentId": "1234567890123456","postId": "1234567890123456","postUrl": "https://www.facebook.com/groups/1745271899086274/permalink/1234567890123456/","groupId": "1745271899086274","groupName": "Cheap Meal Ideas","groupUrl": "https://www.facebook.com/groups/cheapmealideas","url": "https://www.facebook.com/groups/1745271899086274/permalink/1234567890123456/?comment_id=987654321012345","createdAt": 1753500600,"publishedAt": "2026-07-26T09:30:00Z","text": "Here's the recipe: 2 cups lentils, 1 onion, 2 carrots, veg stock...","depth": 0,"user": {"id": "10002","name": "Mark Alvarez","url": "https://www.facebook.com/mark.alvarez","gender": "MALE","profilePicture": "https://scontent.fplu1-1.fna.fbcdn.net/v/profile2.jpg"},"reactionCount": 6,"reactions": { "Like": 5, "Love": 1 },"replyCount": 2,"scrapedAt": "2026-07-26T13:32:01Z"}
Reply rows use the same shape as comment rows, with type: "reply" and parentId set to the parent comment's commentId instead of the post ID.
How do you filter and target specific posts?
This Actor doesn't search Facebook by keyword β it always starts from a group you name β so precision targeting comes from four knobs working together rather than a query string.
- Group targeting.
startUrlsaccepts a full URL, a bare vanity name, or a numeric group ID, and normalizes any of the three into a canonical group URL, so you can mix formats freely across a list of groups in one run. - Time scope.
scrapeUntilbounds a run by date β absolute ("2026-06-01") or relative ("2 weeks"). Pair it withsortType: "new_posts"and pagination stops as soon as it crosses your cutoff, which keeps a scheduled daily or weekly run cheap and fast instead of re-walking the whole feed every time. - Quality thresholds.
minReactionsdrops low-engagement posts before they're charged, andpostTypenarrows to text-only, photo, video, or link posts β useful when you only want, say, the photo posts in a marketplace-style group. - Volume controls.
countcaps parent posts per run (0 = unlimited);maxCommentsandmaxRepliesindependently cap the comment thread depth pulled per post, so a run withcount: 20andmaxComments: 5never charges more than 20 posts plus up to 100 comment rows, regardless of how deep the real threads go.
{ "startUrls": ["https://www.facebook.com/groups/localbuysell"], "postType": "photo", "minReactions": 10, "count": 30 }
{ "startUrls": ["https://www.facebook.com/groups/cheapmealideas"], "sortType": "new_posts", "scrapeUntil": "3 days", "keywords": ["recipe"] }
{ "startUrls": ["https://www.facebook.com/groups/1745271899086274"], "includeComments": true, "maxComments": 50, "maxReplies": 10, "count": 10 }
βΆοΈ Want to try other Facebook scrapers?
| Scraper | What it extracts |
|---|---|
| Facebook Groups Search Scraper Plus | Discovers Facebook groups by keyword and enriches results with member counts, activity level, and privacy status |
| Facebook Groups Posts & Comments Scraper (pay-per-events) | A pay-per-event variant covering the same group posts-and-comments use case |
| Facebook Photos Scraper | Extracts photos from a Facebook profile or page, with real dimensions, captions, and engagement counts |
| Instagram Followers Scraper | Scrapes the followers list of an Instagram account |
| Instagram Profile Contact Enricher | Enriches Instagram profiles into contact rows β business phone/email, category, and validated bio contacts |
| LinkedIn Profile Contact Lookup | Looks up contact details for LinkedIn profiles |
How to extract Facebook group data programmatically
The Actor runs like any other Apify Actor: start it through the Console, on a schedule, via a webhook, or through the Apify API/SDK with your Apify API token. There's no separate signup or API key beyond your Apify account.
Python example
from apify_client import ApifyClientclient = ApifyClient("<APIFY_API_TOKEN>")run = client.actor("facebook-group-posts-scraper-pro").call(run_input={"startUrls": ["https://www.facebook.com/groups/cheapmealideas"],"count": 50,"includeComments": True,"maxComments": 10,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["type"], item.get("text", "")[:80], item.get("reactionCount"))
Export to spreadsheets or CRM
Every dataset row is flat enough to export directly: use the Dataset tab's CSV or Excel export, and map text, user.name, groupName, reactionCount, and url to your CRM's note, contact-name, source, and link fields β nested keys like user and reactions export as JSON strings in CSV, so pull user.name/user.url via a quick post-processing step if your CRM needs them as separate columns.
Is it legal to scrape Facebook?
Scraping publicly accessible Facebook group content β posts that any logged-out visitor to a public group can see β is generally lawful; this Actor does not access private or closed groups unless you supply your own session cookie for a group you already belong to. Each row does contain personal data (post and comment authors' names, profile URLs, and profile pictures), so GDPR and CCPA apply to how you store and use it, not to the act of collecting public posts itself: you need a lawful basis (typically legitimate interest) for retaining that personal data, and you should honor deletion/access requests from individuals identified in your dataset. Consult legal counsel for commercial applications involving bulk storage of personal data.
β Frequently asked questions
What happens if a post is later deleted from the group?
The Actor has no way to detect deletions after the fact β it returns whatever the group's feed serves at the moment of the run. A previously scraped row stays in your dataset even if the post is later removed by its author or a moderator; run the Actor again on a schedule if you need to track that kind of drift.
Can I get comments and replies along with the posts?
Yes. Set includeComments: true (or set maxComments above 0) and each post's comments come back as separate child rows, with maxReplies optionally pulling reply threads underneath each comment. Child rows are pushed to the same dataset as the posts, interleaved right after their parent, and also mirrored to a separate comments-<RUN_ID> dataset for the run.
How accurate is the reaction and comment data?
The Actor returns the counts exactly as Facebook's own feed API reports them at request time β it does not recompute or estimate anything. Because group activity changes continuously, treat counts as a snapshot as of scrapedAt, and re-run on a schedule if you need current numbers.
How many posts and comments can I get per run?
count caps parent posts per run, from 0 (unlimited) up to 100,000. maxComments caps comments per post up to 1,000 β but leaving it at 0 while includeComments is on removes that cap entirely, bounded only by an internal 60-page pagination guard rather than a fixed number. maxReplies caps replies per comment up to 500, and 0 skips replies outright.
Can I target specific kinds of posts within a group?
Yes β postType narrows to text-only, photo, video, or link posts, minReactions filters out low-engagement posts, and keywords/excludeKeywords include or exclude posts by text content. All four apply to parent posts only, before the row is charged.
Does Facebook Group Posts Scraper Pro work with Claude, ChatGPT, and AI agent frameworks?
It's not exposed through an MCP server. Any agent framework that can call the Apify API or the apify-client SDK β which covers Claude, ChatGPT, and custom agent stacks alike β can start a run and read the resulting dataset as a normal HTTP call.
How does this compare to other Facebook group scrapers?
As observed on the Apify Store on 2026-07-26, logical_scrapers' Facebook group posts scraper caps runs at 50 group URLs and uses a lightweight Cheerio (HTTP-only) engine with an optional Notion output, but does not document comment or reply extraction. memo23's Facebook Group Posts and Details Scraper requires a logged-in session cookie even for public groups and bills on a flat monthly price rather than pay-per-event. cleansyntax's scraper targets Facebook profiles rather than groups. This Actor is group-specific, requires no login for public groups, and returns full comment and reply threads as linked child rows alongside per-type reaction breakdowns.
Can I use this without a Facebook account or API key?
Yes, for public groups β no Facebook login, API key, or developer account is required; the Actor only needs your Apify account and a group URL. The cookie input is optional and experimental, used only when you want to reach a closed group you're already a member of.
Conclusion
Facebook Group Posts Scraper Pro turns any public Facebook group into a structured, filterable dataset β posts, full comment and reply threads, per-type reactions, and computed engagement, all under one consistent schema. It's built for teams who need group discussion as data: social listening, community management, market research, and AI pipelines that would otherwise be stuck copy-pasting a Facebook feed. Run it from the Apify Console or schedule it against the groups you track, and point your dashboard, spreadsheet, or agent at the dataset it produces.