# Facebook Page Scraper (`apt_marble/facebook-page-scraper`) Actor

Scrape any public Facebook Page into one clean row: name, category, intro, follower and like counts, profile and cover images, both Page identifiers, and the newest public post with its reactions, comments and shares. Optional website, email and phone. No account or login needed.

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

## Pricing

$1.50 / 1,000 page scrapeds

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?

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 Page Scraper

Turn a list of Facebook Pages into a clean, structured table: the Page's name,
category, intro text, follower and like counts, its profile and cover imagery,
its two Facebook identifiers, and — if you want it — its most recent public
post with the reactions, comments and shares already attached. Give it a Page
link, a handle or a Page id and it gives you back one tidy row per Page. No
Facebook account, no login and no personal details are involved.

### What you can do with it

- **Build a competitor board.** Track the follower and like counts of every
  brand in your category and watch them move week over week.
- **Enrich a list you already have.** Feed in the Facebook links from a CRM
  export or a directory scrape and get back category, audience size, bio and
  imagery for each one.
- **Check what a brand posted last.** The newest public post arrives with its
  text, publish time, media and engagement counts, so a scheduled run doubles as
  a light-touch content monitor.
- **Verify that a handle still belongs to who you think it does.** Facebook
  reassigns vanity URLs, so every row reports the identity that actually came
  back and flags it when it does not match what you asked for.
- **Grab logos and cover art at scale** for a pitch deck, a comparison page or a
  directory listing.
- **Pull contact details too**, by switching on the contact option — the
  website, email and phone number a Page publishes in its intro block.

### What you get

One row per Page. An abridged real example:

```
{
  "pageId": "54971236771",
  "profileId": "100044561550831",
  "vanity": "NASA",
  "canonicalUrl": "https://www.facebook.com/NASA/",
  "name": "NASA - National Aeronautics and Space Administration",
  "category": "Government organization",
  "intro": "Explore the universe and discover our home planet.",
  "followers": 28000000,
  "followersAreApproximate": true,
  "followersText": "28M",
  "likes": 28660417,
  "talkingAboutCount": 87820,
  "profilePictureUrl": "<direct image link>",
  "coverPhotoUrl": "<direct image link>",
  "latestPost": {
    "postId": "1591339195694784",
    "url": "https://www.facebook.com/reel/1596135602179420/",
    "publishedAt": "2026-07-31T21:00:25.000Z",
    "text": "The sky is full of excitement this month! You can look forward to seeing: ...",
    "reactions": 2371,
    "reactionsBreakdown": { "like": 1974, "love": 349, "care": 29, "wow": 14, "haha": 2, "angry": 2, "sad": 1 },
    "comments": 92,
    "shares": 293,
    "mediaType": "Video",
    "mediaUrl": "<direct media link>",
    "isSponsored": false
  },
  "identityMatchesRequest": true,
  "requestedInput": "https://www.facebook.com/NASA/",
  "availability": "OK",
  "sourceUrl": "https://www.facebook.com/NASA/",
  "scrapedAt": "2026-08-01T09:14:02.318Z"
}
```

### Input reference

| Setting | Type | Default | What it does |
| --- | --- | --- | --- |
| **Facebook Pages** | list of text | one example Page | The Pages to scrape, one per line. A Page link, a handle with or without the @, or a Page's numeric id. Anything that is not a Page — a group, a post, a marketplace listing, a personal profile link — is skipped and noted in the log. |
| **Include the latest post** | yes / no | yes | Adds the Page's newest public post, with its text, publish time, media and engagement counts. |
| **Include contact details** | yes / no | no | Also returns the website, email and phone number the Page publishes. Slightly slower, because a second, lighter version of each Page is read. |
| **Browse from** | choice | United States | Which country to browse from. Facebook tailors some Pages by region. |
| **Pages at a time** | number 1–8 | 4 | How many Pages to work on simultaneously. Four is the sweet spot; higher settings do not finish sooner. |

### Output fields

