Facebook Groups Scraper - $0.70 per 1,000 Posts avatar

Facebook Groups Scraper - $0.70 per 1,000 Posts

Pricing

from $0.70 / 1,000 post scrapeds

Go to Apify Store
Facebook Groups Scraper - $0.70 per 1,000 Posts

Facebook Groups Scraper - $0.70 per 1,000 Posts

Scrape posts from public Facebook groups with no login, no cookies and no browser: author, text, timestamp, permalink, photos, videos and reaction, comment and share counts. At $0.70 per 1,000 posts it is the cheapest Facebook group post scraper on the market. Private groups return a free notice.

Pricing

from $0.70 / 1,000 post scrapeds

Rating

0.0

(0)

Developer

Dami's Studio

Dami's Studio

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 hours ago

Last modified

Share

Facebook Groups Scraper — public group posts, no login

Paste public Facebook group URLs, get their posts back as structured rows: author name and profile picture, post text, timestamp, permalink, attached photos and videos, and reaction, comment and share counts.

No Facebook account. No cookies to paste. No session token, no browser, no captcha solving. You give it a group URL, it gives you rows.

Price

$0.70 per 1,000 posts — $0.0007 per post — plus a $0.002 start fee per run.

That is the cheapest Facebook group post scraper on the market, and 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 are charged once per post row that actually lands in the dataset. Nothing else bills:

  • the free sample row you get from an empty run — free
  • diagnostic rows (private group, bad URL, throttled, no posts in your date range) — free
  • posts dropped by your onlyPostsNewerThan / onlyPostsOlderThan filter — free
  • proxy bandwidth — free, there is no per-gigabyte surcharge on this Actor at all

The start fee is billed per gigabyte of run memory. The default is 1 GB, so it is charged once.

Posts returnedWhat you pay
0 (group turned out private)$0.002
20$0.016
100$0.072
500$0.352
1,000$0.702

Input

FieldTypeWhat it does
startUrlsarrayPublic Facebook group URLs. Vanity URLs (/groups/dogspotting/) and numeric URLs (/groups/874728723021553) both work. Up to 20 groups per run.
resultsLimitintegerTotal posts across all groups. Maximum 1000. Default 20.
viewOptionstringCHRONOLOGICAL (new posts), RECENT_ACTIVITY (newest activity), TOP_POSTS (most relevant).
onlyPostsNewerThanstringKeep posts after this point. 2026-01-01, a full ISO timestamp, or a relative value like 7 days.
onlyPostsOlderThanstringKeep posts before this point. Same formats.
proxyUrlsarrayOptional, 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.

Field names follow the naming convention that is common across Facebook scrapers, so an input you already have usually pastes straight in and a downstream pipeline usually needs no rewriting.

{
"startUrls": [
{ "url": "https://www.facebook.com/groups/dogspotting/" }
],
"resultsLimit": 100,
"viewOption": "CHRONOLOGICAL",
"onlyPostsNewerThan": "30 days"
}

Run it with no input at all and you get one clearly labelled sample row, uncharged, so you can see the exact output shape before spending anything.

Output

One row per post. This is a 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/10166019288919467/",
"id": "10166019288919467",
"legacyId": null,
"time": "2026-08-15T12:30:13.000Z",
"timestamp": 1786797013,
"text": "A beauty 🫶",
"user": {
"id": "pfbid0gf27iWyWWmzm8KJaTYpsWb93g5SVDn5KDmaxFTmxDYWsLH1hdCC4tYJDe5tGQFXVl",
"name": "Daniela Lisa Lombardi",
"profileUrl": null,
"profilePic": "https://scontent.xx.fbcdn.net/v/t1.6435-1/758252895_...jpg"
},
"likesCount": 35,
"commentsCount": 1,
"sharesCount": 0,
"topReactionsCount": [18, 16, 1],
"attachments": [
{ "type": "photo", "thumbnail": "https://scontent.xx.fbcdn.net/v/t39.30808-6/774136759_...jpg", "id": "10165027268481605" }
],
"attachmentsCount": 4,
"isVideo": false,
"link": null,
"groupId": "10487409466",
"groupTitle": "Dogspotting",
"inputUrl": "https://www.facebook.com/groups/dogspotting/",
"scrapedAt": "2026-08-15T13:29:20.412Z"
}

Field reference

