# Facebook Comments Scraper: Sentiment & Toxicity Analysis (`simpleapi/facebook-comments-scraper`) Actor

💬 Facebook Comments Scraper scrapes comments & replies from public posts — author names, text, timestamps, reactions & permalinks. 🔍 Clean, dedupe, and export to CSV/JSON. 📊 Ideal for social listening, sentiment, marketing, and research. 🚀 Fast, reliable, API-ready.

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

## Pricing

from $2.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 — Sentiment, Toxicity and Moderation Data

This Actor scrapes public comments — including nested replies — from any Facebook post, photo, or reel URL and returns each one as a structured JSON row with the commenter's name, comment text, timestamp, like count, reply count, and detected language. A rule-based moderation flag and text metrics populate on every run, and an optional AI layer adds sentiment, emotion, toxicity, and spam scores using a provider you choose. Community moderators, social listening agencies, and sentiment researchers use it to turn a comment thread into a filterable, exportable dataset.

### What is Facebook Comments Scraper: Sentiment & Toxicity Analysis?

Facebook Comments Scraper: Sentiment & Toxicity Analysis reads the public comment thread under a Facebook post, photo, or reel and returns every top-level comment — with its nested replies — as a normalized JSON record. Each record is enriched with language, a moderation flag, and text metrics automatically, and can optionally add AI-generated sentiment, emotion, toxicity, spam, and intent scores. No Facebook login, developer account, or API key is required — the Actor runs logged-out, over a forced residential proxy, with a guest-cookie warmup.

- Discovery is by direct URL, not search or category: feed it one or more `postUrls` (post, photo, or reel permalinks) per run.
- Always-on deterministic layer — `language`, a rule-based `moderationFlag`, `textLength`, and `emojiCount` — no key, no extra cost, no setup.
- Optional AI layer — `sentiment`, `emotion`, `toxicityScore`, `spamScore`, and `intent` — using any of seven LLM providers (Anthropic, OpenAI, Google, xAI, DeepSeek, Perplexity, Mistral) selected through `aiModel`.
- Nested reply threads are fetched and attached under each top-level comment, up to `repliesPerComment` deep.
- Time-window and ordering controls — `commentsSince` plus `commentOrder` (most relevant, newest, or original feed order) — scope which comments get analyzed.
- Output lands in a standard Apify dataset, exportable as JSON, CSV, Excel, or pulled via the Apify API.

### What data can I extract with Facebook Comments Scraper: Sentiment & Toxicity Analysis?

Every row mixes raw Facebook comment data with two enrichment layers — a deterministic one that always runs, and an optional AI one — so a single record answers both "what was said" and "how it should be triaged."

| Field | Example value | Use case |
| --- | --- | --- |
| `full_url` / `facebookUrl` | `https://www.facebook.com/humansofnewyork/posts/pfbid0Bb...` | Group all comments back to the source post you submitted |
| `url_key` | `pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl` | Short join key for the parent post across a multi-URL run |
| `commentUrl` | `https://www.facebook.com/.../posts/...?comment_id=123` | Deep link straight to the individual comment |
| `id` / `feedbackId` / `facebookId` | internal Facebook node IDs | De-duplication and re-fetch reference |
| `profileName` | `Jane Doe` | Commenter display name |
| `profileId` / `profileUrl` | numeric ID / profile link (when Facebook exposes it) | Identify or link back to the commenter |
| `profilePicture` | CDN image URL | Avatar for a moderation or CRM UI |
| `text` | `"This made my whole day 😊"` | The comment body itself |
| `date` | `2026-01-14T18:32:07+00:00` | Sort or window by recency |
| `likesCount` | `214` | Engagement weighting |
| `commentsCount` | `6` | Number of replies Facebook reports under the comment |
| `threadingDepth` | `0` (top-level) or `1` (reply) | Distinguish comments from replies in a flat export |
| `reply` | array of reply objects | Nested thread attached to the comment |
| `expansionToken` | internal pagination token (present only when more replies exist) | Needed only if you re-page replies yourself |
| `pageAdLibrary` | `{ "is_business_page_active": true, "id": "..." }` (present only when Facebook attaches it) | Flags comments on posts tied to an active ad account |
| `language` | `en` | Route non-English comments to the right reviewer |
| `moderationFlag` | `clean` or `profanity\|contains_link` | Pre-filter obviously actionable comments without AI |
| `textLength` | `143` | Spam/low-effort filtering by character count |
| `emojiCount` | `2` | Quick sentiment proxy without AI |
| `sentiment` | `positive` / `negative` / `neutral` / `mixed` | Bucket comments for a sentiment dashboard |
| `emotion` | `joy` | Finer-grained tone than sentiment alone |
| `toxicityScore` | `0.0`–`1.0` | Rank comments for a moderation review queue |
| `spamScore` | `0.0`–`1.0` | Separate spam/bait from genuine feedback |
| `intent` | `praise` / `complaint` / `question` / `spam` / `lead` / `statement` | Route comments to sales, support, or moderation |

