# Facebook Page Posts Scraper — Reactions by Kind, No Login (`foxlabs/facebook-page-posts-scraper`) Actor

Posts of public Facebook Pages, newest first: text with mentions and links, exact time, kind, photos and video, reactions in total and by kind (like, love, care, haha, wow, sad, angry), comment and share counts, video views, reactions per hour, top comments. Only-new mode. No login.

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

## Pricing

$2.00 / 1,000 posts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Page Posts Scraper — Reactions by Kind, No Login 🚀

**foXLabs Facebook series:** [Page Profile](https://apify.com/foxlabs/facebook-page-profile-scraper) · [Post Comments](https://apify.com/foxlabs/facebook-post-comments-scraper) · [Page Reviews](https://apify.com/foxlabs/facebook-page-reviews-scraper) · [Page Videos](https://apify.com/foxlabs/facebook-page-videos-scraper) · [Page Events](https://apify.com/foxlabs/facebook-page-events-scraper)

🎉 Posts of public Facebook Pages, newest first, exactly as Facebook shows them to a visitor who is not signed in — the text, exact time, kind, photos and video, **reactions in total and by kind (like, love, care, haha, wow, sad, angry)**, comment and share counts, video views — plus what this Actor adds: how fast a post gathers reactions and comments per hour, hashtags, and the post's top comments. No login, no cookies, no account of anyone. Only-new mode for recurring runs.

### 🔍 What is the Facebook Page Posts Scraper — and when should you use it?

Give this Actor one or more public Facebook Pages and it returns their posts as clean rows — one per post, newest first, with the engagement numbers broken down by reaction kind and normalized per hour so you can compare posts fairly.

**Use it when you need:** a Page's recent posts with full engagement; social-listening or competitor content tracking across many Pages; the fastest-growing posts (reactions/comments per hour); or a recurring feed of only-new posts.

**Use something else when:** you need *every* comment on a post → [Facebook Post Comments Scraper](https://apify.com/foxlabs/facebook-post-comments-scraper); the Page's contact/profile record → [Facebook Page Profile Scraper](https://apify.com/foxlabs/facebook-page-profile-scraper); reviews → [Reviews](https://apify.com/foxlabs/facebook-page-reviews-scraper); videos/reels → [Videos](https://apify.com/foxlabs/facebook-page-videos-scraper).

### 🤖 Use with AI agents

**Already on the Apify MCP server?** Ask for this Actor by name: `foxlabs/facebook-page-posts-scraper`. An agent can discover it, run it and read the dataset over MCP.

**Real-time Standby API.** This Actor ships a Standby endpoint so an agent can fetch a Page's newest posts on demand — `GET /posts?page=NASA&maxPosts=12` returns rows immediately, billed with the same `post` event. Parameters: `page`, `maxPosts`, `postKinds`, `minReactions`, `minComments`, `postedAfter`, `topComments` (1/0).

Otherwise paste this into Claude, ChatGPT, Cursor or any MCP-enabled assistant:

```
I want public Facebook Page posts with engagement using the Apify Actor
`foxlabs/facebook-page-posts-scraper`.

Input: `pages` is a list of Pages (name, @handle, numeric id or URL). `maxPostsPerPage` caps
rows per Page. Each row has text, kind, createdAt, reactions, reactionsByType, commentCount,
shareCount, reactionsPerHour and the post's topComments.

Start with:
{ "pages": ["NASA"], "maxPostsPerPage": 25 }

Ask me which Pages to track, run the Actor, then summarise the posts as a table.
```

The machine-readable API, MCP config and OpenAPI definition live at `apify.com/foxlabs/facebook-page-posts-scraper.md`.

### 📋 Overview

Everything you need to turn a public Facebook Page's timeline into clean, structured data — full post details, engagement by reaction kind and velocity signals — in one Actor, with no login, cookies or account.

**Why teams pick this Actor:**

- ✅ **Reactions by kind** — not just a total, but like/love/care/haha/wow/sad/angry each with its count.
- ⚡ **Velocity built in** — reactions and comments per hour since the post went up.
- 🎯 **Honest nulls** — a value Facebook does not give is `null`, never `0` for "unknown".
- 🔁 **Only-new mode** — schedule recurring runs that bring only posts not seen before.
- 💰 **Pay only for results** — one `post` event per delivered row; filters, status rows and unreadable Pages are free.
- 🤖 **Agent-ready** — MCP + a real-time Standby API.

### ✨ Features

- 🔍 **Whole timeline, newest first** — by Page name, @handle, numeric id or URL.
- 📄 **Full post** — text, kind (text/photo/album/video/reel/link), photos at full size, video (plays, duration, playable URL), shared link, mentions, hashtags.
- ❤️ **Engagement** — total reactions, reactions by kind, comment and share counts, video views, and per-hour velocity.
- 💬 **Top comments** — the two or three Facebook shows under the post, on each row.
- 🔁 **Only-new lists** — remember delivered posts under a name and skip them next run.
- 📦 **Clean export** — deduplicated camelCase rows, ready for CSV/Excel/JSON.

### 🎬 Quick Start

```bash
curl -X POST "https://api.apify.com/v2/acts/foxlabs~facebook-page-posts-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"pages": ["NASA"], "maxPostsPerPage": 25}'
```

### 🚀 Getting Started (3 steps)

1. **Choose your Pages** — one per line: `NASA`, `@NASA`, a numeric id or a full URL.
2. **Set the cap** — `maxPostsPerPage` limits rows per Page (default 100), newest first.
3. **Run and export** — get a clean dataset as JSON, CSV or Excel.

### 📥 Input

| Field | Default | What it does |
|---|---|---|
| `pages` | — | One Page per line: `NASA`, `@NASA`, a numeric id, or `https://www.facebook.com/NASA`. A Page written twice is read once. |
| `maxPostsPerPage` | 100 | Posts to deliver for each Page, from the newest down. |
| `maxPosts` | 100000 | Rows in the whole run; the run stops there. |
| `postedAfter` | — | A date (2026-10-01): the walk down a Page stops at older posts. |
| `postKinds` | all | Keep only these kinds; the rest are skipped, not charged. |
| `minReactions`, `minComments` | — | Keep only posts at or above these counts. |
| `includeTopComments` | true | The post's top comments on each row (no extra request). |
| `onlyNewPosts`, `listName` | false, `default` | Remember delivered posts under a name and skip them in later runs. |
| `proxyConfiguration` | residential Apify Proxy | Nothing to change for normal use (see "How it reads Facebook"). |

A run with one Page and the defaults delivers up to 100 posts.

### 📤 Output

One row per post. A value Facebook does not give is `null` — never `0` for "unknown".

| Field | What it is |
|---|---|
| `postId`, `url` | the post's id and permalink |
| `pageId`, `pageName`, `pageUrl`, `pageIsVerified` | the Page, as the post names it |
| `text` | the post's text (null for a reel or video without a caption) |
| `kind` | `text`, `photo`, `album`, `video`, `reel`, `link` |
| `createdAt`, `hoursSincePost` | when it went up (UTC), and the hours since |
| `reactions`, `reactionsByType` | all reactions, and each kind with its count |
| `commentCount`, `shareCount`, `videoViews` | Facebook's own counts |
| `reactionsPerHour`, `commentsPerHour` | counts divided by the hours since the post |
| `images` | every photo at full size: `id`, `url`, `width`, `height`, `accessibilityCaption` |
| `video` | for a video/reel: `id`, `url`, `title`, `playableUrl`, `hdUrl`, `durationSeconds`, `views`, `thumbnailUrl` |
| `link` | the shared link: `url` (unwrapped), `title`, `description`, `source`, `imageUrl` |
| `mentions`, `hashtags` | tagged Pages/people; hashtags in the text |
| `topComments` | the two or three comments Facebook shows under the post |
| `canComment`, `isSponsored` | whether visitors can comment; whether the post is sponsored |
| `position`, `input` | place in the timeline (1 = newest) and the input line it came from |
| `type`, `error` | `post` for a data row; `status` + `error` for a free row explaining an empty line |

```json
{
  "type": "post",
  "postId": "1652244896270880",
  "url": "https://www.facebook.com/NASA/posts/pfbid0dPToN66…",
  "pageId": "100044561550831",
  "pageName": "NASA - National Aeronautics and Space Administration",
  "pageIsVerified": true,
  "text": "Brewing up baby stars ⭐ NASA's James Webb Space Telescope…",
  "kind": "photo",
  "createdAt": "2026-10-09T20:54:33.000Z",
  "hoursSincePost": 24.7,
  "reactions": 5362,
  "reactionsByType": { "like": 3173, "love": 1994, "care": 107, "wow": 75, "haha": 12, "angry": 1 },
  "commentCount": 108,
  "shareCount": 565,
  "reactionsPerHour": 216.7,
  "commentsPerHour": 4.4,
  "topComments": [{ "commentId": "848869361623320", "author": "Beyond Earth", "text": "That eight-pronged diffraction pattern is Webb's signature…", "reactions": 3 }],
  "position": 1,
  "input": "NASA"
}
```

### 💼 Use cases

**1. Competitor content tracking** — watch what a peer posts and how it performs.
*Input:* the competitor's Pages, scheduled daily with `onlyNewPosts`. *Output:* new posts + engagement. *Use:* benchmark cadence and what resonates.

**2. Social listening & virality** — catch the posts gaining traction fastest.
*Input:* many Pages, `minReactions` set. *Output:* posts sorted by `reactionsPerHour`. *Use:* surface what's taking off now.

**3. Content research** — study a Page's best posts by format and reaction mix.
*Input:* one Page, `postKinds` filter. *Output:* posts with `reactionsByType`. *Use:* learn which formats and emotions win.

### 🔗 Integration

**JavaScript / Node.js**

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('foxlabs/facebook-page-posts-scraper').call({
  pages: ['NASA'], maxPostsPerPage: 25,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0]);
```

**Python**

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('foxlabs/facebook-page-posts-scraper').call(
    run_input={'pages': ['NASA'], 'maxPostsPerPage': 25}
)
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)
```

Written for `apify-client` 3 for Python, where `call()` returns a run object; with version 1 or 2 it returns a dict — write `run['defaultDatasetId']` there.

**Automation (n8n / Zapier / Make):** schedule or webhook → HTTP request to the Actor API with your `pages` → handle the JSON dataset → push to a sheet, CRM or dashboard.

### 📊 Pricing

Pay per event, one event per delivered row: **`post`**. The price is on the Pricing tab. Nothing else is charged: no start fee, no charge for a status row, none for a post the filters left out, none for a Page that could not be read. A run that delivers nothing costs nothing.

Platform usage besides the rows: the Actor reads Facebook through residential proxy, about 55 KB a post on the wire (measured 2026-10-10), which the per-row price covers.

### ❓ FAQ

**Do I need a Facebook account, login or cookies?** No. It reads only what Facebook shows a signed-out visitor on public Pages — no login, no cookies, no account, no CAPTCHA solving.

**What can I search by?** A Page name, `@handle`, numeric id or full URL — one per line.

**Can I get every comment?** No — each row carries the two or three *top* comments Facebook shows. For all comments use the [Facebook Post Comments Scraper](https://apify.com/foxlabs/facebook-post-comments-scraper).

**How do I avoid re-delivering the same posts?** Turn on `onlyNewPosts` with a `listName` and schedule the run; each run brings only posts it hasn't delivered.

**How current is the data?** Every run reads Facebook live, newest first.

**Can I export to CSV / Excel / JSON?** Yes — directly from the Apify dataset.

### 🐛 Troubleshooting

- **Fewer posts than expected** — a visitor doesn't always see a whole timeline; some Pages show only part (the run stops where Facebook stops and says so), or `maxPostsPerPage`/filters are capping rows.
- **A Page returns a status row** — it's a personal profile, a group, or shown only to signed-in users; those are free, not charged.
- **`video.playableUrl` is empty** — Facebook only sometimes puts the file address in the timeline (~half of videos in our measurements); image URLs are signed and expire.
- **Reaction names** come back mapped to the seven standard kinds regardless of the Page's language.

**How it reads Facebook:** the Actor opens a Page as a signed-out visitor and asks Facebook's own timeline endpoint (three posts a call, newest first) using the tokens the Page's HTML carries. Facebook serves public Pages to residential addresses only, so Apify Proxy residential is used by default; rate-limited exit IPs are dropped and replaced. Every run starts with a one-call check and ends with a clear message (no empty rows) if Facebook's queries changed.

### ⚠️ Trademark

Independent, third-party tool. Not affiliated with, endorsed by or connected to Meta Platforms, Inc. "Facebook" and related marks belong to their owners and are used here for identification only.

### ⚖️ Is it legal to scrape this data?

It reads only what Facebook shows a signed-out visitor on public Pages. Posts and top comments carry the names of people who wrote them publicly; personal data is protected by the GDPR and similar laws, so only collect and process it with a legitimate basis. The Actor does not log in, use anyone's account or cookies, or solve CAPTCHAs. See Apify's blog post on the legality of web scraping.

### 🤝 Support & contact

- 🌐 **Website:** [data.foxlabs.com.tr](https://data.foxlabs.com.tr)
- 📧 **Email:** info@foxlabs.com.tr
- 🐛 **Issues:** open a ticket in the Actor's **Issues** tab — include the run id; the run's `SOURCE_REPORT` record holds what was asked, what Facebook answered and why the run stopped.
- 🧰 **More clean data actors:** [Fox Labs on Apify](https://apify.com/foxlabs)

### Changelog

#### 0.1.1 — 2026-10-11 — the shared core of the family

- The `video` of a video or reel post carries its duration from the player's data and its live status, and the post's text as its description when the video itself has none — the shared core was updated with the family's other Actors (Comments, Page Profile, Videos, Events, Reviews); the other fields of a post row are unchanged.

#### 0.1.0 — 2026-10-11 — first release

- Posts of public Facebook Pages as a signed-out visitor sees them: the Page's own HTML and the site's timeline query, three posts a call, newest first.
- Every row: text with mentions and links, exact time, kind, photos (full size), video (plays, duration, address), reactions in total and by kind, comment and share counts, video views, per-hour velocity, hashtags, top comments, comment/sponsored flags; the Page's id, name, URL and verification.
- Lines that bring nothing get a free status row; filters leave posts out without charging. Only-new lists for recurring runs; a restarted run continues without duplicates. Standby mode prepared; published in batch mode.

# Changelog

This Actor's version history is a separate document: https://apify.com/foxlabs/facebook-page-posts-scraper/changelog.md

# Actor input Schema

## `pages` (type: `array`):

One Page per line: a name (NASA), @NASA, a numeric id, or an address (https://www.facebook.com/NASA). The forms can be mixed; a Page written twice is read once. Only public Pages can be read — a Page Facebook shows to signed-in users only gets a status row that says so.

## `maxPostsPerPage` (type: `integer`):

How many posts to deliver for each Page, from the newest down. Facebook hands the timeline out three posts a call.

## `maxPosts` (type: `integer`):

The run stops when this many rows have been delivered. You are charged only for delivered rows.

## `postedAfter` (type: `string`):

A date such as 2026-10-01: the walk down each Page's timeline stops at older posts (a pinned post above them is still read). Leave empty for no date limit.

## `postKinds` (type: `array`):

Leave empty for every kind. Choose some to get only those; a post of another kind is skipped and not charged.

## `minReactions` (type: `integer`):

Deliver only posts with at least this many reactions. Leave empty for every post.

## `minComments` (type: `integer`):

Deliver only posts with at least this many comments. Leave empty for every post.

## `includeTopComments` (type: `boolean`):

The two or three comments Facebook shows under a post in the timeline (author, text, time, reactions) as topComments on the row. No extra request, no extra charge. For every comment of a post use the Facebook Post Comments Scraper.

## `onlyNewPosts` (type: `boolean`):

Remember delivered posts under the list name below and skip them in later runs. Schedule the same Pages hourly or daily and each run brings only the posts it has not delivered before. With this on, "Maximum posts per Page" is how far down each timeline the Actor looks.

## `listName` (type: `string`):

Name of the memory used by "Only posts not delivered before" (looked at only when that is on). Use a different name for each project. Letters, digits and hyphens (a hyphen not first or last), up to 40 characters; capitals are read as lower case.

## `proxyConfiguration` (type: `object`):

Nothing to change for normal use: the Actor reads Facebook through Apify Proxy residential addresses, the only kind Facebook serves its public Pages to (measured: residential 25 of 25 requests, datacenter 0 — sent to the login page). Set a proxy here to send every request through it instead; a setting the platform refuses ends the run before anything is read.

## Actor input object example

```json
{
  "pages": [
    "NASA"
  ],
  "maxPostsPerPage": 30,
  "maxPosts": 100000,
  "includeTopComments": true,
  "onlyNewPosts": false,
  "listName": "default"
}
```

# Actor output Schema

## `dataset` (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 = {
    "pages": [
        "NASA"
    ],
    "maxPostsPerPage": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("foxlabs/facebook-page-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 = {
    "pages": ["NASA"],
    "maxPostsPerPage": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("foxlabs/facebook-page-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 '{
  "pages": [
    "NASA"
  ],
  "maxPostsPerPage": 30
}' |
apify call foxlabs/facebook-page-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,foxlabs/facebook-page-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/tyJOhWurn7sziGWzr/builds/sdzukJlXcWnUlKDlS/openapi.json
