Facebook Comment Scraper - Public Page Comments, No Login avatar

Facebook Comment Scraper - Public Page Comments, No Login

Pricing

from $2.50 / 1,000 results

Go to Apify Store
Facebook Comment Scraper - Public Page Comments, No Login

Facebook Comment Scraper - Public Page Comments, No Login

Facebook comment scraper that extracts commenter names and comment text from any public Facebook profile or Page, no login needed. Scrape recent posts, export to JSON/CSV/Excel, or send results straight to Notion, Slack, or Airtable.

Pricing

from $2.50 / 1,000 results

Rating

0.0

(0)

Developer

Techforce Global

Techforce Global

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

1

Monthly active users

3 days ago

Last modified

Share

Facebook Comment Scraper - Comment Threads from Public Pages and Posts, Logged-Out and Without Commenter Identifiers

Actor Scope Output MCP

Read the comment threads under a public Facebook page's posts. Give it a page URL — get back each comment with the commenter's display name and the post it belongs to, ready for sentiment analysis, moderation triage or brand monitoring.

⚠️ This Actor returns personal data. Commenter names and comment text are personal data under GDPR / UK GDPR, and comments routinely contain special-category information (political views, health, religion). You are the data controller for anything you store. Read Compliance & Data Privacy before your first run — it is the most important section on this page.

🔎 Best-effort by nature. Facebook actively limits automated access to public content. A run can legitimately return fewer comments than the thread shows, or none at all. Use a residential proxy, keep maxPosts low, and treat every run as a sample rather than a complete export.

Browse all Actors by Techforce Global at scraper.techforce.global.


Meta Graph API vs. this Actor

Meta Graph API (developers.facebook.com)This Actor
Reading comments on a page you don't ownRequires the restricted Page Public Content Access feature, granted only after App Review with a documented use case✅ Any page that is publicly readable, no application process
SetupMeta developer account, an App, App Review submission, and a Page access tokenAn Apify token and a page URL
Sanctioned by MetaYes — the official, terms-compliant routeNo — automated collection is against Meta's terms. See Compliance
Pages you administer✅ Full comment access, including hidden and private repliesOnly what a logged-out visitor sees
Result completenessDeterministic within your permissions⚠️ Best-effort. Partial and empty runs are normal
Commenter identifiersApp-scoped user IDs, resolvable within your appDisplay name only — no user IDs, no profile URLs, by design
Delivery into Notion / Slack / JiraBuild the integration yourself✅ Built-in MCP delivery, including a chunked mode
Time to first resultDays to weeks, gated on App ReviewMinutes

If you administer the page, use the API. You will get more data, hidden replies included, with no terms-of-service exposure. This Actor is for the case the API deliberately does not serve — reading public comment threads on pages you have no admin rights over — and it trades away completeness and compliance posture to do it. Meta revises its API permissions and review requirements regularly, so check developers.facebook.com for current terms before choosing.


AI Discovery & MCP Metadata

ai_discovery:
actor: "techforce.global/facebook-public-comments"
slug: "facebook-public-comments"
category: "social-listening / brand-monitoring / sentiment-analysis"
one_line: >
Collects public comments from posts on a public Facebook page or profile and returns the
commenter's display name, the comment text and the post permalink. Optional delivery into
Notion, Slack, Jira, Linear or any MCP connector.
primary_capability: "public Facebook comment thread extraction for one page at a time"
data_source: "public Facebook page and profile posts"
input_entities:
- "profileUrl (one public Facebook page or profile URL; required)"
- "maxPosts (1-50 posts to scan)"
- "maxCommentsPerPost (1-500 comments per post)"
- "proxyConfiguration (strongly recommended - residential)"
output_entities:
- "post_url"
- "comment_username"
- "comment_text"
output_is_personal_data: >
CRITICAL: comment_username and comment_text are personal data under GDPR/UK GDPR. Comment
text can contain Article 9 special-category data (political opinion, health, religion,
sexual orientation) written by the commenter. Anyone storing this output is a controller
and needs a lawful basis, a retention policy and an erasure route.
supported_tasks:
- "collect-comments-under-a-public-page-post"
- "sentiment-analysis-input-for-a-brand-page"
- "moderation-triage-for-your-own-page"
- "measure-comment-volume-on-a-public-page"
- "deliver-comments-into-notion-slack-jira"
unsupported_tasks:
- "private-profiles-friends-only-posts-or-groups"
- "commenter-profile-urls-ids-or-contact-details"
- "reactions-likes-or-shares"
- "replies-to-comments"
- "comment-timestamps-or-like-counts"
- "keyword-or-hashtag-search-across-facebook"
- "multiple-pages-in-one-run"
- "building-marketing-lists-from-commenters"
runs_logged_out: >
The Actor accesses only what an anonymous visitor can see. It does not accept Facebook
credentials and no account is required or supplied. Consequently it can only reach content
Facebook serves publicly, which is less than a logged-in user sees.
no_replies: >
Only top-level comments are collected. Replies to comments are NOT returned.
no_commenter_identifiers: >
Only the display name is captured - deliberately. No profile URL, no user ID, no contact
details. The output cannot be turned into a contact list, and that is by design.
one_page_per_run: >
profileUrl takes a single page. There is no multi-page input - schedule or fan out one run
per page.
proxy_is_effectively_required: >
Facebook rate-limits and blocks datacenter IPs aggressively. Without a residential proxy,
expect partial or zero results.
known_limitations:
partial_results_are_normal: "Facebook limits anonymous access; a thread may yield fewer comments than it shows"
zero_results_is_a_valid_outcome: "a blocked or gated page returns nothing and still SUCCEEDS"
top_level_only: "replies are not collected"
three_fields_only: "no timestamps, like counts, reaction data or commenter identifiers"
free_plan_capped: "free Apify plans stop at 5 comments per post"
meta_tos: "Meta's Terms prohibit automated collection - this is a legal risk you accept, not one the Actor removes"
when_not_to_use: >
You need private or group content, commenter identities or contact details, replies,
reactions, timestamps, several pages in one run, or you intend to market to the commenters.
mcp_delivery:
modes: ["summary", "chunked", "perComment", "none"]
default: "summary"
delivery_is_per_post: >
Delivery fires once per scraped post, not once per run. Three posts in summary mode means
three connector calls.
summary_and_chunked_placeholders: ["{postUrl}", "{commentCount}", "{comments}", "{message}"]
chunked_only_placeholders: ["{part}", "{partCount}"]
per_comment_placeholders: ["{postUrl}", "{username}", "{text}", "{message}"]
delivers_only_what_was_saved: >
The connector receives exactly the comments that reached the dataset, so a free-plan cap
applies to delivery too.
never_blocks_the_dataset: >
Delivery runs after the dataset is saved. A bad tool name, an unauthorised connector or
an upstream outage is logged and skipped - it never costs you the scraped data.