#### Sentiment, emotion, and toxicity scores

When `aiEnhancement` is on and a provider key resolves, each top-level comment is classified into `sentiment` (positive, negative, neutral, or mixed), a single-word `emotion` (joy, anger, sadness, fear, surprise, disgust, or neutral), a `toxicityScore` and `spamScore` (each 0–1), and a short `intent` label (question, complaint, praise, spam, lead, statement). These come from a real LLM call made with your own `aiModel` and `aiApiKey` — not a fixed lookup table — so a moderation team can, for example, sort a run's dataset by `toxicityScore` descending to build a review queue instead of reading every comment in arrival order. One limitation to know: nested replies are not sent through this layer, so `reply[]` items carry the raw fields only, with `sentiment`/`toxicityScore`/etc. absent.

#### Scope and volume controls

Because comments aren't a geographic directory, targeting here means scoping the analysis run itself: `maxAnalyzedComments` caps how many top-level comments per URL get processed, `repliesPerComment` controls how deep into each thread you follow, `commentOrder` chooses most-relevant, newest, or original feed order, and `commentsSince` restricts analysis to comments newer than an absolute date or a relative window like `2 weeks`. Together these decide runtime, AI cost, and which slice of a busy thread you actually see.

### Why not build this yourself?

Meta's Graph API can return comments through its `/{post-id}/comments` edge, but only for Pages and posts you (or a Page you administer) control with a valid Page access token — it was never designed to pull comments off an arbitrary public post, photo, or reel you don't own, and it has no sentiment or toxicity classification at all. Reproducing what this Actor does yourself means solving several separate problems: extracting the internal `doc_id` and `feedback_id` values Facebook embeds in a post's inline JavaScript bundles before you can even call its private GraphQL comments endpoint; walking cursor-based pagination for both top-level comments and nested reply threads; keeping a guest session alive with a warmed-up `datr` cookie so Facebook serves comments to a logged-out client at all; and routing every request through a residential proxy, since Facebook blocks datacenter IPs quickly on this surface. None of that touches the enrichment layer — language detection, the moderation heuristic, and the optional multi-provider LLM call for sentiment, toxicity, emotion, spam, and intent are a second build on top of the scraping problem.

This Actor ships both pipelines as one run: the scraping side (ID extraction, pagination, guest warmup, forced residential proxy) and the enrichment side (deterministic fields on every run, optional AI fields through your own provider key). Build your own Graph API client if you already administer the Page and only need its plain comment data with no enrichment. Use this Actor when the post isn't yours, when you need replies threaded and time-windowed, or when you want sentiment/toxicity scoring without writing a classifier yourself.

### How to use data extracted from Facebook?

#### Community and brand moderation