| Field | Description |
| --- | --- |
| `pageId` | The Page's own numeric identifier. |
| `profileId` | The Page's profile identifier. This is a **different** number in a different namespace — both are given, never merged. |
| `vanity` | The handle Facebook actually resolved to. |
| `canonicalUrl` | The Facebook address the Page resolved to. |
| `name` | The Page name. |
| `category` | The category the Page publishes, e.g. "Government organization". |
| `intro` | The Page's intro / bio text. |
| `followers` | Follower count. Read `followersAreApproximate` before treating it as exact. |
| `followersAreApproximate` | `true` when Facebook published the figure rounded. |
| `followersText` | The figure exactly as Facebook shows it, e.g. `28M`. |
| `likes` | Exact like count, where Facebook publishes one. |
| `talkingAboutCount` | People talking about this Page, where published. |
| `profilePictureUrl` | Direct link to the profile image. |
| `coverPhotoUrl` | Direct link to the cover image. |
| `latestPost` | The newest public post: `postId`, `url`, `publishedAt`, `text`, `reactions`, `reactionsBreakdown`, `comments`, `shares`, `mediaType`, `mediaUrl`, `isSponsored`. |
| `website`, `email`, `phone` | Present only when the contact option is switched on, and only where the Page publishes them. |
| `identityMatchesRequest` | `false` when the handle you supplied resolved to a different one. `null` when you supplied an id, so there was nothing to compare. |
| `requestedInput` | The exact line you supplied, so results are easy to join back to your list. |
| `availability` | `OK` on every returned row. A Page that is not publicly viewable, and a Page that could not be read at all, are reported separately in the run log instead — never as a row, and never charged for. |
| `sourceUrl` | The Facebook address that was read. |
| `scrapedAt` | When the row was produced, in ISO 8601. |

### Pricing

You pay **$0.0015 for each Page returned** — that is **$1.50 per 1,000 Pages**,
whether or not you switch on the latest post and the contact details.

- 100 Pages → **$0.15**
- 1,000 Pages → **$1.50**
- 10,000 Pages → **$15.00**

Pages that turn out not to be publicly viewable, and Pages that could not be read
at all, produce no row and **cost you nothing**. You are only charged for a Page
you actually get data for.

### Limits & what this actor cannot do

- **Only the most recent public post.** Facebook shows visitors who are not
  logged in just the newest post on a Page, so a full post history cannot be
  collected. This actor returns one post per Page and never claims otherwise.
- **Some Pages are not publicly viewable at all.** They are set so their content
  is visible only to logged-in visitors, or the handle no longer exists. Those
  are reported as unavailable in the run log — never returned as an empty row,
  and never charged for. Expect a noticeable share of any large, unvetted list
  to land here.
- **Occasionally Facebook turns an attempt away instead of answering.** The
  actor tries again automatically, and if Facebook still will not answer for
  that Page, the run reports it as **unreadable** and counts it separately from
  the unavailable ones. That is deliberate: nothing was learned about the Page
  either way, so calling it "not publicly viewable" would state a fact that is
  not in evidence. Unreadable Pages are never charged for, and re-running just
  those inputs usually clears them.
- **Follower counts are published rounded for large Pages.** Facebook shows
  "28M" rather than an exact figure, so the row carries
  `followersAreApproximate` and the exact number is given only where Facebook
  publishes one.
- **No verification badge is reported.** Facebook's public signal for it is
  unreliable — it reads "not verified" for several household-name Pages that are
  verified in reality — so shipping it would be worse than leaving it out.
- **No Page creation date.** It is not published to visitors who are not logged
  in on any surface this actor reads.
- **Engagement is a snapshot.** Reaction, comment and share counts change from
  minute to minute; the numbers are correct as of `scrapedAt` and will drift
  afterwards.
- **Vanity URLs get reassigned.** A handle that once belonged to one brand can
  now resolve to a completely different profile, with a perfectly healthy-looking
  result. Every row reports the identity that actually came back, and
  `identityMatchesRequest` flags the difference so it is visible rather than
  silent.
