# Facebook Scraper: Pages, Posts, Groups & Comments (`apisamurai/facebook-scraper`) Actor

Facebook scraper for public pages, profiles, page and group posts, post details and comments by URL. No login or cookies, free date filter, exact limits, pay only for real rows.

- **URL**: https://apify.com/apisamurai/facebook-scraper.md
- **Developed by:** [API Samurai](https://apify.com/apisamurai) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 post from feeds

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 Scraper: Pages, Posts, Groups & Comments

This Facebook scraper gets public data from Facebook pages, profiles, groups, posts and comments by URL. Page rows come with category, likes, followers, email, phone, website, address and ad status. Post rows come with text, date, reactions, comment count, shares, views, photos, video links and author. Comment rows come with text, date, reactions, reply count and commenter. No Facebook account, login or cookies are needed, the date filter is free, and you pay only for real, unique rows.

### What you can use it for

- **Monitor brand and competitor pages**: new posts, reactions and comments on a schedule.
- **Collect leads** from business pages: email, phone, website, address and category.
- **Track public groups** for topics, questions and product mentions.
- **Analyze audience reactions** with full comment text for sentiment and AI datasets.
- **Check ad activity**: each page row says whether the page is running ads.

### How to use

1. Open the [Facebook Scraper](https://apify.com/apisamurai/facebook-scraper) page and click **Try for free**.
2. Paste page, profile or group links, and any post links, one per line.
3. Set **Max posts per page, profile or group**, and optionally **Posted after** and **Add comments of each post**.
4. Click **Start**. Rows appear in the **Output** tab while the run works.
5. Export the dataset as JSON, CSV or Excel, or check the `SUMMARY` record in the key-value store.

**API:** start a run and get the rows in one call with `POST https://api.apify.com/v2/acts/apisamurai~facebook-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>` and the input as JSON in the body.

### Input

| Field | What it does |
|---|---|
| Page, profile or group links | `https://www.facebook.com/NASA`, `profile.php?id=...` or `/groups/...`. Pages give one page row plus recent posts; groups give recent posts. |
| Post links | `/posts/...`, `/reel/...`, `/watch/?v=...`, `/videos/...`, `/photo/?fbid=...`, `/groups/.../posts/...` or `/share/p/...`. One row per post. |
| Add recent posts of each page or profile | On by default. Newest first. |
| Max posts per page, profile or group | Default 10. Enforced exactly. |
| Posted after | `2026-10-01` or `7 days`. Older posts are skipped and not charged. |
| Add comments of each post | Off by default. One row per comment. |
| Max comments per post | Default 20. Enforced exactly. |

```json
{
  "pageUrls": ["https://www.facebook.com/NASA", "https://www.facebook.com/groups/742354120555345/"],
  "postUrls": ["https://www.facebook.com/reel/1535656380759655"],
  "includePosts": true,
  "maxPostsPerPage": 20,
  "postedAfter": "30 days",
  "includeComments": true,
  "maxCommentsPerPost": 50
}
```

### Output

One row per page, post or comment; `type` tells them apart. Field names never change between runs, and missing values are `null`, never a fake 0. Example post row from a live run (shortened):

`json
{
  "type": "post",
  "id": "1705688854261871",
  "url": "https://www.facebook.com/natgeo/posts/pfbid025aNMbNrYGNizGSMp7coqF46h91hSSQdyAo3AhYhCwoUeyJF3ceXyFA8YhKSErP3sl",
  "permalink": "https://www.facebook.com/natgeo/posts/pfbid025aNMbNrYGNizGSMp7coqF46h91hSSQdyAo3AhYhCwoUeyJF3ceXyFA8YhKSErP3sl",
  "text": "Over more than a decade, a total of 15 feet washed ashore along the Salish Sea. This type of mystery, it turns out, re...",
  "postedAt": "2026-10-30T01:00:00.000Z",
  "reactions": 933,
  "reactionBreakdown": {
    "thankful": 0,
    "like": 763,
    "love": 12,
    "care": 5,
    "haha": 4,
    "wow": 138,
    "sad": 7,
    "anger": 4,
    "pride": 0,
    "confused": 0
  },
  "commentsCount": 119,
  "shares": 83,
  "views": null,
  "author": {
    "id": "100044623170418",
    "name": "National Geographic",
    "handle": null,
    "url": null,
    "verified": null,
    "imageUrl": null
  },
  "imageUrls": [
    "https://scontent-bos5-1.xx.fbcdn.net/v/t39.30808-6/873928258_1705688834261873_3243387074114719293_n.jpg?..."
  ],
  "video": null,
  "link": null,
  "isPaidPartnership": null,
  "sharedPostId": null,
  "sharedPostUrl": null,
  "topComments": [
    {
      "id": "Y29tbWVudDoxNzA1Njg4ODU0MjYxODcxXzk3NTk3OTU5ODM2MzA2NA==",
      "text": "The feet belong to people who died by accident or suicide in the sea, their bodies sank but the...",
      "postedAt": "2026-10-30T01:25:02.000Z",
      "author": {
        "id": "pfbid0Pc4FR9LkqPiii8TFFgh4DbodHt5Chc5TZiU1Kg8raAA7mYoCrAuXxmuT91hcDhHzl",
        "name": "Samara Dyva",
        "url": null,
        "imageUrl": null
      }
    }
  ],
  "source": "page",
  "input": "https://www.facebook.com/natgeo",
  "scrapedAt": "2026-10-31T16:24:49.190Z"
}
`

Page rows have `type: "page"`, `id`, `name`, `url`, `category`, `intro`, `likes`, `followers`, `talkingAbout`, `rating`, `ratingCount`, `email`, `phone`, `website`, `address`, `links`, `services`, `priceRange`, `createdAt`, `isBusinessPageActive`, `adStatus`, `adLibraryPageId`, `profilePicUrl`, `coverPhotoUrl`, `input`, `scrapedAt`.

Post rows have `type: "post"`, `id`, `url`, `permalink`, `text`, `postedAt`, `reactions`, `reactionBreakdown`, `commentsCount`, `shares`, `views`, `author` (`id`, `name`, `handle`, `url`, `verified`, `imageUrl`), `imageUrls`, `video` (`url`, `sdUrl`, `hdUrl`, `thumbnailUrl`, `durationSeconds`), `link` (shared link preview), `isPaidPartnership`, `sharedPostId`, `sharedPostUrl`, `topComments`, `source` (`page`, `group` or `post`), `input`, `scrapedAt`. Group feeds do not show shares, and views are only known for videos.

Comment rows have `type: "comment"`, `id`, `postId`, `postUrl`, `text`, `postedAt`, `reactions`, `reactionBreakdown`, `repliesCount`, `author` (`id`, `name`, `url`, `imageUrl`), `attachments`, `source`, `input`, `scrapedAt`.

Each run also writes a `SUMMARY` record. For every input link it lists rows requested and delivered, posts and comments delivered, posts older than **Posted after**, duplicates, links not found, failed lookups, and why it stopped (`limit reached`, `no more results`, `older than postedAfter`, `private or not found`, `duplicate`, `temporary error`, `spending limit`, `free plan limit` or `data source unavailable`).

### Pricing

$6.50 per 1,000 pages; $2.40 per 1,000 posts from page and group feeds; $6.50 per 1,000 posts by link; $0.75 per 1,000 comments

### Fair billing

- No start fee, no per-run fee, no minimum charge. You pay per row saved.
- The date filter is free. Posts older than **Posted after** are skipped and never charged, and paging stops once a feed is past the date.
- Only real rows are charged. Private, missing and age-restricted pages and posts cost nothing.
- Duplicates are never charged. A post found in a feed and also pasted as a link is saved once.
- Failed lookups are not charged. They are counted in the `SUMMARY` record and listed in the log.
- Post and comment limits are exact: you never get, or pay for, more than you asked.
- When you hit your spending limit, the run stops cleanly.
- Free Apify plan: up to 100 rows per run, so you can try it. Any paid plan removes the limit.

### Integrations

- **Apify API** to start runs and read datasets from any language, plus the Python and JavaScript clients (`apify-client`).
- **Zapier, Make and n8n** to send new rows to Google Sheets, HubSpot, Slack or a database.
- **MCP for AI agents:** connect the Apify MCP server to Claude, ChatGPT or another MCP client and the agent can run this Actor as a tool.
- **Schedules and webhooks** in Apify Console for daily or weekly runs.

### FAQ

**Do I need a Facebook account, login or cookies?**
No. You only need an Apify account. The Actor reads public data, the same as a logged-out visitor sees.

**Can it scrape private groups or personal profiles that are not public?**
No. Only public pages, public profiles and public groups. Private and age-restricted pages are reported as `private or not found` and are not charged.

**Why do posts by link cost more than posts from a feed?**
A page or group feed returns about 3 posts per data request, while a post link needs a request of its own. Post links also include the share count for group posts and, when Facebook shows them, view counts.

**Why did I get fewer rows than I asked for?**
Open the `SUMMARY` record. It says for each link why it stopped: no more posts, the **Posted after** date, a duplicate, a private or missing page, a temporary error, the spending limit or the free plan limit.

**Does "Posted after" filter comments too?**
No. It filters posts. Comments are collected for every post that is saved, up to **Max comments per post**.

**Does it get replies to comments?**
No. Comment rows are top-level comments with their reply count.

**Can I schedule it?**
Yes. Create a schedule in Apify Console, for example a daily run over your pages with **Posted after** set to `1 day`, and connect an integration to get the new rows.

**Is it legal to scrape Facebook?**
The Actor collects only public data. You are responsible for how you use it: follow Facebook's terms and the laws where you live, and take care with personal data (for example under GDPR). This is not legal advice.

# Actor input Schema

## `pageUrls` (type: `array`):

Public Facebook pages, profiles or groups, e.g. https://www.facebook.com/NASA, https://www.facebook.com/profile.php?id=100064... or https://www.facebook.com/groups/... One per line. Pages and profiles give one page row (category, likes, followers, contact details, ad status) plus their recent posts when turned on. Public groups give their recent posts.

## `postUrls` (type: `array`):

Full details of these posts, videos, reels or photos: text, date, reactions, comments count, shares, views, media and author. Links like https://www.facebook.com/<page>/posts/..., /reel/..., /watch/?v=..., /groups/<group>/posts/..., /photo/?fbid=... or /share/p/.... One per line.

## `includePosts` (type: `boolean`):

On: also save the recent posts of each page and profile, newest first, one row per post. Group links always return posts.

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

Maximum post rows for each page, profile or group. Enforced exactly.

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

Only posts published on or after this date, e.g. 2026-10-01, or a relative value like 7 days or 3 months. Older posts are skipped and never charged, and paging stops once a feed is past this date. Leave empty for all posts.

## `includeComments` (type: `boolean`):

On: also save the comments of every post in this run (from pages, profiles, groups and post links), one row per comment with text, date, reactions, reply count and commenter name.

## `maxCommentsPerPost` (type: `integer`):

Maximum comment rows for each post when comments are on. Enforced exactly.

## Actor input object example

```json
{
  "pageUrls": [
    "https://www.facebook.com/NASA"
  ],
  "includePosts": true,
  "maxPostsPerPage": 3,
  "includeComments": false,
  "maxCommentsPerPost": 20
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (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 = {
    "pageUrls": [
        "https://www.facebook.com/NASA"
    ],
    "maxPostsPerPage": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("apisamurai/facebook-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 = {
    "pageUrls": ["https://www.facebook.com/NASA"],
    "maxPostsPerPage": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("apisamurai/facebook-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 '{
  "pageUrls": [
    "https://www.facebook.com/NASA"
  ],
  "maxPostsPerPage": 3
}' |
apify call apisamurai/facebook-scraper --silent --output-dataset

```

## MCP server setup

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