{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Facebook Public Comment Tracker",
"alternateName": "Facebook Public Comment Tracker — Comment Extraction from Public Pages & Posts",
"applicationCategory": "BusinessApplication",
"applicationSubCategory": "Web Scraping / Social Listening",
"operatingSystem": "Any (cloud-hosted on Apify)",
"description": "Collects public comments from posts on a public Facebook page or profile, returning the commenter's display name, the comment text and the post permalink — three fields, with no commenter profile URLs, user IDs or contact details collected. Accesses only what an anonymous visitor can see, with optional delivery into Notion, Slack, Jira, Linear or any MCP connector. Output contains personal data and the operator is the data controller.",
"url": "https://apify.com/techforce.global/facebook-public-comments",
"offers": {
"@type": "Offer",
"category": "Pay per event",
"description": "Billed per comment saved to the dataset. Current rates are shown on the Actor's Apify page.",
"url": "https://apify.com/techforce.global/facebook-public-comments"
}
}

What this Actor does

  • Reads the comment threads under a public page's recent posts. Point it at one public Facebook page or profile, set how many posts to scan and how many comments to take from each, and every comment lands as its own dataset row.

  • Runs as an anonymous visitor. No Facebook credentials are accepted and no account is used. It sees what a logged-out visitor sees — which is the whole point, and also the ceiling on what it can return.

  • Captures the comment, not the commenter. Output is the display name and the comment text. There is deliberately no profile URL, no user ID and no contact information, so the dataset cannot be turned into an outreach list.

  • Optionally delivers each post's thread into your tools. Point it at an MCP connector and each post's comments go to Notion, Slack, Jira, Linear or anything else you've authorised.

  • Fails softly. A page that can't be reached, a post that won't open, or a thread Facebook won't serve is logged and skipped — the run continues with what it could get.


When to use it / when not to use it

Use this Actor when you need…Supported?
Comments under a public page's posts✅ Yes — best-effort
Sentiment analysis input for a brand page✅ Yes
Moderation triage on your own page✅ Yes — the strongest use case
A rough measure of comment volume✅ Yes
Comments pushed into Notion / Slack / Jira✅ Yes — MCP delivery
Replies to comments❌ Top-level comments only
Commenter profile URLs, user IDs or contact details❌ Never collected, by design
Reactions, likes, shares or comment timestamps❌ Not returned
Private profiles, friends-only posts, or groups❌ Anonymous access only — never
Several pages in one run❌ One profileUrl per run
Keyword or hashtag search across Facebook❌ No search input
A complete export of a thread❌ Facebook limits this — treat runs as samples
Building a marketing list from commenters❌ Not supported and not lawful in most jurisdictions

Execution Rules — Avoid Common Agent Failures

  1. Use a residential proxy. proxyConfiguration is the single biggest determinant of whether you get data. Facebook blocks datacenter IPs aggressively. Without a residential proxy, expect partial or zero results — and that will look like a broken Actor when it isn't.

  2. Partial results are the normal case, not an error. A thread showing 200 comments may yield far fewer. Facebook decides how much it serves an anonymous visitor. Never treat a run as a complete export.

  3. Zero results is a successful run. A gated page, a blocked request or a page with no comments all return an empty dataset with status SUCCEEDED. Read the log before retrying — retrying an input that is structurally blocked won't help.

  4. profileUrl must be a public page or profile. Private profiles, friends-only posts and groups are invisible to an anonymous visitor and will simply return nothing.

  5. One page per run. There is no multi-page input, and no keyword search. Schedule or fan out one run per page.

  6. Keep maxPosts low. Each post is a separate page load. maxPosts: 3 (the default) is a sensible starting point; pushing toward 50 raises both cost and block risk sharply.

  7. Only top-level comments are returned. Replies are not collected. If a thread's substance is in the replies, this Actor won't capture it.

  8. The output has three fields. No timestamps, no like counts, no reaction data, no commenter identifiers. Don't build a pipeline expecting more.

  9. Delivery fires once per post, not once per run. maxPosts: 3 in summary mode means three connector calls. Size your connector expectations accordingly.

  10. Free Apify plans stop at 5 comments per post. The run succeeds and says so. Delivery is capped to match, so the connector never receives more than the dataset kept.

  11. Treat every output row as personal data from the moment you receive it. See Compliance & Data Privacy. This is not boilerplate for this Actor.


