# Facebook Public Group Posts Scraper (`automation-lab/facebook-group-posts-scraper`) Actor

Extract posts, authors, timestamps, media, links, and visible engagement from accessible public Facebook groups for community and brand monitoring.

- **URL**: https://apify.com/automation-lab/facebook-group-posts-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Facebook Public Group Posts Scraper

Collect **facebook public group posts** as structured data for community research, brand monitoring, and repeatable reporting. Supply accessible public group URLs and receive post text, authors, timestamps, media links, external URLs, permalinks, and engagement totals visible to signed-out visitors.

The Actor uses an anonymous US residential route. It does not ask for Facebook credentials, access private groups, scrape group members, or bypass audience restrictions.

### What does Facebook Public Group Posts Scraper do?

Facebook Public Group Posts Scraper turns the public discussion feed of each supplied group into dataset records. It follows Facebook's structured feed pagination until it reaches your item limit or the public feed ends.

You can:

- collect posts from one or several numeric public group URLs;
- keep all visible posts or filter visible text by topic;
- keep only posts published after an ISO date or timestamp;
- schedule the same input for recurring community monitoring;
- export results to JSON, CSV, Excel, XML, or RSS through Apify;
- send finished datasets to a webhook or downstream data pipeline.

Each accepted post creates one dataset item. Filtering is applied before storage and charging for the item event.

### Who is it for?

**Community managers** can review announcements, questions, and recurring themes across accessible groups.

**Brand and market researchers** can collect public discussions for qualitative analysis without copying pages manually.

**Event and nonprofit teams** can locate public registration, meeting, or volunteer announcements with `searchTerms`.

**Data teams** can schedule runs and load normalized records into a warehouse, spreadsheet, or dashboard.

**Developers** can call the Actor through the Apify API or expose it as a tool through Apify MCP.

This Actor is not intended for private-group research, member-list collection, login-only content, or personal-profile enrichment.

### Why use this Actor?

- **Purpose-built records:** output is normalized around posts rather than raw page HTML.
- **No user cookies:** the production route is anonymous and does not accept Facebook login credentials.
- **Useful monitoring filters:** topic and publication-time filters reduce downstream processing.
- **Bounded retries:** transient transport, rate-limit, and session failures trigger limited retries and one residential session rotation.
- **Honest failures:** login shells, private groups, rejected feed documents, and unrecognized response shapes fail clearly instead of returning a misleading successful empty run.
- **Standard Apify output:** datasets work with exports, schedules, webhooks, integrations, API clients, and MCP.

Facebook controls the public response shape and feed ordering. No scraper can promise that every historical post is exposed to an anonymous visitor.

### What Facebook group post data is extracted?

| Field | Type | Description |
|---|---|---|
| `postId` | string | Facebook post identifier |
| `postUrl` | string | Canonical public post permalink |
| `groupId` | string | Numeric source group identifier |
| `groupUrl` | string | Canonical source group URL |
| `author` | object | Visible author ID, name, URL, and profile picture URL when exposed |
| `text` | string or null | Visible post text; media-only posts can be null |
| `postedAt` | string or null | ISO 8601 publication timestamp when exposed |
| `engagement` | object | Visible reaction, comment, and share totals |
| `mediaUrls` | string\[] | Public image and video attachment URLs |
| `externalUrls` | string\[] | External links found in text or attachments |
| `scrapedAt` | string | ISO 8601 extraction timestamp |

Null values mean Facebook did not expose that field to the anonymous public response. Engagement totals reflect what was visible at scrape time and can differ from totals shown to a logged-in member.

### How to scrape Facebook public group posts

1. Open the Actor in Apify Console.
2. Add one or more public URLs containing a numeric group ID, for example `https://www.facebook.com/groups/1443890352589739/`.
3. Choose `maxItems` for the maximum number of saved posts across all groups.
4. Optionally add `searchTerms` or a `since` timestamp.
5. Click **Start**.
6. Open the **Dataset** tab to preview, download, or integrate the records.

