Facebook Groups Scraper - Public Group Posts avatar

Facebook Groups Scraper - Public Group Posts

Pricing

from $0.67 / 1,000 posts

Go to Apify Store
Facebook Groups Scraper - Public Group Posts

Facebook Groups Scraper - Public Group Posts

Scrape posts from public Facebook groups. Each post gives the author, text, exact time, permalink, photos and videos, plus reaction, comment and share counts. Up to 5,000 posts and 50 groups per run, with a keyword filter. $0.70 per 1,000 posts.

Pricing

from $0.67 / 1,000 posts

Rating

5.0

(1)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

157

Total users

75

Monthly active users

4.2 hours

Issues response

2 days ago

Last modified

Categories

Share

Paste public Facebook group URLs and get their posts as rows: the text, the author, the exact posting time, the permalink, the photos and videos, and the reaction, comment and share counts. No login, and no browser to wait on.

If a group shows no posts, it comes back as a free note in your dataset rather than a charge.

On the Apify Free plan, most runs return no posts. Paid plans get them.

InputPublic Facebook group URLs
OutputOne row per post: text, author, posting time, permalink, photos and videos, reactions, comments, shares
Ceiling5,000 posts and 50 groups per run
Account neededNone
Apify planA paid plan. On the Free plan most runs end with a free RATE_LIMITED note and no posts
Price$0.70 per 1,000 posts on the free plan, down to $0.67 on Business

🔍 What Facebook Groups Scraper does

Give it group URLs, pick how the feed should be ordered, say how many posts you want, and press Start. Each post becomes one row with everything the group page publishes about it.

Three orderings, and they are Facebook's own, not a sort applied afterwards: New posts walks the feed by posting time, Newest activity brings up threads that were commented on recently, and Most relevant is Facebook's own ranking. For monitoring, use New posts.

There is a date window too. Give onlyPostsNewerThan a date or something like 7 days, or 2 hours when you check often, and older posts are dropped before they are written, so you are not charged for them.

Two switches help with groups you check often. keywords keeps only posts holding one of your words, and the rest are never charged. onlyNewPosts remembers the newest post each run handed over, so the next run gives you only what came after it.

Both numeric group URLs and the handle form work.

📋 What data you get from each Facebook group post

What you getField
The post's id and permalinkid, url, legacyId
The texttext
The original post's text, when the post is a sharesharedPostText
When it was postedtime, timestamp
Who posted ituser (name, id, picture, profile link)
Reactions, comments and shareslikesCount, topReactionsCount, commentsCount, sharesCount
Reactions by type: like, love, haha and the restreactionsByType
Photos, videos and a shared linkattachments, attachmentsCount, photoCount, isVideo, link
Each picture's size and Facebook's own description of itwidth, height, accessibilityCaption inside attachments
The groupgroupId, groupTitle, facebookUrl
The URL you gaveinputUrl
The comments shown under the post (optional, no extra charge)topComments
Full comment threads (optional, paid add-on)separate rows with recordType: "comment"

▶️ How to scrape Facebook groups

  1. Open Facebook Groups Scraper and click Try for free.
  2. Paste group URLs into Facebook group URLs.
  3. Set Number of posts and pick a Sorting order.
  4. Add Posts newer than if you only want recent ones, then click Start.
  5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

Run it with no usable group URL and you get one labelled sample row, which is not charged.

💰 How much does it cost to scrape Facebook groups?

$0.70 per 1,000 posts. That is the free plan's price; paid plans pay a little less: $0.69 on Starter, $0.68 on Scale and $0.67 on Business.

One charge per post row. Posts your date window or your words leave out are never charged, and neither are sample or diagnostic rows. An empty group or a run that finds nothing costs you nothing for results. Top comments with each post cost nothing extra.

Full comment threads are an add-on: each comment row is charged as one Comment event, at the price on the Pricing tab. While that price is not there yet, asking for them returns one free note and reads no comments.

📥 What you give it

{
"startUrls": [{ "url": "https://www.facebook.com/groups/dogspotting/" }],
"resultsLimit": 50,
"viewOption": "CHRONOLOGICAL",
"onlyPostsNewerThan": "7 days"
}
FieldDefaultWhat it is
startUrlsnone, the form starts with an exampleUp to 50 public group URLs. Any past the fiftieth are left unread and listed in one free BAD_INPUT row.
resultsLimitempty, runs as 20Posts across the whole run, up to 5,000. Five groups at resultsLimit: 100 is a hundred posts in total, not five hundred.
maxPostsPerGroupnoneThe most posts from any one group. Set it and leave resultsLimit empty, and the run asks for that many from every group.
viewOptionempty, runs as CHRONOLOGICALCHRONOLOGICAL for new posts, RECENT_ACTIVITY for recently commented threads, TOP_POSTS for Facebook's ranking.
keywordsnoneWords or phrases. Only posts holding at least one of them, in the text, the shared post's text or a link preview, are delivered and charged. Case does not matter.
onlyNewPostsfalseEach run remembers the newest post it handed over per group, in a store called facebook-groups-scraper-new-posts on your own Apify account, and the next run skips everything up to it. Delete that store to start over.
onlyPostsNewerThannone2026-01-01, a full ISO timestamp, or a span such as 7 days, 2 hours or 30 minutes. Older posts are skipped and never charged.
onlyPostsOlderThannoneThe same formats, the other way round. Use both for a window.
allPhotosfalseTurn it on to get up to 24 photos of each post instead of the first 5. The price per post stays the same, but the run takes longer, a few seconds more for each post with more than 5 photos, so give big runs a longer timeout.
includeTopCommentsfalseAdds topComments to each post: the one or two comments Facebook already shows under it. No extra charge.
maxCommentsPerPostnoneFull comment threads: up to this many comments from each post that has some, as their own rows, charged per comment.
includeCommentRepliesfalseWith maxCommentsPerPost set, the replies under each comment too. They count toward that number.
proxyUrlsnoneLeave it empty. It is here for callers who want the traffic to leave through servers they already pay for, as http://user:pass@host:port. There is no bandwidth surcharge on this actor either way.

