Facebook Comments Scraper: Sentiment & Toxicity Analysis avatar

Facebook Comments Scraper: Sentiment & Toxicity Analysis

Pricing

Pay per usage

Go to Apify Store
Facebook Comments Scraper: Sentiment & Toxicity Analysis

Facebook Comments Scraper: Sentiment & Toxicity Analysis

πŸ’¬ 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.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

SimpleAPI

SimpleAPI

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

14 days ago

Last modified

Share

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."

FieldExample valueUse case
full_url / facebookUrlhttps://www.facebook.com/humansofnewyork/posts/pfbid0Bb...Group all comments back to the source post you submitted
url_keypfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4YlShort join key for the parent post across a multi-URL run
commentUrlhttps://www.facebook.com/.../posts/...?comment_id=123Deep link straight to the individual comment
id / feedbackId / facebookIdinternal Facebook node IDsDe-duplication and re-fetch reference
profileNameJane DoeCommenter display name
profileId / profileUrlnumeric ID / profile link (when Facebook exposes it)Identify or link back to the commenter
profilePictureCDN image URLAvatar for a moderation or CRM UI
text"This made my whole day 😊"The comment body itself
date2026-01-14T18:32:07+00:00Sort or window by recency
likesCount214Engagement weighting
commentsCount6Number of replies Facebook reports under the comment
threadingDepth0 (top-level) or 1 (reply)Distinguish comments from replies in a flat export
replyarray of reply objectsNested thread attached to the comment
expansionTokeninternal 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
languageenRoute non-English comments to the right reviewer
moderationFlagclean or profanity|contains_linkPre-filter obviously actionable comments without AI
textLength143Spam/low-effort filtering by character count
emojiCount2Quick sentiment proxy without AI
sentimentpositive / negative / neutral / mixedBucket comments for a sentiment dashboard
emotionjoyFiner-grained tone than sentiment alone
toxicityScore0.0–1.0Rank comments for a moderation review queue
spamScore0.0–1.0Separate spam/bait from genuine feedback
intentpraise / complaint / question / spam / lead / statementRoute 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

ParameterRequiredTypeDescriptionExample value
postUrlsNoarrayFacebook post, photo, or reel permalinks to analyze["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"]
maxAnalyzedCommentsNointeger (default 10, min 1)Hard cap on top-level comments analyzed per URL25
repliesPerCommentNointeger (default 1, min 0)Nested replies fetched per threaded comment3
commentOrderNostring (default "all")most_relevant, newest, or all (original feed order)"newest"
commentsSinceNostringAbsolute date (2024-01-15) or relative window (2 weeks) β€” only comments/replies after this point are analyzed"1 week"
aiEnhancementNoboolean (default false)Turn on the AI sentiment/emotion/toxicity/spam/intent layertrue
aiModelNostring (default "claude-haiku-4-5")Model name; provider is auto-detected from the prefix"gpt-4o-mini"
aiApiKeyNostring (secret)Provider API key; falls back to the matching env var if left blank"sk-..."
proxyConfigurationNoobjectInformational only β€” the Actor always attaches its own residential proxy{ "useApifyProxy": false }
{
"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.

{
"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.

{ "postUrls": ["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"], "commentOrder": "newest", "commentsSince": "3 days", "maxAnalyzedComments": 100 }
{ "postUrls": ["https://www.facebook.com/humansofnewyork/posts/pfbid0BbKbkisExKGSKuhee9a7i86RwRuMKFC8NSkKStB7CsM3uXJuAAfZLrkcJMXxhH4Yl"], "commentOrder": "most_relevant", "maxAnalyzedComments": 30, "repliesPerComment": 10 }
{ "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 nameWhat it extracts
Facebook Page Posts & Comments ScraperPosts from a Page with their attached comment threads in one run
Facebook Groups Scraper: Sentiment & Lead AnalysisGroup posts/comments with the same style of sentiment and lead enrichment
Facebook Posts Scraper: Performance AnalyzerPost-level engagement metrics (likes, shares, comments) over time
Facebook Groups Posts Scraper: with Post AnalyticsGroup post content plus post-level analytics
Facebook Ads Library Scraper: Creative & Ad Text DetailsAd creatives and ad copy from the public Ads Library
Facebook User Search Scraper: Related Profiles & PagesProfile, 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

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.

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.