Input Contract

ParameterTypeRequiredDefaultDescription
profileUrlstringyeshttps://www.facebook.com/zuckOne public Facebook page or profile URL.
maxPostsintegerno3Posts to scan from the page. 150. Each is a page load.
maxCommentsPerPostintegerno20Comments to take per post. 1500. A ceiling, not a quota.
proxyConfigurationobjectno{"useApifyProxy": false}Strongly recommended: Apify Proxy with RESIDENTIAL.

Delivery (optional)

ParameterTypeDefaultDescription
mcpConnectorstringMCP connector to deliver into. The Console offers a picker of connectors you've authorised. Empty = dataset only.
mcpToolstring""Tool to call on that connector — e.g. create_page, send_message, create_issue. Required when a connector is set.
deliveryModestring"summary"summary (one call per post), chunked (split long threads), perComment (one call per comment), none.
mcpArgumentsobject{}Arguments for the tool. {placeholder} tokens are substituted per call.
mcpMessageTemplatestring""Text rendered into {message}. Same placeholders.

Delivery placeholders

ModePlaceholders
summary{postUrl} {commentCount} {comments} {message}
chunkedthe same, plus {part} {partCount} — and {comments} holds one part
perComment{postUrl} {username} {text} {message}

{comments} renders as name: text lines. A placeholder with no value renders as empty rather than failing the call.

Delivery is per post. Every mode above fires once for each scraped post. In perComment mode, a run with 3 posts × 20 comments is up to 60 connector calls — check your connector's rate limits first.

{
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"]
}
}

Output Contract

One dataset item per comment.

FieldTypeNullableMeaning
post_urlstringnoPermalink of the post the comment was left on.
comment_usernamestringnoDisplay name on the comment, as Facebook renders it. Personal data.
comment_textstringnoComment body as posted. Personal data; may contain special-category information.

Three fields, always present. There is no commenter profile URL, user ID, timestamp, like count or reaction data — not omitted by accident, but deliberately not collected.

Example output object

{
"post_url": "https://www.facebook.com/<page>/posts/<post-id>",
"comment_username": "Jordan Blake",
"comment_text": "Been using this for two years and the support team is genuinely excellent."
}

Values above are illustrative. comment_username is shown as a plausible display name to make the shape clear — real runs return real people's names, which is exactly why the compliance section matters.

What a successful run looks like

  • Status: SUCCEEDED
  • Dataset: one item per comment, saved as each post's thread is read
  • Log: the page being opened, then a line per post as its comments are scraped, plus a warning for any post that couldn't be opened
  • Zero results is also a success. A gated page, a blocked request, or a page whose posts have no public comments all return an empty dataset. Check the log to see which it was.

Dataset views

ViewShows
CommentsCommenter, comment, and the post it belongs to
By PostThe same rows ordered post-first, for reading one thread at a time

Invocation & Integration

Apify Console

Open the Actor page, paste a public page URL, enable Apify Proxy with the RESIDENTIAL group, and click Start.

MCP — add as an agent tool

$claude mcp add apify --transport http https://mcp.apify.com/?actors=techforce.global/facebook-public-comments

Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("techforce.global/facebook-public-comments").call(run_input={
"profileUrl": "https://www.facebook.com/<your-page>",
"maxPosts": 3,
"maxCommentsPerPost": 50,
"proxyConfiguration": {
"useApifyProxy": True,
"apifyProxyGroups": ["RESIDENTIAL"],
},
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
print(f'{row["comment_username"]}: {row["comment_text"][:80]}')

JavaScript / TypeScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('techforce.global/facebook-public-comments').call({
profileUrl: 'https://www.facebook.com/<your-page>',
maxPosts: 3,
maxCommentsPerPost: 50,
proxyConfiguration: { useApifyProxy: true, apifyProxyGroups: ['RESIDENTIAL'] },
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`${items.length} comments across ${new Set(items.map(i => i.post_url)).size} posts`);

cURL — synchronous (waits, returns the dataset)

curl -X POST "https://api.apify.com/v2/acts/techforce.global~facebook-public-comments/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H 'Content-Type: application/json' \
-d '{
"profileUrl": "https://www.facebook.com/<your-page>",
"maxPosts": 3,
"maxCommentsPerPost": 50,
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}'

cURL — asynchronous with a spend cap

curl -X POST "https://api.apify.com/v2/acts/techforce.global~facebook-public-comments/runs?token=<YOUR_APIFY_TOKEN>&maxTotalChargeUsd=2" \
-H 'Content-Type: application/json' \
-d '{ "profileUrl": "https://www.facebook.com/<your-page>", "maxPosts": 10, "maxCommentsPerPost": 100 }'

maxTotalChargeUsd is the hard ceiling for the run. Use it on any unattended run.

With MCP delivery — new comments into Slack

{
"profileUrl": "https://www.facebook.com/<your-page>",
"maxPosts": 2,
"maxCommentsPerPost": 50,
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] },
"mcpConnector": "slack",
"mcpTool": "send_message",
"deliveryMode": "summary",
"mcpArguments": {
"channel": "#social-listening",
"text": "{commentCount} comments on {postUrl}:\n\n{comments}"
}
}