📤 What you get back

A real row from a run on 21 September 2026. The image links are signed and very long, so they are cut short here:

{
"ok": true,
"recordType": "post",
"charged": true,
"facebookUrl": "https://www.facebook.com/groups/dogspotting/",
"url": "https://www.facebook.com/groups/dogspotting/permalink/10166203291439467/",
"id": "10166203291439467",
"legacyId": null,
"time": "2026-09-20T23:30:52.000Z",
"timestamp": 1789947052,
"text": "His name is Invader and he invaded my heart",
"user": {
"id": "pfbid02UQC3terETmAmd24Hgg4ev1Pxye5Bh6SQ9HCYF58dVPrULg7E3tumNTv4Hs2Aoz4tl",
"profileUrl": null,
"profilePic": "https://scontent-lga3-3.xx.fbcdn.net/v/t39.30808-1/560561781_10164128278012578_..."
},
"likesCount": 147,
"commentsCount": 0,
"sharesCount": 0,
"topReactionsCount": [86, 60, 1],
"attachments": [
{
"type": "photo",
"thumbnail": "https://scontent-lga3-3.xx.fbcdn.net/v/t39.30808-6/791453646_10165826125182578_...",
"url": "https://www.facebook.com/photo/?fbid=10165826125842578&set=gm.10166203291439467&idorvanity=10487409466",
"id": "10165826125842578"
}
],
"attachmentsCount": 1,
"isVideo": false,
"link": null,
"groupId": "10487409466",
"groupTitle": "Dogspotting",
"inputUrl": "https://www.facebook.com/groups/dogspotting/",
"scrapedAt": "2026-09-21T01:45:39.314Z"
}
FieldHow to read it
id, urlThe post id and its permalink. id is your dedupe key across runs.
time, timestampThe real posting time, as ISO and as a unix number. Not "2 hours ago".
likesCountEvery reaction added together, not only thumbs-up. In the row above, 147 is the 86, 60 and 1 in topReactionsCount summed.
topReactionsCountThe counts behind the reaction types on the post, as numbers with no labels. reactionsByType gives the same counts by name, for example {"like": 86, "love": 60, "haha": 1}, and adds up to likesCount. null when the post has no reaction.
width, height, accessibilityCaptionIn an attachments entry: the size of the picture the thumbnail link opens, and Facebook's own description of it, such as "May be an image of a dog". The caption is null when Facebook has none. Photos added by allPhotos carry neither.
topCommentsWith includeTopComments on: the comments Facebook shows under the post, each with text, profileName, date, likesCount, repliesCount and commentUrl. Usually one or two, and an empty list on most posts with few comments.
userName and picture. profileUrl is often null and the id is the long pfbid form, which is what Facebook hands out for group authors now.
attachmentsOne entry per photo or video, with a thumbnail and, on videos, the video link. Every media link is signed and stops working after a while, so download what you want to keep in the same session.
photoCountHow many photos the post has in total, the number behind the "+N" on the last photo. attachments holds the first 5 of an album's photos, or up to 24 with allPhotos on, so a post with 31 photos gives 5 links (24 with allPhotos) and photoCount: 31. A video in the same set counts as one. null when the post has no photo.
sharedPostTextOn a share, text is only what the person sharing typed above it, and often empty. This is the shared post's own text, in full. null when the post is not a share or the shared post has no text.
legacyIdFacebook's older numeric id when the page still carries one. Usually null.

🧾 Reading the output

Four kinds of row, and only posts and comments cost anything.

RowHow to spot itCharged
A postrecordType: "post"yes
A comment, with full threads onrecordType: "comment", with the post's link in facebookUrl and its id in postIdyes, as a Comment
The sample row_sample: true, on a run with no usable inputno
A diagnostic_uncharged: true, and it carries a codeno

The charged field is a row marker, not a receipt. It is what separates a real post from a sample or a diagnostic, and it is stamped as the row is built rather than after the money moves. Your Apify run detail is the authority on what you were actually billed. Diagnostic rows carry code, not errorCode:

CodeWhat it means
FREE_PLANThe first row of a run on the Apify Free plan: Facebook serves only a few group reads, and this Actor keeps them for paid plans, so most Free-plan runs end with RATE_LIMITED and no posts.
BAD_INPUTNot a Facebook group URL, or more than 50 groups in one run: that row lists the ones left out.
NO_PUBLIC_POSTSThe group showed no posts to the run. A handle that no longer exists lands here too.
NO_RESULTSThe feed answered and had nothing matching your date window or your words, or nothing new since your last run.
FILTER_TOO_RAREYour words matched too few of the posts read to keep reading. What matched is delivered.
TIME_LIMITThe run stopped just before its time limit. What was delivered stays. The run ends as failed only when nothing came back before the limit.
COMMENTS_SOONYou asked for full comment threads before they were switched on. No comments were read.
MEMORY_ERRORWith onlyNewPosts on, the record of your last run could not be opened, so nothing was read.
NOT_FOUNDThat group is gone.
RATE_LIMITEDFacebook throttled the reads. Any groups still queued are skipped.
NOT_SERVEDThis group was not served this run. Re-run it later. Until 12 October 2026 this code was called BLOCKED.
STOPPED_EARLYThe run stopped before your limit: the feed stopped giving out posts, or further down it held very few posts that fit your settings. You keep everything collected up to that point.
SCHEMA_DRIFTThe feed came back in a shape this could not read. Worth sending in, it usually means Facebook changed something.
TARGET_ERROR, NETWORKFacebook errored, or the request did not complete. Re-run it.

💡 What people use it for

  • Watching buy-and-sell and local groups for a word, with onlyNewPosts on, and acting on new posts the same day.
  • Collecting questions people ask in a niche group, to write content that answers them.
  • Tracking how a community reacts to an announcement, by post text and reaction counts.
  • Keeping an archive of a group you run, outside Facebook, with permalinks that still work.

From a group's feed to the threads people argued in, in three steps:

  1. Run this on a group with viewOption set to RECENT_ACTIVITY.
  2. Sort on commentsCount and copy the url of the busiest posts.
  3. Paste them into Facebook Comments Scraper, which reads group-post links, and read the comments themselves.

🚧 What it does not do

  • Full comment threads are a paid add-on. Each comment is charged as a Comment event at the price on the Pricing tab, and while that price is not there the option returns a free note. Top comments with each post are free, but they are only the one or two Facebook shows.
  • No member lists, no admin lists, no group rules.
  • No search inside a group. The word filter checks the posts the run reads; it does not ask Facebook to search. A word that turns up rarely stops the run early with a free FILTER_TOO_RARE row.
  • No sale listing fields such as price or sold status. Sale posts come back as ordinary posts, with the price wherever the seller typed it in the text.
  • No photo or video files, only links, and those links expire.
  • 50 groups per run at most. Any beyond that are left unread and listed in one free BAD_INPUT row.
  • It won't read a whole group to find a handful of posts. Sorted by top posts or recent activity with a date window, or skipping far back with onlyPostsOlderThan, a run stops once the posts further down mostly fall outside your settings, and says so in a free STOPPED_EARLY row. Newest first with Posts newer than still returns every post in the window.
  • resultsLimit is the whole run, not per group. Sharing 50 posts across 10 groups is five each if the feeds cooperate. maxPostsPerGroup caps each group.
  • onlyNewPosts does not go back. Older posts a run did not hand over are not picked up later, so set resultsLimit to cover what a group posts between runs.
  • It is not an official Facebook tool. Dami's Studio is independent and is not affiliated with or endorsed by Facebook or Meta, or by any other company named on this page.

🧭 Which Facebook scraper do you need?

If you wantUse
Posts from public groupsThis one
Posts from a Facebook PageFacebook Posts Scraper
Comments under a post or reel, group posts includedFacebook Comments Scraper
Reels from a PageFacebook Reels Scraper
A Page's website, e-mail, phone and addressFacebook Page Contact Info Scraper

❓ Questions people ask

Do I need a Facebook account to scrape groups?

No. Public groups are read without one.

Why did I get fewer posts than I asked for?

Either the group has fewer public posts, your date window excluded the rest, or the feed stopped early. A STOPPED_EARLY or NO_RESULTS row tells you which. If you get NO_PUBLIC_POSTS, open the group in a private browser window. If a signed-out visitor sees no posts there either, that is why.

Can I call it from code or connect it to an AI assistant?

Yes. The API tab has ready-made code for Python, JavaScript and the command line. For Claude, ChatGPT or another MCP client, connect https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/facebook-groups-scraper. Either way the run happens on your Apify account at the same price.

These are pages anyone can read without an account. Posts contain personal data, which GDPR and similar laws cover, so have a lawful reason for collecting them. Apify's write-up on scraping and the law is a reasonable starting point, and we are not lawyers.

🆘 If something breaks

Open the Issues tab on the actor page. Send the run ID and the group URL. The code on the diagnostic row usually says what happened on its own.