# Facebook Comments Scraper (Reaction Breakdown & Engagement) (`scraply/facebook-comments-scraper`) Actor

💬 Facebook Comments Scraper (Reaction Breakdown & Engagement) extracts comments from public posts—text, author, time, reactions & replies. 📥 Export CSV/JSON. 📊 Perfect for social listening, sentiment analysis & community management. ⚡ Fast, reliable, scalable.

- **URL**: https://apify.com/scraply/facebook-comments-scraper.md
- **Developed by:** [Scraply](https://apify.com/scraply) (community)
- **Categories:** Automation, Lead generation, Social media
- **Stats:** 18 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Comments Scraper (Reaction Breakdown & Engagement Data)

Scrape comments and replies from public Facebook posts and videos, then get a
**per-comment reaction-type breakdown** (LIKE/LOVE/HAHA/WOW/SAD/ANGRY/CARE)
and locally-computed **engagement analytics** — engagement rate per comment,
a top-commenter leaderboard, and comment velocity since the post was
published. Built for social listening, engagement research, and Facebook
comment-data export/API workflows that need more than a raw like count.

### Features

- **Bulk URLs** — process multiple Facebook post/video permalinks in one run.
- **Comments + first-page replies** — top-level comments and their first page
  of nested replies, tagged `type`/`isChild`/`parentId` so parent and reply
  rows are both easy to filter and easy to reassemble.
- **Reaction-type breakdown** — raw reaction ids + counts per comment/reply,
  plus a best-effort id → name map. Unknown ids stay `name: null` rather than
  a guessed label.
- **Engagement analytics** — `engagementScore` / `engagementRatePercent` per
  row, a per-post summary (total comments/replies, best-effort post date,
  comment velocity per hour), and a run-level **top-commenter leaderboard**
  ranked by total engagement.
- **Absolute or relative date filter** — keep only comments newer than a
  fixed date or a relative window (`2 weeks`, `3 months`, …).
- **Honest truncation flag** — every row carries `commentsTruncated` so it's
  always clear when a thread had more comments/replies than were fetched.
- **Real-time output** — rows land in the Output tab as soon as each post is
  processed, no waiting for the whole run to finish.

### Use cases

- Social-listening dashboards that need reaction sentiment, not just a like count.
- Brand/campaign post monitoring — who is most engaged, and how fast a post
  is picking up comments.
- Research and moderation datasets needing per-comment reaction breakdowns.
- Feeding a downstream sentiment/AI pipeline with real comment text plus its
  engagement context.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `startUrls` | array (required) | — | Facebook post/video permalink URLs, one per line |
| `commentSettings.maxComments` | integer | 10 | Max top-level comments per post |
| `commentSettings.maxRepliesPerComment` | integer | 2 | Max replies kept per top-level comment |
| `commentSettings.commentsSortOrder` | enum | `all` | `most_relevant`, `newest`, or `all` (original order) |
| `onlyCommentsNewerThan` | datepicker (absolute or relative) | — | Keep only comments/replies newer than this date/window |
| `reactionEngagementSettings.includeReactionBreakdown` | boolean | `true` | Include the per-comment reaction-type breakdown |
| `reactionEngagementSettings.computeEngagementAnalytics` | boolean | `true` | Include engagement score/rate, post summary, and the leaderboard |
| `reactionEngagementSettings.topCommentersLimit` | integer | 10 | How many ranked rows the leaderboard keeps |
| `proxyConfiguration` | object | informational only | The Actor always routes through Apify residential proxy regardless of this field |

### Output

Each comment/reply is one dataset row (`type: "comment"` or `"reply"`):

- `facebookUrl`, `commentUrl`, `id`, `feedbackId`, `date`, `text`
- `profilePicture`, `profileId`, `profileName`, `profileUrl` (when available)
- `likesCount`, `commentsCount`, `reply` (nested replies, kept for backward compatibility), `threadingDepth`, `facebookId`, `inputUrl`
- `type` (`comment`/`reply`), `isChild`, `parentId`, `commentsTruncated`
- `reactions.raw` — `[{id, name, count}, ...]` (raw reaction ids always present; `name` is a best-effort LIKE/LOVE/HAHA/WOW/SAD/ANGRY/CARE map, `null` for unmapped ids)
- `reactions.byType` — `{LIKE: n, LOVE: n, ...}` summed from the mapped raw entries
- `reactions.totalFromBreakdown`, `reactions.reactorsCountReduced` — cross-check totals
- `engagementScore`, `engagementRatePercent` — this row's share of the post's total engagement

Once per post, a `type: "postEngagementSummary"` row is added with
`totalComments`, `totalReplies`, `totalEngagement`, `postDate` (best-effort,
`null` when it can't be reliably determined), `postDateCoverage`, and
`commentVelocityPerHour`.

At the end of the run, up to `topCommentersLimit` `type: "commenterLeaderboard"`
rows are added, ranked by `totalEngagement` across the whole run.

An `error` field (with `full_url`/`url_key`) is added instead when a post
could not be processed.

### How it works

The Actor loads each post's own permalink page (through Apify's residential
proxy) and parses comments — including their first page of replies — directly
out of that page's server-rendered data. This is the same single page fetch
needed to identify the post, so no extra network round-trip is spent per
comment or per reply page. Because this reads only the first page of replies
Facebook renders server-side, very long reply threads are naturally partial —
this is disclosed honestly via `commentsTruncated` rather than hidden.

### Reaction-type mapping

Facebook represents each reaction type as an opaque numeric id rather than a
readable name at the comment level. This Actor ships the **raw ids and
counts always**, plus a best-effort mapping to LIKE/LOVE/HAHA/WOW/SAD/ANGRY/CARE
built from publicly known, long-stable Facebook reaction ids. An id this
Actor doesn't recognize is reported with `name: null` — never a guessed name.

### Cautions

- Data from publicly available posts only.
- Comply with Facebook's Terms of Service and applicable privacy laws.
- Use responsibly.

# Actor input Schema

## `startUrls` (type: `array`):

One URL per line. Works with typical post, photo, and reel permalinks from facebook.com.

## `commentSettings` (type: `object`):

Max comments, reply depth, and sort order.

## `onlyCommentsNewerThan` (type: `string`):

Pick an absolute date (e.g. 2024-01-15) or a relative window (e.g. 1 day, 2 weeks, 3 months). Only comments/replies posted after this point are kept. Leave blank to disable.

## `reactionEngagementSettings` (type: `object`):

Controls for this variant's own added data: per-comment reaction-type breakdown and derived engagement analytics.

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

Informational only - the scraper always routes through Apify residential proxy at runtime regardless of what is selected here.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# 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 = {
    "startUrls": [
        "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"
    ],
    "onlyCommentsNewerThan": "",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraply/facebook-comments-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 = {
    "startUrls": ["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"],
    "onlyCommentsNewerThan": "",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("scraply/facebook-comments-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 '{
  "startUrls": [
    "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"
  ],
  "onlyCommentsNewerThan": "",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call scraply/facebook-comments-scraper --silent --output-dataset

```

## MCP server setup

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