Remember this fires once per post — two posts means two Slack messages. Use chunked for long threads, and think twice before perComment.


Autonomous Agent Error Handling & Resolution Matrix

Each row is a condition observable from the run's status, log or dataset.

ConditionWhat you seeCauseDeterministic action
MISSING_PROFILE_URLLog: profileUrl is missing; empty datasetprofileUrl not suppliedModify Input: supply a public page URL. Do not retry unchanged.
INVALID_PROFILE_URLLog: profileUrl must be a valid URLValue doesn't start with httpModify Input: pass a full URL including scheme.
NO_POSTS_FOUNDLog: No posts found; empty datasetPage is gated, private, blocked, or has no visible postsEnable a residential proxy and retry once. If it persists, the page is not publicly readable — stop.
POST_UNREACHABLELog: could not open a specific post, run continuesThat post was blocked or removedExpected, partial. Other posts are unaffected.
FEWER_COMMENTS_THAN_VISIBLEDataset smaller than the thread showsFacebook limits what it serves anonymouslyExpected. maxCommentsPerPost is a ceiling, not a quota. Treat as a sample.
ZERO_RESULTSSUCCEEDED, empty datasetAny of the above, or genuinely no commentsEnable residential proxy, lower maxPosts, retry once. Then stop.
LIKELY_RATE_LIMITEDRepeated post-unreachable warnings across a runIP is being throttled or blockedSwitch to residential proxy, reduce maxPosts, and space runs out.
FREE_PLAN_CAPPEDLog: free plan cap reached per postFree Apify plan — 5 comments per postUpgrade the plan. Retrying will not change it.
CONNECTOR_TOOL_NOT_FOUNDLog: tool not available, followed by the available toolsmcpTool name is wrongModify Input: copy an exact name from that log line. Dataset unaffected.
CONNECTOR_NO_TOOLLog: connector selected but no tool name providedmcpConnector set, mcpTool emptyModify Input: set mcpTool, or clear mcpConnector.
CONNECTOR_RATE_LIMITEDConnector errors on later calls in a multi-post runDelivery fires per post (per comment in perComment)Modify Input: switch to summary or chunked, or lower maxPosts.
CONNECTOR_UNREACHABLELog: could not reach the connectorConnector not authorised, or running outside the Apify platformAuthorise it in Apify, or set deliveryMode: "none". Data already saved.

Verify any platform-level HTTP status behaviour against the Apify API reference before relying on it in automation — the rows above describe this Actor's observable behaviour, not Apify's transport layer.


Natural Language → Actor Mapping

A user says…IntentInput
"What are people saying under our latest posts?"Own-page monitoring{"profileUrl":"https://www.facebook.com/<your-page>","maxPosts":3}
"Pull comments from this page's last 10 posts"Volume{"profileUrl":"<page-url>","maxPosts":10,"maxCommentsPerPost":100}
"I need comment text for sentiment analysis"Analysis input{"profileUrl":"<page-url>","maxPosts":5,"maxCommentsPerPost":200}
"Check the comments on our newest post only"Single post{"profileUrl":"<page-url>","maxPosts":1,"maxCommentsPerPost":500}
"Anything abusive in our comments?"Moderation triage{"profileUrl":"<your-page>","maxPosts":5,"maxCommentsPerPost":200}
"It returned nothing — try harder"BlockedAdd {"proxyConfiguration":{"useApifyProxy":true,"apifyProxyGroups":["RESIDENTIAL"]}}
"Just a quick sample"Cheap probe{"profileUrl":"<page-url>","maxPosts":1,"maxCommentsPerPost":10}
"Post our page's comments to Slack daily"Scrape + deliverAbove, plus mcpConnector, mcpTool, mcpArguments, on a schedule
"File negative comments as Jira issues"Scrape + deliver{"profileUrl":"<your-page>","mcpConnector":"jira","mcpTool":"create_issue","deliveryMode":"perComment"}
"Track comment volume on our page weekly"Scheduled monitorSame input on a schedule

Should NOT route here: private profiles, friends-only posts or groups · commenter profile URLs, user IDs, emails or phone numbers · replies to comments · reactions, likes, shares or timestamps · keyword or hashtag search across Facebook · several pages in one run · a complete export of a thread · building a marketing or outreach list from commenters · scraping an individual private person's activity.


Agent Execution & Routing Logic

