# Facebook Posts Scraper — Pages & Profiles (`data-wan/facebook-posts`) Actor

Collect public Facebook Page and profile posts without a Facebook account. Get text, authors, engagement and available media references. Choose a post limit per source and filter by publication date.

- **URL**: https://apify.com/data-wan/facebook-posts.md
- **Developed by:** [Data Wan](https://apify.com/data-wan) (community)
- **Categories:** Social media
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.79 / 1,000 saved posts

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Facebook Posts Scraper

Collect posts from public Facebook Pages and anonymously accessible profiles. Get text,
publication dates, authors, engagement counts and available media references in one dataset.
No Facebook account or cookies are required.

**$0.99 per 1,000 saved posts on Free / Starter, $0.89 on Scale and $0.79 on Business.**
Platform usage is included: no separate compute, proxy, Actor start or date-filter fee.
Twenty saved posts cost **$0.0198** at the Free / Starter rate. Check the Pricing tab for
the active rate before starting; Free is the account plan, not a free trial.

Use this Actor for content research, publishing activity and engagement comparisons.
Choose an independent post limit for each source, or collect a publication window.
Requested sources, observed authors and shared originals stay distinct in the results.

### First run: one Page, up to 20 posts

1. Open the Input form and paste a public Page or profile link into **Page or profile URLs**.
   The prefilled BBC News Page is a starting example.
2. Set **Maximum posts per source** to **20**, then click **Start**.
3. When processing finishes, open **Output** to inspect the dataset and download results.
   Also check the run summary for each source's outcome.

The equivalent JSON input is:

```json
{
  "sourceUrls": ["https://www.facebook.com/bbcnews/"],
  "maxPostsPerSource": 20
}
```

The default table shows the first observed author and first media preview when available.
**Full details** keeps all observed authors, media, reactions, shared-original context and
field issues. A missing preview does not mean the post has no media.

#### What results look like

This is a **synthetic illustration**, not a Facebook capture or an Apify Console screenshot.
Each row is one post; nested authors or media do not create extra post rows.

| Post | Published (UTC) | First author | Reactions | Comments | Shares |
|---|---|---|---:|---:|---:|
| An example update with a link. | 2026-10-01 12:00 | Example Page | 125 | 18 | 7 |

Selected fields from the same synthetic row:

```json
{
  "postId": "9000000000000003",
  "createdAt": "2026-10-01T12:00:00Z",
  "text": "An example update with a link.",
  "textLinks": ["https://example.com/article"],
  "authors": [
    {"id": "9000000000000001", "name": "Example Page", "url": "https://www.facebook.com/example/", "avatarUrl": null}
  ],
  "reactionsCount": 125,
  "commentsCount": 18,
  "sharesCount": 7,
  "attachments": [],
  "sharedPost": null,
  "issues": [],
  "sourceUrl": "https://www.facebook.com/example/"
}
```

`textLinks` contains observed message destinations. `attachments` holds available media or
link attachments; it is empty in this illustration. `sharedPost`, when available, contains
the original post's own text, authors and media separately from the collected wrapper.
The JSON above shows selected fields; complete rows also carry source and input identity.

### Collect from several Pages

For a comparison, request up to 100 posts from each source. This example saves at most
200 rows, costing at most **$0.198** at the $0.99-per-1,000 event rate if all 200 are saved.

```json
{
  "sourceUrls": [
    "https://www.facebook.com/bbcnews/",
    "https://www.facebook.com/cern/"
  ],
  "maxPostsPerSource": 100
}
```

Every input is processed independently, including repeated inputs. A post appearing in
several sources is saved and billed separately for each input. Fresh runs can repeat posts too.

### Research a publication period

```json
{
  "sourceUrls": ["https://www.facebook.com/bbcnews/"],
  "maxPostsPerSource": 200,
  "since": "2026-10-01",
  "until": "2026-10-07"
}
```

Calendar dates include the whole UTC day. Exact boundaries accept timezone-aware,
whole-second timestamps such as `2026-10-01T12:00:00Z` or `2026-10-01T15:00:00+03:00`.
Both bounds are inclusive. Posts with unknown publication dates are retained with an
`unverifiable_date_window` issue; they are not confirmed matches for the chosen period.

#### Monitor new publications

For each run, set `since` to your last completed cutoff and `until` to the end of the new
window. Include some overlap and deduplicate saved results by `postId`; inclusive bounds
can return a boundary post again. Advance the cutoff only after that source's window ends
`complete`. `limit_reached`, `incomplete`, a partial run or a timeout does not establish
coverage: increase the limit or resolve the interruption before advancing. Feed order is
not guaranteed newest first. Keep unknown-date rows separate when assessing window coverage.

Checking engagement on older posts is a different job from finding new publications:
use a window that includes those older posts to collect their current available counts.
The Actor keeps no automatic monitoring state or resume checkpoint.

### Input reference

| Option | Meaning |
|---|---|
| `sourceUrls` | Public Facebook Page/profile URLs; direct post, group and search URLs are unsupported. |
| `sourceIds` | Numeric Page/profile IDs as strings, as an alternative to URLs. |
| `maxPostsPerSource` | Strict saved-post limit for each input: default 100, allowed 1–10,000; the form starts at 20. |
| `since`, `until` | Optional inclusive publication bounds, as UTC days or timezone-aware timestamps. |

Provide 1–1,000 sources across the two source lists combined. URLs are processed before IDs.
A permitted limit does not guarantee the run can finish within its timeout or budget.

### Output fields

| Fields | Contents |
|---|---|
| `postId`, `url` | Collected post identity and observed permalink. |
| `text`, `textLinks` | Available text and observed message links. |
| `createdTime`, `createdAt` | Publication time as Unix seconds and a UTC timestamp. |
| `authors` | All observed authors with available IDs, names, profile and avatar URLs. |
| `reactionsCount`, `commentsCount`, `sharesCount`, `videoViewCount` | Available engagement counts; unknown values stay null. |
| `reactions` | Observed reaction types and counts, which may be a subset. |
| `attachments`, `sharedPost` | Feed-visible media/link references and separate shared-original context. |
| `inputIndex`, `inputUrl`, `inputSourceId`, `sourceId`, `sourceUrl` | Original input position and resolved source identity. |
| `feedbackId`, `issues` | Observed feedback identity and field-level uncertainty. |

Media references are not downloaded files. Viewer links, previews and direct media URLs
have separate fields; URLs may expire. Album items and video variants are limited to what
the feed exposes. No complete album, complete text/link inventory or full archive is promised.
Unknown data stays null with issues where applicable; observed zero and empty lists remain distinct.

### Exports, API and schedules

Apify provides [dataset downloads](https://docs.apify.com/storage/dataset)
for formats such as JSON, CSV and Excel, and [API access](https://docs.apify.com/api/v2/actors-runs-post)
to start runs from another application. These are Apify platform features.
Use [Apify schedules](https://docs.apify.com/actors/running/schedules) for recurring runs.
A normal schedule reruns the input you supplied: fixed `since`/`until` dates do not advance
automatically. Update those bounds yourself or through your workflow for moving windows.

### Run outcomes and common questions

**Where do I check completeness?** Read the unbilled run summary, including every input.
`complete` means the available traversal finished, including confirmed zero results;
`limit_reached` means the requested cap was reached. `incomplete` stopped early;
`failed` / `invalid_source` could not be collected; `skipped` was not processed.
A successful platform run can contain unsuccessful inputs. An inaccessible source does
not establish that it is private, deleted or empty. Other inputs' saved posts remain available.

**What survives an interrupted run?** Acknowledged rows remain in the dataset. Some inputs
may be unfinished, and interruption can leave summary counts behind the retained rows.
Check the dataset itself. A new run starts over and may save and bill the same posts again.

**Are empty inputs or the summary charged?** No. Billing counts saved post rows, including
duplicates across independently processed inputs or repeated runs. There is no separate
Actor start, publication-date-filter, compute or proxy fee.

**Can I collect comment text?** This Actor returns available comment counts. Use the
separate [DataWan Facebook Comments Scraper](https://apify.com/data-wan/facebook-comments)
for comment bodies and optional replies; its runs and charges are separate.

**Need help?** Open an [issue on this Actor](https://apify.com/data-wan/facebook-posts/issues)
with the run link, intended input and expected outcome. Do not include account credentials.

# Actor input Schema

## `sourceUrls` (type: `array`):

Public Facebook Page/profile links. Together with Source IDs: 1–1,000 inputs. Each input is processed independently.

## `sourceIds` (type: `array`):

Numeric Page/profile IDs as strings. Together with Source URLs: 1–1,000 inputs.

## `maxPostsPerSource` (type: `integer`):

One limit applies independently to each source, including repeated inputs.

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

Optional UTC calendar day (2026-10-01) or timezone-aware timestamp (2026-10-01T12:00:00Z), inclusive. Unknown-date posts are retained with an issue.

## `until` (type: `string`):

Optional UTC calendar day (2026-10-07 includes that entire day) or timezone-aware timestamp, inclusive. Omit or use null for no upper bound.

## Actor input object example

```json
{
  "sourceUrls": [
    "https://www.facebook.com/bbcnews/"
  ],
  "maxPostsPerSource": 20
}
```

# Actor output Schema

## `summary` (type: `string`):

No description

## `posts` (type: `string`):

No description

# 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 = {
    "sourceUrls": [
        "https://www.facebook.com/bbcnews/"
    ],
    "maxPostsPerSource": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("data-wan/facebook-posts").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 = {
    "sourceUrls": ["https://www.facebook.com/bbcnews/"],
    "maxPostsPerSource": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("data-wan/facebook-posts").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 '{
  "sourceUrls": [
    "https://www.facebook.com/bbcnews/"
  ],
  "maxPostsPerSource": 20
}' |
apify call data-wan/facebook-posts --silent --output-dataset

```

## MCP server setup

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

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/InkyRQ0vgc0Cg6kYs/builds/Pr2shhOr1s0ukmNc0/openapi.json
