# Facebook Post Scraper (`apt_marble/facebook-post-details-scraper`) Actor

Turn any public Facebook post link into one clean row: author, date, post text, reaction total with the like/love/haha/wow/sad/angry/care breakdown, comment and share counts, video views and plays, and media links. Works on posts, photos, videos and reels. No account needed.

- **URL**: https://apify.com/apt\_marble/facebook-post-details-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 post 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/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 Post Scraper

Give it a link to any public Facebook post and get the post back as one clean
row: who published it, when, its wording, the reaction total **and the
per-emotion breakdown**, comment and share counts, video views and plays, the
outbound link and the pictures or video attached to it. It works on ordinary
posts, photo posts, videos, reels and permalinks, and it needs no Facebook
account of any kind. Reels and photo permalinks publish less than ordinary posts
do — where Facebook shows nothing, the field arrives empty rather than guessed.

### What you can do with it

- **Measure a campaign post by post.** Pull the exact reaction, comment and share
  figures for every post you or a client published, and see which emotions people
  actually reacted with.
- **Benchmark competitors.** Track the posts a rival brand publishes and compare
  engagement per post, per format and per publishing time.
- **Score creator and influencer content** before you pay for it, using the real
  engagement on specific posts rather than a follower count.
- **Feed a reporting dashboard** on a schedule and keep a dated history of how a
  post performed, since the figures on Facebook keep moving.
- **Study video performance properly** — views and plays are two different
  figures on Facebook and both are reported separately here.
- **Archive the wording and imagery** of posts you care about, together with the
  date the picture and video links stop working.

### What you get

One row per post. Abridged real example:

```
{
  "postId": "1591339195694784",
  "url": "https://www.facebook.com/NASA/videos/whats-up-august-2026/1596135602179420/",
  "postType": "video",
  "authorName": "NASA - National Aeronautics and Space Administration",
  "authorPageId": "100044561550831",
  "publishedAt": "2026-07-31T20:58:24.000Z",
  "text": "The sky is full of excitement this month! ...",
  "reactions": 2363,
  "reactionsText": "2.3K",
  "reactionsBreakdown": { "like": 1967, "love": 348, "haha": 2, "wow": 14, "sad": 1, "angry": 2, "care": 29 },
  "comments": 92,
  "shares": null,
  "views": 33155,
  "plays": 193813,
  "videoId": "1596135602179420",
  "durationMs": 163349,
  "mediaUrls": ["https://video.<...>.fbcdn.net/o1/v/t2/f2/m366/..."],
  "mediaUrlExpiresAt": "2026-08-06T05:41:19.000Z",
  "linkUrl": null,
  "availability": "OK",
  "scrapedAt": "2026-08-01T19:21:44.881Z"
}
```

### Input reference

| Field | Type | Default | What it does |
| --- | --- | --- | --- |
| **Post links** | list of text | one example post | The posts you want. Open a post, video, reel or photo on Facebook and copy the link from your browser. Post, video, reel, photo and permalink forms are all accepted. For the wording and the author's name, link to the **post**; a link to a picture on its own page carries the numbers but not those two — see the limits. Required. |
| **Include media links** | true / false | `true` | Include the picture and video links attached to each post. Turn it off for a lighter dataset. |
| **Browse from** | choice | United States | The country to browse from. Some posts are shown differently depending on where the visitor is. |
| **Posts at a time** | whole number 1–8 | `4` | How many posts to work on simultaneously. Four is the sweet spot; higher is not faster. |

Anything that is not a post link — a Page link, a home page link, a link from
another site — is skipped with a message saying why, and the run continues.

### Output fields

