Facebook Groups Scraper - $0.70 per 1,000 Posts
Pricing
from $0.70 / 1,000 post scrapeds
Facebook Groups Scraper - $0.70 per 1,000 Posts
Posts from public Facebook groups: author, text, timestamp, permalink, photos and videos, and reaction, comment and share counts. No login needed from you, and no browser. Private groups return a free diagnostic row instead of a charge. $0.70 per 1,000 posts.
Pricing
from $0.70 / 1,000 post scrapeds
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
9
Total users
4
Monthly active users
3 days ago
Last modified
Categories
Share
Facebook Groups Scraper
Paste public Facebook group URLs, get their posts back as rows: author name and profile picture, post text, timestamp, permalink, attached photos and videos, and reaction, comment and share counts.
You don't supply a login, a cookie or a token. Nothing to set up. Group URL in, rows out.
Price
$0.70 per 1,000 posts ($0.0007 per post), plus a $0.002 start fee per run.
The rate is flat: the same $0.70 on the free plan as on any paid plan, no volume tiers, no minimum spend, no monthly rental.
You're charged once per post row that actually lands in the dataset. Nothing else bills:
- the free sample row an empty run returns
- diagnostic rows (private group, bad URL, throttled, no posts in your date range)
- posts dropped by your
onlyPostsNewerThan/onlyPostsOlderThanfilter - proxy bandwidth, which carries no per-gigabyte surcharge on this Actor at all
The start fee is billed per gigabyte of run memory. Default is 1 GB, so it's charged once.
| Posts returned | What you pay |
|---|---|
| 0 (group turned out private) | $0.002 |
| 20 | $0.016 |
| 100 | $0.072 |
| 500 | $0.352 |
| 1,000 | $0.702 |
Input
| Field | Type | What it does |
|---|---|---|
startUrls | array | Public Facebook group URLs. Vanity (/groups/dogspotting/) and numeric (/groups/874728723021553) both work. Up to 20 groups per run. |
resultsLimit | integer | Total posts across all groups. Maximum 1000, default 20. |
viewOption | string | CHRONOLOGICAL (new posts), RECENT_ACTIVITY (newest activity), TOP_POSTS (most relevant). |
onlyPostsNewerThan | string | Keep posts after this point. 2026-01-01, a full ISO timestamp, or something relative like 7 days. |
onlyPostsOlderThan | string | Keep posts before this point. Same formats. |
sessionCookies | array | Optional, and most runs never touch it. See About logins below. |
proxyUrls | array | Optional, and almost nobody needs it. Your own proxy servers, on your own bill. Leave it empty and the Actor uses its own egress at no extra cost to you. |
{"startUrls": [{ "url": "https://www.facebook.com/groups/dogspotting/" }],"resultsLimit": 100,"viewOption": "CHRONOLOGICAL","onlyPostsNewerThan": "30 days"}
Run it with no input and you get one labelled sample row, uncharged, so you can see the exact output shape before spending anything.
Output
One row per post. Real row, trimmed only where the image URLs would run off the page:
{"ok": true,"recordType": "post","charged": true,"facebookUrl": "https://www.facebook.com/groups/dogspotting/","url": "https://www.facebook.com/groups/dogspotting/permalink/10166049003509467/","id": "10166049003509467","legacyId": null,"time": "2026-08-21T03:08:00.000Z","timestamp": 1787281680,"text": "Meet Steve the dog hanging out in the camping 🏕 store by the pizza joint","user": {"id": "1515654893","name": "Tia Harrison","profileUrl": "https://www.facebook.com/tia.schmitz.harrison","profilePic": "https://scontent-phl2-1.xx.fbcdn.net/v/t39.30808-1/727449562_...jpg"},"likesCount": 8,"commentsCount": 0,"sharesCount": 0,"topReactionsCount": [7, 1],"attachments": [{ "type": "photo", "thumbnail": "https://scontent-phl2-1.xx.fbcdn.net/v/t39.30808-6/780058410_...jpg", "id": "10232892375201070" }],"attachmentsCount": 2,"isVideo": false,"link": null,"groupId": "10487409466","groupTitle": "Dogspotting","inputUrl": "https://www.facebook.com/groups/dogspotting/","scrapedAt": "2026-08-21T03:34:25.390Z"}
Field reference
| Field | Meaning |
|---|---|
id | Facebook's post id. Stable, safe as a primary key. |
url | Direct permalink to the post. |
facebookUrl | The group the post belongs to. |
time / timestamp | Creation time as ISO 8601 and as Unix seconds. Same instant. |
text | The post body. null for posts that are only a photo or a video. |
user.name | Author display name as Facebook renders it publicly. |
user.id | Either a numeric id or an opaque pfbid… string, depending on the account. The pfbid form rotates over time, so don't treat it as a permanent identity. |
user.profilePic | Avatar URL. Signed CDN links that expire in a few days. Re-host anything you want to keep. |
user.profileUrl | Present when the feed payload carries it, null otherwise. Roughly half the rows in a typical run. |
likesCount | Total reactions, all types combined. |
commentsCount | Comment count as shown on the post. |
sharesCount | Share count. Often 0, because most group posts aren't shareable. |
topReactionsCount | Counts of the individual top reaction types, most-used first. |
attachments | Photos and videos, de-duplicated. Videos carry videoUrl where the payload exposes one. |
isVideo | True when at least one attachment is a video. |
link | External link attached to the post, with title and description when Facebook rendered a preview card. |
groupId / groupTitle | Numeric group id and group name, resolved from the handle you supplied. |
recordType | post for real data, sample for the free example row, diagnostic for a free explanation of something that went wrong. |
charged | Whether that row was billed. Only post rows are ever true. |
Diagnostic rows carry ok: false and a code: NO_PUBLIC_POSTS, BAD_INPUT, RATE_LIMITED,
BLOCKED, SCHEMA_DRIFT, NO_RESULTS, STOPPED_EARLY, each with a details sentence. To keep
only real posts, filter on recordType === "post".
About logins
Worth spelling out, because "no login" gets used loosely.
Runs start logged out, and for a public group that is usually all it takes. When Facebook hands a logged-out reader nothing back, the run falls back to an account session that ships with the Actor so you don't have to supply one. That's what "no login needed from you" means here: there is a session involved, it just isn't yours and you never see it.
That built-in session is shared across everyone using the Actor, and Facebook meters per account.
If you're running heavily and start seeing throttled diagnostic rows, sessionCookies lets you
paste your own c_user=…; xs=… pair and get a rate limit nobody else is using. Treat those values
like a password. Anyone holding them can act as that account, and Facebook may sign the session out
or restrict the account for automated use.
What it does not do
Written plainly, because finding this out after you've paid is worse than reading it here.
- Public groups only. A private or closed group shows its feed to members and nobody else. No session that isn't a member of that group changes it. Point this Actor at a private group and you get one free diagnostic row saying so, and a bill of exactly the start fee.
- No comments. It returns the comment count, not the comment text. This reads the group feed, not individual post threads.
- No member lists. Group membership isn't public.
legacyIdis usually null, anduser.profileUrlis null on a fair share of rows. Those fields exist because the feed payload sometimes carries them. They're never invented.- 1,000 posts per run. Deep pagination gets slower and more likely to be throttled the further back you go. If you need more, run again with a date filter or split the groups across runs.
- Throttling is real. Facebook meters this endpoint per outgoing address. A run that hits a throttled window returns free diagnostic rows instead of posts, succeeds rather than failing, and bills only the start fee. Waiting a few minutes and re-running is normally enough. Heavy back-to-back runs against the same group are what triggers it.
- A run that returns nothing stops early on purpose. If the first few groups give back no posts,
because they're private, throttled or mistyped, the run stops rather than walking the remaining
URLs, and writes a
STOPPED_EARLYorRATE_LIMITEDrow naming the ones it skipped. That keeps a doomed run down to a single start fee. sharesCountis often 0. That's what Facebook reports for most group posts, not a parsing bug.- Media URLs expire. Every
scontent.*.fbcdn.netlink is signed and short-lived. Download what you want to keep, promptly.
How it works
The group page is fetched as an ordinary visitor. Facebook usually answers with its "you must log in to continue" shell, which looks like a dead end and isn't: the shell carries the CSRF token and build identifiers the site's own JavaScript would use, and the public feed endpoint accepts them. The Actor then calls that endpoint the way the page would, reads the streamed response, and turns each story into a row.
There's no headless browser anywhere in here, which is most of the reason it can be priced where it is. And when Facebook changes the shape of that query, the Actor re-reads the current identifiers from Facebook's own public script bundles and retries once before giving up, so a routine site change doesn't need a redeploy to recover.
FAQ
Do I need a Facebook account, cookies, or an access token?
Not from you. Runs work with nothing filled in. There's an optional sessionCookies field if you
want the run to use your own account's rate limit instead of the shared one.
Can it scrape private or closed groups? No. A closed group's feed is only served to members, so nothing outside it can read the posts. You get a free diagnostic row explaining it rather than a silent empty result.
How much does 1,000 posts cost? $0.702, being a $0.002 start fee plus 1,000 × $0.0007. No subscription, no minimum.
What happens if the group is empty, private, or the URL is wrong? The run succeeds, writes a free diagnostic row saying which of those it was, and charges the start fee only. It never fails the run to tell you a URL was wrong, because a failed run still bills a start fee and you shouldn't pay extra for a typo.
Does it get comments too? No, comment counts only.
Can I filter by date?
Yes. onlyPostsNewerThan and onlyPostsOlderThan accept 2026-01-01, a full ISO timestamp, or a
relative value like 7 days or 3 months. Posts you filter out aren't charged.
Can I scrape several groups in one run?
Up to 20. resultsLimit is the total across all of them, split evenly, and any share a group can't
fill is handed to the groups that can.
How do I sort by newest?
viewOption: "CHRONOLOGICAL", which is the default.
Do the image URLs stay valid? No. Signed CDN links that expire within days. Download anything you intend to keep.
Is this legal? It reads pages published to the open internet. What you then do with personal data, meaning names, profile pictures and post text, is your responsibility, and in the EU and UK that means GDPR applies to you as the controller. Scrape public groups, respect deletion requests, and don't use it to build a spam list.
Integration
Runs like any other Actor: from the Console, the API, the JavaScript or Python client, a schedule, or over MCP from an AI assistant. Results land in the default dataset and export as JSON, CSV, Excel, XML or RSS.
curl -X POST "https://api.apify.com/v2/acts/dami_studio~facebook-groups-scraper/runs?token=YOUR_TOKEN" \-H 'content-type: application/json' \-d '{"startUrls":[{"url":"https://www.facebook.com/groups/dogspotting/"}],"resultsLimit":100}'
Support
If a group returns a diagnostic row you think is wrong, open an issue on the Actor with the group URL and the run id. Include the run id. Without it there's nothing to look at. Facebook changing the shape of its feed payload is the usual cause.