A moderator running weekly checks on a Page's post comments sets `postUrls` to that week's posts, turns on `aiEnhancement`, and raises `maxAnalyzedComments` to cover the full thread. The output dataset carries `moderationFlag` (always on, so it's usable even without an AI key) alongside `toxicityScore` and `spamScore` when AI is enabled. Filtering the dataset to `moderationFlag != "clean"` OR `toxicityScore > 0.6` produces a short, prioritized list of comments to review or hide, instead of scrolling the full thread by hand. `profileName` and `commentUrl` on each flagged row make it a one-click jump back to the live comment.

#### Social listening agencies

Agencies running the same check across several client Pages point one run at each client's recent post URLs, with `commentOrder` set to `newest` and `commentsSince` set to a rolling window like `1 week`. Because every row carries `full_url`/`url_key`, the resulting dataset can be grouped per client and per post without any extra joining logic, and `sentiment`/`emotion` give a quick per-client tone summary to drop into a recurring report.

#### Market and sentiment research

A researcher comparing audience reaction across competing brand posts collects comments from each brand's equivalent announcement, then aggregates `sentiment` and `toxicityScore` distributions per `full_url` to compare, for example, how positively two competitors' audiences reacted to a similar product launch. `language` lets the same aggregation be split by market before drawing conclusions.

#### AI agents and automated pipelines

Because `aiModel` already accepts Claude, GPT, Gemini, Grok, DeepSeek, Sonar, and Mistral model names, an agent pipeline can call this Actor as a comment-classification step and consume `sentiment`/`intent`/`toxicityScore` directly, without re-implementing prompt logic — useful for a triage agent that decides whether a comment needs a human reply.

### 🔼 Input sample

| Parameter | Required | Type | Description | Example value |
| --- | --- | --- | --- | --- |
| `postUrls` | No | array | Facebook post, photo, or reel permalinks to analyze | `["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"]` |
| `maxAnalyzedComments` | No | integer (default `10`, min `1`) | Hard cap on top-level comments analyzed per URL | `25` |
| `repliesPerComment` | No | integer (default `1`, min `0`) | Nested replies fetched per threaded comment | `3` |
| `commentOrder` | No | string (default `"all"`) | `most_relevant`, `newest`, or `all` (original feed order) | `"newest"` |
| `commentsSince` | No | string | Absolute date (`2024-01-15`) or relative window (`2 weeks`) — only comments/replies after this point are analyzed | `"1 week"` |
| `aiEnhancement` | No | boolean (default `false`) | Turn on the AI sentiment/emotion/toxicity/spam/intent layer | `true` |
| `aiModel` | No | string (default `"claude-haiku-4-5"`) | Model name; provider is auto-detected from the prefix | `"gpt-4o-mini"` |
| `aiApiKey` | No | string (secret) | Provider API key; falls back to the matching env var if left blank | `"sk-..."` |
| `proxyConfiguration` | No | object | Informational only — the Actor always attaches its own residential proxy | `{ "useApifyProxy": false }` |

```json
{
  "postUrls": [
    "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"
  ],
  "maxAnalyzedComments": 25,
  "repliesPerComment": 3,
  "commentOrder": "newest",
  "commentsSince": "1 week",
  "aiEnhancement": true,
  "aiModel": "claude-haiku-4-5",
  "aiApiKey": ""
}
```

**Common pitfall:** turning `aiEnhancement` on without setting `aiApiKey` (and without the matching provider env var set on your Apify account) does not fail the run — it silently leaves `sentiment`, `emotion`, `toxicityScore`, `spamScore`, and `intent` as `null` on every row, with only a warning in the log. Always check the log line `AI enrichment enabled — provider=... model=...` to confirm the key actually resolved. Separately, `proxyConfiguration` is accepted but ignored: Facebook is always scraped through Apify's residential proxy group regardless of what you set here.

### 🔽 Output sample

Each dataset row is one top-level comment, in the exact order chosen by `commentOrder`, as typed and normalized JSON. Export directly from the Apify dataset as JSON, CSV, or Excel, or read it over the Apify API.

```json
{
  "facebookUrl": "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl",
  "commentUrl": "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl?comment_id=1029384756",
  "id": "Y29tbWVudDoxMDI5Mzg0NzU2",
  "feedbackId": "ZmVlZGJhY2s6MTAyOTM4NDc1Ng==",
  "date": "2026-01-14T18:32:07+00:00",
  "text": "This made my whole day, thank you for sharing her story.",
  "profilePicture": "https://scontent.fxyz1-1.fna.fbcdn.net/v/t1.6435-1/example.jpg",
  "profileId": "100004827364591",
  "profileName": "Jane Doe",
  "profileUrl": "https://www.facebook.com/jane.doe",
  "likesCount": 214,
  "commentsCount": 1,
  "reply": [
    {
      "facebookUrl": "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl",
      "commentUrl": "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl?comment_id=1029384790",
      "id": "Y29tbWVudDoxMDI5Mzg0Nzkw",
      "feedbackId": "ZmVlZGJhY2s6MTAyOTM4NDc5MA==",
      "date": "2026-01-14T19:05:41+00:00",
      "text": "Agreed, this one hit hard.",
      "profilePicture": null,
      "profileId": "100009182736450",
      "profileName": "Sam Rivera",
      "likesCount": 12,
      "commentsCount": 0,
      "reply": [],
      "threadingDepth": 1,
      "facebookId": "1029384790",
      "inputUrl": "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"
    }
  ],
  "threadingDepth": 0,
  "facebookId": "1029384756",
  "inputUrl": "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl",
  "expansionToken": "AbW7z...",
  "url_key": "pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl",
  "language": "en",
  "moderationFlag": "clean",
  "textLength": 58,
  "emojiCount": 0,
  "sentiment": "positive",
  "emotion": "joy",
  "toxicityScore": 0.02,
  "spamScore": 0.01,
  "intent": "praise"
}
```

Note the nested `reply` object above: it carries only the raw Facebook fields (`text`, `profileName`, `likesCount`, etc.) — `language`, `moderationFlag`, and the AI fields are not attached to replies, only to the top-level comment.

If a post URL fails entirely (bad link, no `doc_id`/`feedback_id` found, or no pages returned), the Actor pushes a different, uncharged shape instead: `{"url_key": ..., "full_url": ..., "error": "...", "comments": []}`. This row has no `text`, `sentiment`, or other comment fields — filter it out of downstream analysis with an expression like `item.error == null` (or "text is not empty") before aggregating.

### How do you filter and target specific comments?

There's no keyword search here — every comment comes from a `postUrls` link you provide — so targeting means controlling *which* comments on that thread get analyzed and how deep the analysis goes. Four levers matter. **Recency vs. relevance**: `commentOrder` picks `newest` (chronological), `most_relevant` (Facebook's own relevance ranking, weighted toward likes and replies), or `all` (original feed order); combine with `commentsSince` for an absolute date or a relative window like `3 months` to restrict to a recent slice. **Volume**: `maxAnalyzedComments` is the hard cap on top-level comments per URL — it directly drives both scrape time and, when AI is on, classification cost. **Thread depth**: `repliesPerComment` controls how many nested replies per comment are fetched and formatted the same way, so a low value keeps runs fast while a higher one captures fuller discussions. **Enrichment scope**: there's no built-in toxicity/sentiment threshold input — scoring is applied to every analyzed comment, and you filter the resulting dataset by `toxicityScore`, `sentiment`, or `moderationFlag` afterward. Note that `commentsSince` filtering happens after the fetch, so a narrow window still requires a high enough `maxAnalyzedComments` to reach far enough back in the thread.