| Field | Description |
| --- | --- |
| `postId` | Facebook's own identifier for the post. |
| `url` | The link Facebook settled on for the post, after any redirect. |
| `sourceUrl` | The link you supplied. |
| `availability` | `OK`, or `UNAVAILABLE` when nothing real came back for that link. |
| `identityMatchesRequest` | Whether the post that came back is the one the link asked for. Empty when the link uses one of Facebook's opaque identifiers, which cannot be compared. |
| `postType` | `link`, `photo`, `video`, `reel` or `text`. |
| `authorName`, `authorPageId` | Who published the post. On reels and on a picture opened on its own page Facebook publishes only the identifier, so `authorName` is empty there. |
| `publishedAt` | Publication time, in ISO 8601. |
| `text` | The wording of the post, in full and untruncated. Empty — never borrowed from anything else on the page — when Facebook publishes no wording for that link. |
| `reactions` | Total reactions. Empty — never `0` — when Facebook publishes no figure. |
| `reactionsText` | The shortened figure as Facebook displays it, e.g. `2.3K`. |
| `reactionsBreakdown` | Per-emotion counts: `like`, `love`, `haha`, `wow`, `sad`, `angry`, `care`. An emotion Facebook does not publish for that post is empty rather than `0`. |
| `comments` | Number of comments Facebook shows on the post. |
| `shares` | Exact share count where Facebook publishes one. |
| `sharesText` | The share figure as displayed, which for some posts is only a shortened label such as `1.7K`. |
| `views`, `plays` | Video figures. These are two different measurements and are never merged. |
| `videoId`, `durationMs`, `isLive` | Video details, where the post is a video or reel. |
| `mediaUrls` | Links to the pictures and video attached to the post. |
| `mediaUrlExpiresAt` | The moment those links stop working. See the limits below. |
| `linkUrl`, `linkTitle`, `linkDomain` | The destination, headline and source of a shared link. |
| `scrapedAt` | When the row was collected. |

### Pricing

You pay per result. Each post that produces a row costs **$0.0015** — that is
**$1.50 per 1,000 posts**. Nothing else is charged: no monthly fee, no charge for
the time a run takes.

A link that turns out to be unavailable produces no row and costs nothing. So a
run over 1,000 links where 940 are live costs **$1.41**.

### Limits & what this actor cannot do

- **Picture and video links are temporary.** Facebook signs them with an expiry —
  roughly four days for video, roughly a month for pictures — and the expiry
  cannot be extended by anyone. Every row carries `mediaUrlExpiresAt` so you know
  exactly when its links die. Download what you need while the links are fresh; a
  "download it later" feature is not possible for this source.
- **Reels publish much less than other posts.** A reel has no per-emotion
  breakdown, no view figure, no play figure and no author name. Those fields come
  back empty rather than as invented zeros. A reel's own identifier is also not
  the number in its link, so both are reported.
- **A link to a picture on its own page is not a link to the post.** Opening a
  photo full-screen gives you a link of the `/photo/?fbid=…` form. Facebook
  publishes the reactions, the emotion breakdown, the comment and share counts
  and the picture itself on that page — but **not the wording the author typed
  and not the author's name**. Both come back empty, and neither is ever filled
  in with text taken from somewhere else on the page. If you want the wording and
  the name, use the link to the post itself.
- **View and play figures belong to the post you asked for, or to nobody.**
  Facebook shows related videos alongside a post, and those neighbours carry
  figures of their own. Nothing from them is ever reported as yours: a post with
  no view figure of its own is reported empty.
- **Share counts are not published everywhere.** They are present on link and
  photo posts, absent on some videos, and on reels only as a shortened label such
  as `1.7K`. A shortened label is reported as text and never converted into a
  number that Facebook never published.
- **The emotion breakdown is a top list, not a full split.** It covers the
  leading emotions only, so it adds up to less than the total. Do not treat the
  sum as the total.
- **Counts are a snapshot.** Reactions, comments, shares and plays move within
  minutes of each other. Every row is stamped with the moment it was collected.
- **Some posts are not publicly viewable at all.** Posts on Pages or in groups
  that require signing in, and links to posts that no longer exist, are reported
  as unavailable rather than returned empty — and are not charged for.
- **A link that looks fine can still be empty.** Facebook answers a made-up post
  identifier with a perfectly normal-looking page. Those are detected by their
  content and reported as unavailable.
- **There is no search.** You supply the post links; the actor cannot find posts
  by keyword, topic or Page.
- **Comment text is not included.** This actor reports the comment count. For the
  comments themselves, use the Facebook Comments Scraper.
