Facebook Comments Scraper: Sentiment & Toxicity Analysis
Pricing
Pay per usage
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
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
14 days ago
Last modified
Categories
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-basedmoderationFlag,textLength, andemojiCountβ no key, no extra cost, no setup. - Optional AI layer β
sentiment,emotion,toxicityScore,spamScore, andintentβ using any of seven LLM providers (Anthropic, OpenAI, Google, xAI, DeepSeek, Perplexity, Mistral) selected throughaiModel. - Nested reply threads are fetched and attached under each top-level comment, up to
repliesPerCommentdeep. - Time-window and ordering controls β
commentsSincepluscommentOrder(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 } |
{"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 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
from apify_client import ApifyClientclient = 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.