Does the user want COMMENTS from a PUBLIC Facebook page?
├── NO → not this Actor.
│ private profile / group / friends-only → not reachable, ever
│ commenter contact details → not collected, by design
│ reactions / likes / timestamps → not returned
│ search by keyword or hashtag → no search input
│ another platform → use that platform's Actor
└── YES
├── Is the page PUBLIC?
│ ├── unsure → try once; "No posts found" means it is not publicly readable
│ └── no → stop. Nothing here will reach it.
├── ALWAYS set proxyConfiguration → Apify Proxy, RESIDENTIAL
(without this, expect partial or zero results)
├── How many posts?
│ ├── newest only → maxPosts: 1
│ ├── recent → maxPosts: 3-5 (default 3)
│ └── deeper → up to 50, but cost and block risk rise sharply
├── How many comments per post?
│ ├── a sample → 10-50
│ └── the thread → up to 500 (a CEILING; Facebook may serve fewer)
├── Is this THEIR OWN page?
│ ├── yes → strongest footing: moderation and analytics on their own content
│ └── no → confirm they have a lawful basis before storing anything
└── Should results land in another app?
├── yes → mcpConnector + mcpTool + deliveryMode
│ NOTE: fires once PER POST, not per run
│ one digest per post → summary
│ long thread → chunked
│ one call per comment→ perComment (watch rate limits)
└── no → leave mcpConnector empty; dataset only

Cost Control & Pricing Transparency

This Actor bills per comment saved (pay-per-event). You pay for rows that reach your dataset, so a blocked run that returns nothing costs nothing in event charges. Current per-comment rates are on the Actor's Apify page; the Console shows the live total while a run is in progress.

ChoiceEffect on cost
maxPostsEach post is a separate page load — the main driver of run time.
maxCommentsPerPostThe main driver of event charges. It is a ceiling; you're only charged for comments actually found.
Residential proxyAdds proxy cost, but without it you may pay for a run that returns nothing useful. Worth it.
Being blockedCosts run time but few or no event charges — the failure mode is cheap, which is small consolation.

Keeping runs predictable:

  1. First run: maxPosts: 1, maxCommentsPerPost: 10, residential proxy on. Confirm the page is readable at all before scaling anything.
  2. Then scale maxCommentsPerPost before maxPosts. More comments from fewer posts is cheaper and less block-prone than the reverse.
  3. Always set a spend cap on unattended and scheduled runsmaxTotalChargeUsd on the API call, or the run limit in the Console.
  4. Free Apify plans stop at 5 comments per post, which makes free runs a connectivity test rather than a data pull.

Troubleshooting

#Symptom you seeMost likely causeFix
1Run ends immediately, empty dataset, log says profileUrl is missingprofileUrl was not supplied. It is the one required fieldPass a public page URL. Do not retry unchanged.
2Log says profileUrl must be a valid URLThe value does not start with httpInclude the scheme: https://www.facebook.com/<page>.
3You forgot to set profileUrl and got comments about Mark ZuckerbergThe schema default and prefill are https://www.facebook.com/zuckAlways pass profileUrl explicitly from API, SDK and MCP calls.
4No posts found, empty datasetThe page is gated, private, blocked from this IP, or has no visible postsEnable a residential proxy and retry once. If it persists, the page is not publicly readable — stop.
5Far fewer comments than the thread visibly showsFacebook serves a fraction of a thread to anonymous visitors, and the Actor clicks "View more comments" a limited number of timesExpected. maxCommentsPerPost is a ceiling, not a quota. Treat every run as a sample.
6One post is missing from an otherwise good runThat post was blocked or removed; the log names it and the run continuesExpected and partial. The other posts are unaffected.
7Repeated post-unreachable warnings across the runThe IP is being throttled or blockedSwitch to a residential proxy, lower maxPosts, and space runs further apart.
8Exactly 5 comments per post, every timeFree Apify plan capUpgrade the plan. Retrying will not change it — the log prints the cap notice.
9A row's comment_text looks like the post body rather than a commentExtraction reads comment blocks from the rendered page, and Facebook marks some non-comment blocks the same wayFilter obvious outliers on ingest. Comparing comment_username against the page's own name catches most of them.
10The same comment appears twiceComments are not de-duplicated across posts, and a shared or cross-posted item can appear under two permalinksDe-duplicate on comment_username + comment_text + post_url in your consumer.
11No commenter profile link or user ID in the outputBy design. The Actor collects three fields only and deliberately does not collect profile URLs, user IDs or contact detailsNot a defect — it is a data-minimisation choice. See Compliance.
12Run takes much longer than expectedmaxPosts drives run time: each post is a separate page load with a fixed settle wait, and the profile scroll runs up to 15 passesLower maxPosts. Prefer more comments from fewer posts.
13Connector configured but nothing deliveredmcpTool is empty — the log says a connector is selected but no tool name was providedSet mcpTool, or clear mcpConnector. The dataset is saved either way.
14Connector starts erroring partway through a multi-post runDelivery fires once per post (once per comment in perComment), so a multi-post run makes many callsSwitch to summary or chunked, or lower maxPosts.
15Delivered comments are fewer than the connector expectedOnly comments that actually reached the dataset are delivered, so a free-plan cap applies to delivery tooExpected, and deliberate — the connector never receives rows the dataset was not allowed to keep.