Start with a small limit when evaluating a new group. Once the public route returns useful records, increase the limit or create a schedule.

### Input parameters

#### `startUrls`

Required. A list of public `facebook.com/groups/<numeric-id>/` URLs. The Actor validates the source domain and numeric group ID before making paid proxy requests.

Vanity-only paths that do not contain a numeric ID are rejected. Copy a group URL that includes its numeric identifier.

#### `maxItems`

Optional integer from 1 to 5,000. The default is 100. This is a global saved-item limit across all supplied groups, not a limit per group.

#### `searchTerms`

Optional list of up to 20 terms, each up to 100 characters. Matching is case-insensitive and uses OR logic: visible post text must contain at least one term. An empty list keeps all posts.

#### `since`

Optional ISO 8601 date or timestamp. Posts with an exposed publication time earlier than this value are skipped. Posts without an exposed timestamp are also skipped when this filter is active.

Example monitoring input:

```json
{
  "startUrls": [
    { "url": "https://www.facebook.com/groups/1443890352589739/" }
  ],
  "maxItems": 100,
  "searchTerms": ["registration", "community event"],
  "since": "2025-01-01T00:00:00.000Z"
}
```

### Output example

A current production-shaped dataset record looks like this after removing personal values:

```json
{
  "postId": "1234567890123456",
  "postUrl": "https://www.facebook.com/groups/123456789012345/posts/1234567890123456/",
  "groupId": "123456789012345",
  "groupUrl": "https://www.facebook.com/groups/123456789012345/",
  "author": {
    "id": "pfbid0ExamplePublicIdentifier",
    "name": "Example Author",
    "url": null,
    "profilePictureUrl": null
  },
  "text": "Registration is now open for our community event.",
  "postedAt": "2025-01-15T12:00:00.000Z",
  "engagement": {
    "reactions": 12,
    "comments": 3,
    "shares": 1
  },
  "mediaUrls": [],
  "externalUrls": ["https://www.example.org/community-event"],
  "scrapedAt": "2025-01-15T12:05:00.000Z"
}
```

The default dataset contains only accepted post records. There are no separate author or media datasets and no separate charge events for nested author, engagement, link, or media fields.

### How much does it cost to scrape Facebook public group posts?

The Actor uses pay-per-event pricing:

- a one-time **Start** event is currently **$0.005 per run**;
- each saved **Item processed** event is tiered by your Apify plan;
- the current BRONZE item price is **$0.0022 per saved post**.

At the current BRONZE tier, approximate Actor charges are:

| Saved posts | BRONZE price calculation |
|---:|---|
| 5 | `$0.005 + (5 × $0.0022)` |
| 25 | `$0.005 + (25 × $0.0022)` |
| 100 | `$0.005 + (100 × $0.0022)` |

Residential proxy and compute consumption are covered by the event pricing. A filter can make the Actor inspect more source posts than it saves, but only saved records emit the item event. Your Apify plan and active tier determine the exact item price shown in Console before a run.

### Community and brand monitoring workflows

#### Recurring topic monitoring

Set `searchTerms`, add a conservative `since` date, and schedule the Actor daily or weekly. Send the dataset to a webhook, database, or diff process. Store the newest `postedAt` value in your own workflow and use it for the next run.

#### Public announcement research

Search for terms such as `registration`, `meeting`, or `volunteer`. Export the retained posts to a spreadsheet with source permalinks so analysts can review context.

#### Multi-group collection

Supply multiple numeric public group URLs and one global item limit. The Actor processes groups in input order. Use separate runs when each group needs its own strict quota or schedule.

#### Data pipeline ingestion

Use the dataset API after the run finishes. Stable camelCase fields make it straightforward to map records into a warehouse table, search index, or language-model analysis step.

### Use the Actor with the Apify API