```json
{ "postUrls": ["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"], "commentOrder": "newest", "commentsSince": "3 days", "maxAnalyzedComments": 100 }
```

```json
{ "postUrls": ["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"], "commentOrder": "most_relevant", "maxAnalyzedComments": 30, "repliesPerComment": 10 }
```

```json
{ "postUrls": ["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"], "maxAnalyzedComments": 50, "aiEnhancement": true, "aiModel": "claude-haiku-4-5", "aiApiKey": "sk-ant-..." }
```

### ▶️ Want to try other Facebook scrapers?

| Scraper name | What it extracts |
| --- | --- |
| Facebook Page Posts & Comments Scraper | Posts from a Page with their attached comment threads in one run |
| Facebook Groups Scraper: Sentiment & Lead Analysis | Group posts/comments with the same style of sentiment and lead enrichment |
| Facebook Posts Scraper: Performance Analyzer | Post-level engagement metrics (likes, shares, comments) over time |
| Facebook Groups Posts Scraper: with Post Analytics | Group post content plus post-level analytics |
| Facebook Ads Library Scraper: Creative & Ad Text Details | Ad creatives and ad copy from the public Ads Library |
| Facebook User Search Scraper: Related Profiles & Pages | Profile, Page, and Group search results by name/keyword |

### How to extract Facebook data programmatically