Diagnostic checklist before opening an issue

  1. Check the page in a logged-out browser first. Open it in a private window. If you cannot see the posts and comments there, the Actor cannot either — that is the ceiling on what anonymous access reaches.
  2. Confirm the run's status. SUCCEEDED with zero items is a valid outcome here, not a crash.
  3. Probe small: {"profileUrl":"<url>","maxPosts":1,"maxCommentsPerPost":10} with a residential proxy on. If that returns comments, the pipeline works and the issue is scale or blocking.
  4. Try a residential proxy before concluding a page is unreadable. The proxy defaults to off, and datacenter IPs are the most common cause of an empty run.
  5. Read the log for which failure it was. "No posts found", "could not open

If it survives all five, open an Issues ticket with the run ID, the exact input JSON, and what you expected.


FAQ

Setup & access

Do I need a Facebook account, app, or API key?

No. You need an Apify account and API token only. The Actor accepts no Facebook credentials and uses no account — it reads what a logged-out visitor sees. If any Actor asks you to hand over your Facebook login, treat that as a red flag, including this one.

Is this the official Meta Graph API?

No. This is an independent Actor, not affiliated with, endorsed by, or sponsored by Meta. The sanctioned route is the Graph API, which is the better option if you administer the page.

Do I need a proxy?

The proxy input defaults to off, but a residential proxy is strongly recommended. Datacenter IPs are the single most common reason a run comes back empty.

Can I plug it into Claude, Cursor, or a LangChain agent?

Yes — it is a native MCP tool:

claude mcp add --transport http apify "https://mcp.apify.com?tools=techforce.global/facebook-public-comments"

Scope & input

Can I scrape a private profile, a group, or a friends-only post?

No. Public pages and public profiles only, and only the posts and comments Facebook shows to an anonymous visitor.

Can I give it a single post URL instead of a page?

Not directly. The input is a page or profile URL, and the Actor discovers recent posts from it. To narrow the scope to effectively one post, set maxPosts: 1.

Can I search comments by keyword?

No. There is no search input. Scrape the page and filter comment_text yourself.

How many posts and comments can one run cover?

maxPosts accepts 1–50 (default 3) and maxCommentsPerPost accepts 1–500 (default 20). Both are ceilings — Facebook decides how much it actually serves.

Do I get replies to comments?

Only where Facebook renders them in the same thread view as the comments themselves. There is no separate reply field and no guaranteed nesting — the output is a flat list.

Are comments returned in chronological order?

No. Order follows however Facebook renders the thread, which is usually relevance-ranked rather than chronological, and there is no timestamp field to re-sort by.

Output & data

What exactly do I get per comment?

Three fields: comment_username, comment_text and post_url. That is the whole output, and it is a deliberate data-minimisation choice.

Why is there no commenter profile URL, user ID, or timestamp?

Because collecting them would materially increase the privacy exposure for people who are not the subject of your research. A display name plus text is enough for sentiment, volume and moderation triage; a resolvable identifier turns the dataset into a profile-building tool.

Can I match comments to specific individuals?

Not reliably, and by design. Display names are not unique and there is no identifier attached. If your use case requires identifying individuals, this Actor is the wrong tool and you should re-examine the lawful basis for it.

Is the output ready for sentiment analysis?

Yes — comment_text is the comment body as posted. Feed it straight into a model, and consider dropping comment_username on ingest, which removes most of the compliance obligations at no analytical cost.

Cost & runtime

How is this billed?

Pay-per-event: one event per comment saved to the dataset. You are charged for rows you actually receive, so a blocked run that returns nothing costs nothing in event charges. Current rates are on the Actor's Apify page.

Does a blocked or empty run still cost money?

No event charges, since nothing was saved. It still consumes platform run time, which is why the cheap probe run is worth doing first.

What does the free plan give me?

5 comments per post, and no event charges. That makes a free run a connectivity test rather than a data pull — enough to confirm a page is readable before you upgrade.

How do I guarantee an agent never overspends?

Pass maxTotalChargeUsd as a query parameter on the run endpoint — a hard per-execution ceiling. Always set one on unattended and scheduled runs.

What makes a run slow?

maxPosts, mostly. Each post is a separate page load with a fixed settle wait, and the initial profile scroll runs up to 15 passes before it gives up. More comments from fewer posts is both faster and less block-prone.


Companion machine-readable files

FileWhat it defines
.actor/input_schema.jsonEvery input, its type, default and bounds
.actor/dataset_schema.jsonThe three output fields and the two Console views
.actor/output_schema.jsonWhere the run's output is exposed
.actor/actor.jsonActor identity, memory bounds and storage wiring

If this page and the schema files disagree, the schema files win. They are what the platform validates against at run time; this page is documentation and can lag a release.


ActorBest for
This ActorComment threads under a public Facebook page's posts
Facebook Company Page ScraperA page's own business details — no personal data
Website Contact ScraperBusiness contact details from a company's own site
Smart Event ScraperEvent listings across six platforms — no personal data
EventsEye ScraperTrade shows with organizer business contacts

If your goal is business information rather than what individuals said, prefer the Facebook Company Page Scraper — it returns no personal data and carries none of the obligations above.