Replace `YOUR_TOKEN` with an Apify API token. Keep tokens in a secret manager rather than source control.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~facebook-group-posts-scraper/runs?token=YOUR_TOKEN&waitForFinish=120" \
  -H "Content-Type: application/json" \
  -d '{
    "startUrls": [{"url":"https://www.facebook.com/groups/1443890352589739/"}],
    "maxItems": 10
  }'
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/facebook-group-posts-scraper').call({
  startUrls: [{ url: 'https://www.facebook.com/groups/1443890352589739/' }],
  maxItems: 10,
  searchTerms: ['registration'],
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("automation-lab/facebook-group-posts-scraper").call(
    run_input={
        "startUrls": [
            {"url": "https://www.facebook.com/groups/1443890352589739/"}
        ],
        "maxItems": 10,
        "since": "2025-01-01T00:00:00.000Z",
    }
)
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

For asynchronous pipelines, start a run without waiting and poll the run endpoint or configure a run-finished webhook.

### Use Facebook group posts through MCP

#### Claude Code

Add this Actor to Claude Code through Apify MCP:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/facebook-group-posts-scraper"
```

#### Claude Desktop, Cursor, and VS Code

Claude Desktop, Cursor, and VS Code can use equivalent JSON configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/facebook-group-posts-scraper"
    }
  }
}
```

Example prompts:

- “Collect five posts from this accessible public Facebook group and summarize the topics.”
- “Find public posts containing registration or volunteer and return their source links.”
- “Run the Facebook group monitor for posts since 2025-01-01 and save the dataset URL.”

MCP follows the same input rules and public-only limitation as Console and API runs.

### Tips for reliable runs

- Verify that the URL opens as a public group and contains `/groups/<numeric-id>/`.
- Begin with `maxItems` between 3 and 10 before scaling a new source.
- Use narrow `searchTerms` only when you expect matching text; zero saved records can be a valid filter result after a recognizable feed is loaded.
- Prefer a full ISO timestamp with `Z` when workflows compare runs across time zones.
- Split unrelated groups into separate scheduled tasks when they need different filters or quotas.
- Save post permalinks as the durable review link. Facebook CDN media URLs can expire.

The Actor automatically uses a sticky US residential session, retries transient failures with bounded backoff, and rotates once when needed. Users do not need to configure or supply proxy credentials in the input.

### Limitations

- Only accessible public Facebook groups are supported.
- Private, hidden, login-required, age-gated, and geography-restricted feeds are outside scope.
- Group URLs must contain a numeric group ID; vanity-only paths are rejected.
- Facebook decides feed ordering, retention, and fields exposed to signed-out visitors.
- When `searchTerms` or `since` is active, each group is scanned for at most two public feed pages. This keeps filtered monitoring bounded, so a high `maxItems` value can return fewer matching posts.
- The Actor does not scrape comments, group members, private profiles, or reaction identities.
- Visible engagement can be missing or differ from a logged-in view.
- Author profile URLs and profile images are sometimes omitted in anonymous responses.
- Media CDN URLs can be temporary; download permitted media promptly if your workflow requires durable files.
- Internal Facebook response changes can temporarily require an Actor update.

A first-page response without a recognizable public post feed fails non-zero. Later pagination ends normally when Facebook reports no next cursor.

### Responsible use and legality

Use this Actor only for data you are legally entitled to collect and process. Public visibility does not remove obligations under Facebook's terms, copyright rules, privacy law, data-protection law, or local regulations.

Do not use output for harassment, discrimination, surveillance of vulnerable people, identity profiling, or attempts to infer sensitive personal attributes. Minimize retained personal data, document a lawful purpose, restrict access, honor deletion requirements, and apply appropriate retention periods.

This Actor does not provide legal advice. Consult qualified counsel for regulated, high-risk, or large-scale uses.

### Troubleshooting

#### “Use a public Facebook group URL containing its numeric group ID”

The supplied URL is not a supported `facebook.com/groups/<numeric-id>/` address. Find a URL that includes the group's numeric ID and try again.