FieldMeaning
idFacebook's post id. Stable, safe to use as a primary key.
urlDirect permalink to the post.
facebookUrlThe group the post belongs to.
time / timestampCreation time as an ISO 8601 string and as Unix seconds. Always the same instant.
textThe post body. null for posts that are only a photo or a video.
user.nameAuthor display name as Facebook renders it publicly.
user.idThe author's opaque profile id (a pfbid… string). It rotates over time — do not treat it as a permanent identity.
user.profilePicAvatar URL. These are signed CDN links and expire in a few days. Re-host anything you need to keep.
user.profileUrlUsually null on group feeds. Facebook does not put the author's profile link in the group feed payload.
likesCountTotal reactions, all types combined.
commentsCountComment count as shown on the post.
sharesCountShare count. Frequently 0 for group posts, because group posts are usually not shareable.
topReactionsCountCounts of the individual top reaction types, most-used first.
attachmentsPhotos and videos, de-duplicated. Videos carry videoUrl where the payload exposes one.
isVideoTrue when at least one attachment is a video.
linkExternal link attached to the post, with its title and description when Facebook rendered a preview card.
groupId / groupTitleNumeric group id and group name, resolved from the handle you supplied.
recordTypepost for real data, sample for the free example row, diagnostic for a free explanation of something that went wrong.
chargedWhether that specific row was billed. Only post rows are ever true.

Diagnostic rows carry ok: false and a codeNO_PUBLIC_POSTS, BAD_INPUT, RATE_LIMITED, BLOCKED, SCHEMA_DRIFT, NO_RESULTS, STOPPED_EARLY — with a details sentence explaining what happened. To keep only real posts, filter on recordType === "post".

What it does not do

Written plainly, because finding this out after you have paid is worse than reading it here.

  • Public groups only. A private or closed group shows its feed to members and nobody else. There is no scraping trick that changes that — the data is simply not served to a logged-out visitor. 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 Actor scrapes the group feed, not individual post threads.
  • No member lists. Group membership is not public.
  • user.profileUrl is usually null, and legacyId is usually null. Those fields exist because the feed payload sometimes carries them; most of the time it does not. They are 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, not per account. 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 in your list give back no posts — all private, all throttled, all mistyped — the run stops rather than walking the remaining URLs, and writes a STOPPED_EARLY or RATE_LIMITED row naming the ones it skipped. That keeps a run that was never going to return data down to a single start fee. Fix or drop the dead URLs and run again.
  • sharesCount is often 0. That is what Facebook reports for most group posts, not a parsing bug.
  • Media URLs expire. Every scontent.*.fbcdn.net link is signed and short-lived. Download what you want to keep, promptly.
  • No login, ever. It does not accept a session cookie, it does not want your credentials, and it will not scrape anything that requires being logged in. That is a deliberate design choice: an account-based scraper gets the account banned, and the ban lands on whoever supplied it.

How it works

The group page is fetched as an ordinary logged-out visitor. Facebook usually answers that with its "you must log in to continue" shell, which looks like a dead end and is not: the shell carries the CSRF token and build identifiers that the site's own JavaScript would use, and the site's public feed endpoint accepts them. The Actor then calls that endpoint the same way the page would, reads the streamed response, and turns each story into a row.

Two consequences worth knowing about. First, there is no headless browser anywhere in this Actor, which is most of the reason it can be priced where it is — starting a headless browser costs many times more per run than an HTTP request does. Second, 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 does not need a redeploy to recover.

FAQ

Do I need a Facebook account, cookies, or an access token? No. Nothing to log into, nothing to paste, nothing to keep alive. If you have used scrapers that ask you for a session cookie, this is not one of them.

Can it scrape private or closed groups? No, and neither can anything else without an account inside the group. You get a free diagnostic row explaining it rather than a silent empty result.

How much does it cost to scrape 1,000 posts? $0.702 — a $0.002 start fee plus 1,000 × $0.0007. There is no subscription and 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 you 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 should not pay extra for a typo.

Does it get comments too? No. Comment counts only. This scrapes the group feed.

Can I filter by date? Yes — onlyPostsNewerThan and onlyPostsOlderThan accept 2026-01-01, a full ISO timestamp, or a relative value such as 7 days or 3 months. Posts you filter out are not 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 cannot fill — because it is private or ran out of posts — is handed to the groups that can.

How do I sort by newest? viewOption: "CHRONOLOGICAL". That is the default.

Why is sharesCount zero on most posts? Because Facebook reports zero. Most group posts are not shareable outside the group.

Do the image URLs stay valid? No. They are signed CDN links that expire within days. Download anything you intend to keep.

Can I use my own proxies? Yes, put them in proxyUrls. You almost certainly do not need to — the built-in egress is already tuned for this target and carries no bandwidth surcharge either way.

Is this legal? It reads pages that are published to the open internet with no login. What you then do with personal data — names, profile pictures, 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 do not use it to build a spam list.

Integration

Runs like any other Actor: from the Console, from the API, from the JavaScript or Python client, from 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. Schema changes on Facebook's side are the usual cause and they get fixed quickly.