Browse the full catalogue at scraper.techforce.global.


Compliance & Data Privacy

Read this section before your first run. For most Actors this is a formality. For this one it is the operating manual.

  • The output is personal data. There is no reading of the law under which it isn't. comment_username is an identifiable person's name and comment_text is content they authored. Under GDPR / UK GDPR you become a data controller the moment you store it, with the full obligation set: a lawful basis, a retention period, a response route for access and erasure requests, and — for any substantial or systematic collection — a Legitimate Interests Assessment or a DPIA. The CCPA/CPRA, Brazil's LGPD and India's DPDP Act 2023 impose parallel duties.

  • Comments contain special-category data, and you cannot filter it in advance. People volunteer political opinions, health conditions, religious belief and sexual orientation in comment threads. That is Article 9 data, which normally requires explicit consent you do not have. You cannot know which rows contain it until after you've collected them — so the safe posture is a short retention period and tight access control on the whole dataset.

  • "Publicly accessible" is not a lawful basis. This is the single most common mistake. A comment being visible to anyone does not make processing it lawful, and EU regulators have repeatedly rejected that argument. You still need a basis, and it must survive a balancing test against the commenter's reasonable expectations — someone replying to a brand post does not expect to enter a third-party database.

  • Meta's Terms of Service prohibit automated collection. Facebook's terms and its robots.txt disallow scraping without written permission, and Meta enforces this — including civil action. This Actor does not remove that risk; it is a risk you accept by running it. No configuration makes the collection ToS-compliant.

  • Your own page is much stronger ground than someone else's. Monitoring and moderating comments on a page you control has an obvious legitimate interest, sits within what commenters expect, and puts you on the right side of most of the above. Third-party pages, competitor monitoring, and anything resembling surveillance of individuals do not.

  • Never use this to build a contact or marketing list. The Actor deliberately omits profile URLs, user IDs and contact details so it can't be used that way. Re-identifying commenters from their display names and then contacting them would breach CAN-SPAM, CASL, ePrivacy/PECR and the DPDP Act — and the GDPR purpose-limitation principle on top.

  • Do not scrape individual private people. The Actor is built for pages. Pointing it at a private individual's profile to compile their activity is targeted surveillance, is unlawful in most jurisdictions, and is not a use this Actor supports.

  • Minimise, and set a retention clock. Keep maxPosts and maxCommentsPerPost at what your actual question requires. Aggregate to sentiment scores or counts and discard the raw names and text as soon as you can — an aggregate is usually what you needed, and it takes you out of scope.

  • No credentials, no account, no private content. The Actor accepts no Facebook login and accesses only what an anonymous visitor sees. If you are ever asked to supply Facebook credentials to an Actor, that is a red flag — including for this one.


🆘 Support & Custom Pipeline Engineering

Need automated multi-city scheduled feeds, webhook enrichment, or enterprise data warehouse syncs?



🏷️ Structured data for search & AI discovery

SoftwareApplication describes the Actor; FAQPage wraps the FAQ above so those answers are eligible for rich results, matching it question-for-question.