#### “Facebook returned no recognizable public post feed”

The group may be private, inaccessible to signed-out visitors, empty, restricted, or temporarily returning a challenge. Confirm public accessibility and retry later. Do not add Facebook cookies; the Actor intentionally has no credential input.

#### The run succeeded with zero dataset items

If a recognizable feed loaded, your `searchTerms` or `since` filter may have excluded every post. Remove the filters and test with a small limit.

#### Some engagement or author fields are null

Facebook did not expose those values in the anonymous response. Null is intentional and preferable to fabricated data.

#### A run stopped after retries

Inspect the log for an HTTP, rate-limit, or GraphQL response error. The Actor retries transient failures and rotates the residential session once; persistent upstream rejection is reported rather than hidden.

### Related tools and integrations

This Actor is intentionally standalone because the current Automation Lab portfolio does not have a closer public-Facebook companion that adds a truthful adjacent workflow. Combine its default dataset with Apify Schedules, Webhooks, Google Sheets, Slack, Zapier, Make, or your own database pipeline.

If you need comments, private-group content, member lists, or authenticated profile data, do not treat this Actor as an equivalent solution. Those workflows require different permissions and product boundaries.

### FAQ

#### Does it need my Facebook login or cookies?

No. It uses an anonymous public-data route and does not accept Facebook credentials.

#### Can it scrape private Facebook groups?

No. Private and login-only groups are explicitly excluded.

#### Can I scrape several groups in one run?

Yes. Add up to 100 supported URLs. `maxItems` applies across the entire run and groups are processed in input order.

#### Does `searchTerms` search Facebook globally?

No. It filters visible post text retrieved from the supplied groups. It does not discover groups or run a Facebook-wide search.

#### Are comments included?

No. The output contains the visible comment count when available, not comment bodies or authors.

#### Why does a filtered run inspect more posts than it saves?

Filtering happens after the public feed response is parsed. The Actor scans at most two public feed pages per group when filters are active, while item events are emitted only for saved records.

#### Can I schedule incremental monitoring?

Yes. Schedule the Actor and set `since` to the last timestamp your workflow processed. Apify schedules do not automatically rewrite input, so update the timestamp in your task or downstream automation when strict incrementality matters.

#### Is every historical post guaranteed?

No. Facebook controls what its anonymous feed exposes and in what order. Treat output as the publicly observable feed at run time, not a complete archival export.

# Actor input Schema

## `startUrls` (type: `array`):

One or more public group URLs containing a numeric group ID, such as https://www.facebook.com/groups/1443890352589739/. Posts are collected in the order the groups are supplied.

## `maxItems` (type: `integer`):

Maximum number of accepted post records across all supplied groups. Filtering can require reading more source posts than this value.

## `searchTerms` (type: `array`):

Optional case-insensitive terms. A post is saved when its visible text contains at least one term. Filtered runs scan at most two public feed pages per group. Supply no terms to keep all posts.

## `since` (type: `string`):

Optional ISO 8601 date or timestamp. Only posts at or after this time are saved. Filtered runs scan at most two public feed pages per group.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.facebook.com/groups/1443890352589739/"
    }
  ],
  "maxItems": 10,
  "searchTerms": [],
  "since": "2025-01-01T00:00:00.000Z"
}
```

# Actor output Schema

## `dataset` (type: `string`):

Default dataset containing all accepted post records.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://www.facebook.com/groups/1443890352589739/"
        }
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/facebook-group-posts-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrls": [{ "url": "https://www.facebook.com/groups/1443890352589739/" }],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/facebook-group-posts-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.facebook.com/groups/1443890352589739/"
    }
  ],
  "maxItems": 10
}' |
apify call automation-lab/facebook-group-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/facebook-group-posts-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Qj1Ba9prQDoc2PAme/builds/YIaaX1jCDI3BhQRUN/openapi.json