This Actor runs like any Apify Actor: call it over the Apify API with your token, pass JSON input, and read the resulting dataset back as structured JSON — no custom protocol to learn.

#### Python example

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("SimpleAPI/facebook-comments-scraper-sentiment-toxicity-analysis").call(
    run_input={
        "postUrls": ["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"],
        "commentOrder": "newest",
        "maxAnalyzedComments": 50,
        "aiEnhancement": True,
        "aiModel": "claude-haiku-4-5",
        "aiApiKey": "sk-ant-...",
    }
)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item.get("profileName"), item.get("sentiment"), item.get("toxicityScore"))
```

#### Export to spreadsheets or CRM

Export the dataset as CSV directly from Apify, then map `profileName` → Contact Name, `text` → Notes/Comment Body, `date` → Interaction Date, and `sentiment`/`toxicityScore`/`intent` → lead-scoring or moderation-priority columns in your CRM or spreadsheet import.

### Is it legal to scrape Facebook comments?

Scraping publicly visible Facebook comments is generally permissible since this Actor only reads content already exposed to a logged-out visitor, without bypassing any login wall. That said, comment records here include personal data — `profileName`, `profileId`, `profileUrl`, and `profilePicture` identify a real, specific individual — so storing or processing them at scale falls under GDPR (if any commenter is in the EU/EEA) and CCPA (for California residents), which require a lawful basis for collection and give commenters rights over their own data. Facebook's own Terms of Service also restrict automated data collection, independent of privacy law. Consult legal counsel for commercial applications involving bulk storage of personal data.

### ❓ FAQ

#### Does a scraped comment go stale if it's later edited or deleted on Facebook?

Yes — this Actor takes a one-time snapshot at run time; it does not revisit a comment to detect later edits, deletions, or moderation by the Page/post owner. If you need current status, re-run the Actor on the same `postUrls` and compare.

#### Can I get sentiment and toxicity scoring along with the main comment data?

Yes. Set `aiEnhancement` to `true` and supply `aiApiKey` (or set the matching provider environment variable); every analyzed top-level comment then gets `sentiment`, `emotion`, `toxicityScore`, `spamScore`, and `intent` alongside the raw comment fields, in the same dataset row.

#### How accurate is the sentiment/toxicity scoring?

It depends on which layer you're looking at. `moderationFlag` is always-on and purely rule-based — a fixed word list plus caps-ratio and link-pattern checks — so it will miss toxic phrasing that doesn't use a listed word and can flag benign all-caps excitement. `sentiment`/`emotion`/`toxicityScore`/`spamScore`/`intent` come from a real LLM classification call using whichever `aiModel` you pick, not a keyword table, but this Actor doesn't benchmark or guarantee an accuracy figure for any provider — quality tracks the model you choose.

#### How many comments can I get per run?

`maxAnalyzedComments` sets the top-level comment cap per URL (default `10`, minimum `1`, no upper limit enforced by the input schema), and `repliesPerComment` separately caps replies per comment (default `1`, minimum `0`). Raise both for a fuller thread; runtime and, if AI is on, classification cost scale with them.

#### Do nested replies get the same sentiment/toxicity scoring as top-level comments?

No. Only top-level comments go through both the deterministic and AI enrichment layers. Replies attached under `reply[]` carry the raw Facebook fields (text, author, date, likes) but no `language`, `moderationFlag`, or AI fields.

#### How does the `commentsSince` time window work?

It accepts an absolute date (`2024-01-15`) or a relative window (`2 weeks`, `3 months`) and keeps only comments/replies posted after that point. Filtering happens after the fetch, so for a narrow recent window you may need to raise `maxAnalyzedComments` to make sure the run reaches far enough into the thread to find them.

#### Does this work with Claude, ChatGPT, and other AI agent frameworks?

Yes for the classification layer: `aiModel` accepts Claude, GPT, Gemini, Grok, DeepSeek, Sonar, and Mistral model names directly. For orchestration, the Actor is callable as a standard Apify API endpoint by any agent framework that can make an HTTP request.

#### How does this compare to other Facebook comment scrapers?

Most comment scrapers return raw fields only and leave sentiment/toxicity classification to a separate tool you build yourself. This Actor bundles a keyless deterministic layer (language, moderation flag, text metrics) with an optional multi-provider AI layer in the same run, so raw comments and their classification land in one dataset row.

#### Can I use this without a Facebook API key or developer account?

Yes. No Facebook login, developer account, or Graph API key is needed — the Actor scrapes public comments logged-out. You only need an Apify account to run it, plus your own third-party AI provider key if you turn `aiEnhancement` on.

#### Do I need to set up my own proxy?

No — `proxyConfiguration` is accepted for compatibility but is informational only. The Actor always routes Facebook requests through Apify's own residential proxy group regardless of what you configure there.

### Conclusion

Facebook Comments Scraper: Sentiment & Toxicity Analysis turns any public post, photo, or reel's comment thread into a structured, filterable dataset — raw comment fields plus an always-on moderation layer and an optional multi-provider AI sentiment/toxicity layer, all in one run. It's built for moderators, social listening agencies, and researchers who need comment data they can sort and threshold, not just read. No Facebook login or developer account is required to start. Open the Actor page on Apify and run it with your own post URLs to see your first dataset.

# Actor input Schema

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

📋 One Facebook post, photo, or reel permalink per line. Every comment fetched from these posts is analyzed for language, moderation flags, and (optionally) AI sentiment & toxicity.

💡 Run a small test first, then raise the comment cap.

## `maxAnalyzedComments` (type: `integer`):

🎯 Hard cap on top-level comments analyzed per URL. Lower = faster and cheaper analysis.

## `repliesPerComment` (type: `integer`):

🧵 Nested replies fetched per threaded comment (each reply keeps the base nested shape). Use a large number for effectively all.

## `commentOrder` (type: `string`):

🔀 Ordering of analyzed comments where supported.

## `commentsSince` (type: `string`):

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 analyzed. Leave blank to disable.

ℹ️ Filtering happens after fetch — raise the comment cap for narrow windows.

## `aiEnhancement` (type: `boolean`):

When ON (and an API key is provided below), each comment is classified for sentiment, emotion, toxicityScore, spamScore, and intent. When OFF (default) these fields are null — language, moderationFlag, textLength, and emojiCount still populate on every run.

## `aiModel` (type: `string`):

Provider auto-detected from the name: claude-*=Anthropic, gpt-*/o1/o3=OpenAI, gemini-*=Google, grok-*=xAI, deepseek-*=DeepSeek, sonar*=Perplexity, mistral-\*=Mistral. Cheaper mini/flash/haiku/lite models are recommended for classification.

## `aiApiKey` (type: `string`):

Secret key for the selected provider. Anthropic→ANTHROPIC\_API\_KEY, OpenAI→OPENAI\_API\_KEY, Google→GEMINI\_API\_KEY/GOOGLE\_API\_KEY, xAI→XAI\_API\_KEY, DeepSeek→DEEPSEEK\_API\_KEY, Perplexity→PERPLEXITY\_API\_KEY, Mistral→MISTRAL\_API\_KEY. Falls back to the matching env var if left blank. Only used when AI enrichment is ON.

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

ℹ️ Informational only — the analyzer always attaches Apify residential proxy at runtime regardless of what is selected here.

## Actor input object example

```json
{
  "postUrls": [
    "https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"
  ],
  "maxAnalyzedComments": 10,
  "repliesPerComment": 1,
  "commentOrder": "all",
  "aiEnhancement": false,
  "aiModel": "claude-haiku-4-5",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

All scraped items in the Actor's default dataset.

# 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/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

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

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

```

## MCP server setup

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