{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
"name": "Facebook Public Comment Tracker",
"alternateName": "Facebook Public Comment Tracker — Comment Extraction from Public Pages & Posts",
"applicationCategory": "BusinessApplication",
"applicationSubCategory": "Web Scraping / Social Listening",
"operatingSystem": "Any (cloud-hosted on Apify)",
"url": "https://apify.com/techforce.global/facebook-public-comments",
"description": "Collects public comments from posts on a public Facebook page or profile, returning the commenter's display name, the comment text and the post permalink — three fields, with no commenter profile URLs, user IDs or contact details collected. Accesses only what an anonymous visitor can see, with optional delivery into Notion, Slack, Jira, Linear or any MCP connector. Output contains personal data and the operator is the data controller.",
"author": {
"@type": "Organization",
"name": "Techforce Global",
"url": "https://www.techforceglobal.com"
},
"provider": {
"@type": "Organization",
"name": "Apify",
"url": "https://apify.com"
},
"offers": {
"@type": "Offer",
"category": "Pay per event",
"description": "Billed per comment saved to the dataset. Current rates are shown on the Actor's Apify page.",
"url": "https://apify.com/techforce.global/facebook-public-comments"
},
"featureList": [
"Comment threads from a public page's recent posts",
"Commenter display name, comment text and post permalink",
"No credentials accepted and no account used - anonymous access only",
"No commenter profile URLs, user IDs or contact details collected, by design",
"Configurable post and per-post comment ceilings",
"Residential proxy support",
"Hidden comments expanded by clicking through the thread's View more control",
"Charged per comment saved, so a blocked run costs nothing in event charges",
"Free plan returns 5 comments per post as a connectivity check",
"Delivery is capped to what the dataset kept, so a connector never receives withheld rows",
"Optional MCP delivery to Notion, Slack, Jira, Linear and more",
"Chunked delivery mode keeps long threads under connector size and timeout caps",
"Two Console dataset views"
],
"isAccessibleForFree": false,
"softwareRequirements": "Apify account and API token",
"softwareHelp": {
"@type": "CreativeWork",
"url": "https://apify.com/techforce.global/facebook-public-comments"
},
"keywords": "Facebook comment scraper, social listening, brand monitoring, sentiment analysis input, public page comments, comment extraction, moderation triage, MCP connector"
}
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Do I need a Facebook account, app, or API key?",
"acceptedAnswer": {
"@type": "Answer",
"text": "No. You need an Apify account and API token only. The Actor accepts no Facebook credentials and uses no account - it reads what a logged-out visitor sees. If any Actor asks you to hand over your Facebook login, treat that as a red flag, including this one."
}
},
{
"@type": "Question",
"name": "Is this the official Meta Graph API?",
"acceptedAnswer": {
"@type": "Answer",
"text": "No. This is an independent Actor, not affiliated with, endorsed by, or sponsored by Meta. The sanctioned route is the Graph API at developers.facebook.com, which is the better option if you administer the page."
}
},
{
"@type": "Question",
"name": "Do I need a proxy?",
"acceptedAnswer": {
"@type": "Answer",
"text": "The proxy input defaults to off, but a residential proxy is strongly recommended. Datacenter IPs are the single most common reason a run comes back empty."
}
},
{
"@type": "Question",
"name": "Can I plug it into Claude, Cursor, or a LangChain agent?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes - it is a native MCP tool. Add it with: claude mcp add --transport http apify \"https://mcp.apify.com?tools=techforce.global/facebook-public-comments\""
}
},
{
"@type": "Question",
"name": "Can I scrape a private profile, a group, or a friends-only post?",
"acceptedAnswer": {
"@type": "Answer",
"text": "No. Public pages and public profiles only, and only the posts and comments Facebook shows to an anonymous visitor."
}
},
{
"@type": "Question",
"name": "Can I give it a single post URL instead of a page?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Not directly. The input is a page or profile URL, and the Actor discovers recent posts from it. To narrow the scope to effectively one post, set maxPosts to 1."
}
},
{
"@type": "Question",
"name": "Can I search comments by keyword?",
"acceptedAnswer": {
"@type": "Answer",
"text": "No. There is no search input. Scrape the page and filter comment_text yourself."
}
},
{
"@type": "Question",
"name": "How many posts and comments can one run cover?",
"acceptedAnswer": {
"@type": "Answer",
"text": "maxPosts accepts 1-50 (default 3) and maxCommentsPerPost accepts 1-500 (default 20). Both are ceilings - Facebook decides how much it actually serves."
}
},
{
"@type": "Question",
"name": "Do I get replies to comments?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Only where Facebook renders them in the same thread view as the comments themselves. There is no separate reply field and no guaranteed nesting - the output is a flat list."
}
},
{
"@type": "Question",
"name": "Are comments returned in chronological order?",
"acceptedAnswer": {
"@type": "Answer",
"text": "No. Order follows however Facebook renders the thread, which is usually relevance-ranked rather than chronological, and there is no timestamp field to re-sort by."
}
},
{
"@type": "Question",
"name": "What exactly do I get per comment?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Three fields: comment_username, comment_text and post_url. That is the whole output, and it is a deliberate data-minimisation choice."
}
},
{
"@type": "Question",
"name": "Why is there no commenter profile URL, user ID, or timestamp?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Because collecting them would materially increase the privacy exposure for people who are not the subject of your research. A display name plus text is enough for sentiment, volume and moderation triage; a resolvable identifier turns the dataset into a profile-building tool."
}
},
{
"@type": "Question",
"name": "Can I match comments to specific individuals?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Not reliably, and by design. Display names are not unique and there is no identifier attached. If your use case requires identifying individuals, this Actor is the wrong tool and you should re-examine the lawful basis for it."
}
},
{
"@type": "Question",
"name": "Is the output ready for sentiment analysis?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes - comment_text is the comment body as posted. Feed it straight into a model, and consider dropping comment_username on ingest, which removes most of the compliance obligations at no analytical cost."
}
},
{
"@type": "Question",
"name": "How is this billed?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Pay-per-event: one event per comment saved to the dataset. You are charged for rows you actually receive, so a blocked run that returns nothing costs nothing in event charges. Current rates are on the Actor's Apify page."
}
},
{
"@type": "Question",
"name": "Does a blocked or empty run still cost money?",
"acceptedAnswer": {
"@type": "Answer",
"text": "No event charges, since nothing was saved. It still consumes platform run time, which is why the cheap probe run is worth doing first."
}
},
{
"@type": "Question",
"name": "What does the free plan give me?",
"acceptedAnswer": {
"@type": "Answer",
"text": "5 comments per post, and no event charges. That makes a free run a connectivity test rather than a data pull - enough to confirm a page is readable before you upgrade."
}
},
{
"@type": "Question",
"name": "How do I guarantee an agent never overspends?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Pass maxTotalChargeUsd as a query parameter on the run endpoint - a hard per-execution ceiling. Always set one on unattended and scheduled runs."
}
},
{
"@type": "Question",
"name": "What makes a run slow?",
"acceptedAnswer": {
"@type": "Answer",
"text": "maxPosts, mostly. Each post is a separate page load with a fixed settle wait, and the initial profile scroll runs up to 15 passes before it gives up. More comments from fewer posts is both faster and less block-prone."
}
}
]
}