- **Speed depends on the size of the job** and on how quickly Facebook answers on
  the day. No fixed rate is promised.
- **Use the data lawfully.** Facebook's terms prohibit automated collection, and
  post content and author details may be 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. Only public posts are collected, and no account is ever involved.

**Does it need my login or any personal details?**
No. There is nothing to connect and nothing to sign in to.

**Can I schedule it?**
Yes. Schedule it like any other actor — daily or hourly runs are a good way to
build a history of how a post's engagement grew, since the figures keep moving.

**Is the data complete?**
For a public post, yes for everything Facebook itself publishes: text, author,
time, reactions with the emotion breakdown, comments, shares and video figures.
There are two exceptions, both in the limits section: Facebook publishes far less
about reels, and a link to a picture on its own page carries the numbers but
neither the wording nor the author's name.

**A row came back with no text — is that a bug?**
No. It means Facebook published no wording for that link. The most common cause
is a `/photo/?fbid=…` link, where the wording lives on the post rather than on
the picture's own page; link to the post to get it. An empty field is always
"Facebook did not publish this", never a guess at what the text might have been.

**Why is a field empty instead of `0`?**
Because empty means "Facebook did not publish this", which is a different fact
from "the figure is zero". This actor never turns one into the other.

**Can I use the picture and video links later?**
Only until `mediaUrlExpiresAt`. After that Facebook refuses them, and nobody can
renew them. Collect the post again to get fresh links.

**What happens with a link to a post that was deleted?**
It is reported as unavailable, produces no row, and costs nothing.

# Actor input Schema

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

Links to the Facebook posts you want. Open a post, video, reel or photo and copy the link from your browser. Post, video, reel, photo and permalink forms are all accepted. For the wording of a post and the author's name, link to the post itself — a link to a picture on its own page carries the engagement figures and the picture, but Facebook publishes neither of those two on that page.

## `includeMedia` (type: `boolean`):

Include the picture and video links attached to each post. These links are temporary — every row carries the date and time its links stop working.

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

The country to browse from. Some posts are shown differently depending on where the visitor is.

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

How many posts to work on at the same time. Four is the sweet spot; higher is not faster and is more likely to be turned away.

## Actor input object example

```json
{
  "postUrls": [
    "https://www.facebook.com/bbcnews/posts/pfbid02Ahoi9DzYPrcsebiwdSZyKpUDUynzbGXv2yxDoT5UooyYpTLdG7rB29GaZSxxtBuXl",
    "https://www.facebook.com/NASA/posts/1591339195694784"
  ],
  "includeMedia": true,
  "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 = {
    "postUrls": [
        "https://www.facebook.com/bbcnews/posts/pfbid02Ahoi9DzYPrcsebiwdSZyKpUDUynzbGXv2yxDoT5UooyYpTLdG7rB29GaZSxxtBuXl",
        "https://www.facebook.com/NASA/posts/1591339195694784"
    ],
    "includeMedia": true,
    "country": "us",
    "concurrency": 4
};

// Run the Actor and wait for it to finish
const run = await client.actor("apt_marble/facebook-post-details-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 = {
    "postUrls": [
        "https://www.facebook.com/bbcnews/posts/pfbid02Ahoi9DzYPrcsebiwdSZyKpUDUynzbGXv2yxDoT5UooyYpTLdG7rB29GaZSxxtBuXl",
        "https://www.facebook.com/NASA/posts/1591339195694784",
    ],
    "includeMedia": True,
    "country": "us",
    "concurrency": 4,
}

# Run the Actor and wait for it to finish
run = client.actor("apt_marble/facebook-post-details-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "postUrls": [
    "https://www.facebook.com/bbcnews/posts/pfbid02Ahoi9DzYPrcsebiwdSZyKpUDUynzbGXv2yxDoT5UooyYpTLdG7rB29GaZSxxtBuXl",
    "https://www.facebook.com/NASA/posts/1591339195694784"
  ],
  "includeMedia": true,
  "country": "us",
  "concurrency": 4
}' |
apify call apt_marble/facebook-post-details-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=apt_marble/facebook-post-details-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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