- **There is no keyword search.** Facebook publishes no public directory of
  Pages, so you supply the Pages you want; this actor cannot find them by topic,
  category or city.
- **Speed depends on the size of the job and on Facebook's own response times.**
  No fixed throughput is promised.
- **Use the data lawfully.** Facebook's terms prohibit automated access, and
  much of this data is personal data. You are responsible for using what you
  collect in line with the source site's terms and with applicable privacy law.

### FAQ

**Do I need a Facebook account?**
No. Nothing about this actor involves an account.

**Does it need my login or personal details?**
No. It never asks for them and there is nowhere to enter them.

**Can I schedule it?**
Yes. Schedule it daily or weekly and each run appends a fresh dated row per
Page, which makes follower growth and posting activity easy to chart over time.

**Is the data complete?**
It is exactly what the Page publishes to the public, and no more. Pages that are
not publicly viewable produce no row. Follower counts are rounded for large
Pages. Only the newest post is available. Everything a Page does not publish
comes back blank rather than guessed at.

**Why are there two different id fields?**
Because Facebook genuinely has two. `pageId` and `profileId` are different
numbers in different namespaces and both legitimately identify the same Page.
Both are given so you can match against whichever one your other data uses.

**What happens when a handle points at the wrong brand now?**
You still get the row, but `identityMatchesRequest` is `false` and `vanity`,
`name` and `canonicalUrl` show you what actually came back, so you can drop or
review it.

**Can it find Pages for me by keyword or city?**
No. Facebook has no public Page directory to search, so the Pages have to come
from you — for example from a maps, directory or search scraper that already
returns Facebook links.

# Actor input Schema

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

The Pages to scrape, one per line. Paste a Page URL (https://www.facebook.com/nike/), a handle with or without the @ (@nike or nike), or a Page's numeric id. Anything that is not a Page — a group, a post, a marketplace listing, a personal profile link — is skipped with a note in the log.

## `includeLatestPost` (type: `boolean`):

Add the Page's most recent public post to each record, with its text, publish time, media and its reaction, comment and share counts. Facebook publishes only the newest post to visitors who are not logged in, so this is one post per Page and never a post history.

## `includeContactSurface` (type: `boolean`):

Also collect the website, email and phone number a Page publishes in its intro block. This makes the run a little slower because a second, lighter version of each Page is read. Leave it off if you only need profile and audience data.

## `country` (type: `string`):

The country to browse from. Facebook tailors some Pages by region, so pick the market you care about.

## `concurrency` (type: `integer`):

How many Pages to work on simultaneously. Four is the sweet spot: higher settings do not finish sooner and make individual Pages slower to come back.

## Actor input object example

```json
{
  "pageUrls": [
    "https://www.facebook.com/NASA/",
    "https://www.facebook.com/bbcnews/"
  ],
  "includeLatestPost": true,
  "includeContactSurface": false,
  "country": "us",
  "concurrency": 4
}
```

# 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 = {
    "pageUrls": [
        "https://www.facebook.com/NASA/",
        "https://www.facebook.com/bbcnews/"
    ],
    "includeLatestPost": true,
    "includeContactSurface": false,
    "country": "us",
    "concurrency": 4
};

// Run the Actor and wait for it to finish
const run = await client.actor("apt_marble/facebook-page-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/",
        "https://www.facebook.com/bbcnews/",
    ],
    "includeLatestPost": True,
    "includeContactSurface": False,
    "country": "us",
    "concurrency": 4,
}

# Run the Actor and wait for it to finish
run = client.actor("apt_marble/facebook-page-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/",
    "https://www.facebook.com/bbcnews/"
  ],
  "includeLatestPost": true,
  "includeContactSurface": false,
  "country": "us",
  "concurrency": 4
}' |
apify call apt_marble/facebook-page-scraper --silent --output-dataset

```

## MCP server setup

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