Facebook Posts Search Scraper: Content Calendar Analysis avatar

Facebook Posts Search Scraper: Content Calendar Analysis

Pricing

from $4.99 / 1,000 results

Go to Apify Store
Facebook Posts Search Scraper: Content Calendar Analysis

Facebook Posts Search Scraper: Content Calendar Analysis

๐Ÿ”Ž Facebook Posts Search Scraper extracts public posts by keyword, hashtag, or date โ€” capturing text, author, URL, reactions, comments & shares. ๐Ÿ“ˆ Ideal for social listening, trend analysis, and competitor research. Export CSV/JSON, schedule, and scale via API. ๐Ÿš€

Pricing

from $4.99 / 1,000 results

Rating

0.0

(0)

Developer

API Empire

API Empire

Maintained by Community

Actor stats

0

Bookmarked

7

Total users

0

Monthly active users

5 days ago

Last modified

Share

Facebook Posts Scraper โ€” Extract Posts, Page Rollups and Rankings

Facebook Posts Search Scraper: Content Calendar Analysis discovers public Facebook posts by keyword or competitor name and returns three linked outputs: matching posts, a per-page engagement rollup, and a competitor ranking table. Every response is typed, normalized JSON โ€” no HTML, no selectors, no parsing. Point it at a topic, brand, or rival page name, and it finds matching posts, groups them by the Facebook Page that published them, and ranks any competitors you list by likes, comments, and shares.

What is Facebook Posts Search Scraper: Content Calendar Analysis?

Facebook Posts Search Scraper: Content Calendar Analysis is an Apify Actor that finds public Facebook posts matching one or more search keywords, brand names, or competitor page names โ€” no Facebook account or login required. It then automatically rolls up the matching posts per Facebook Page (post count, average engagement, top-performing post) and, when you list pages to compare, ranks them side by side on engagement. Optional add-ons enrich pages with follower/category data, page contact details, and post comments.

  • Discover posts by keyword, brand, or competitor/page name across public Facebook
  • Roll up matching posts per Facebook Page: post count, average likes/comments/shares, top post
  • Rank a custom list of competitor pages side by side on engagement
  • Optionally enrich pages with followers/category, page contact details, or post comments
  • Export as JSON or CSV, or read results via the Apify API

What data does Facebook Posts Search Scraper: Content Calendar Analysis collect?

The Actor returns four distinct data types from a single run: the discovered posts themselves, a per-page rollup, an optional competitor ranking, and optional child datasets for comments and contact details.

Data TypeKey FieldsJSON Field Names
Postspage, engagement, caption text, media, timestamppageName, likes, comments, shares, text, thumb, timestamp
Page Summary (rollup)post count, average engagement, top post, optional followers/categorypostCount, avgLikes, avgComments, topPostUrl, followersCount, pageCategory
Comparison Rankingrank, posts found, engagement score per competitorrank, engagementScore, avgLikes, postsFound
Comments (child dataset)comment text, author, likes, repliescommentText, authorName, likesCount, repliesCount
Page Contact (lead data)email, phone, website, addresscontact.email, contact.phone, contact.website, contact.address

Need more Facebook data?

If you need a deep dive on one Page's content strategy rather than keyword discovery across many pages, Facebook Posts Scraper: Content Strategy Insights classifies every post's content type, hashtags, and calls-to-action for a single Page's timeline. If you need full comment threads rather than the top-level comments this Actor collects, Facebook Comments Scraper With Author Lead Enrichment pulls deeper comment data with commenter profile enrichment.

How does Facebook Posts Search Scraper differ from the official Facebook API?

Meta's Graph API requires a registered Meta app, App Review, and โ€” for most Page-content permissions โ€” Business Verification before it returns any Page posts, and it has no endpoint for keyword search across arbitrary public pages; access is scoped to Pages and accounts your app has been explicitly granted. Facebook Posts Search Scraper instead discovers public posts directly from a keyword or page name, with no app review and no per-page permission grant.

FeatureFacebook Graph APIFacebook Posts Search Scraper
Access setupMeta App Review + Business VerificationNo account, no app registration
Keyword search across pagesNot supported โ€” no public post-search endpointCore feature: search by keyword or competitor name
Scope of accessible postsPages/accounts your app is granted access toAny public Facebook post discoverable via search
Page/competitor rollupsNot provided โ€” build it yourself from raw responsesBuilt-in per-page rollup and competitor ranking
Setup timeReview process required before first callFill in input, run
Output consistencyRaw Graph API JSON, versioned per endpointStable typed JSON schema, same fields every run

The Graph API is the right choice if you manage the Pages in question and need officially permissioned access to your own Page analytics. Facebook Posts Search Scraper is the practical choice when you need to discover and compare posts from pages you don't manage, without going through an app review process.

Why do developers and teams scrape Facebook?

For marketers and brand teams

Marketers use comparePages to list a handful of competitor page names or search queries and get back a ranked COMPARISON-RANKING table sorted by engagementScore โ€” the fastest way to see whose posts about a topic are landing best this week. Combined with the per-page PAGE-SUMMARY rollup, a brand team can track its own page's avgLikes/avgComments/avgShares against named rivals without manually opening each competitor's Page and counting reactions by hand. Re-running the same competitorQueries on a schedule turns this into ongoing competitor-monitoring rather than a one-off snapshot, feeding a recurring content or campaign review.

For researchers and analysts

Researchers studying public discourse around a topic, event, or brand can search by keyword rather than by page, so the dataset isn't limited to accounts they already know about. Each post row carries timestamp, text, and engagement counts, giving a public, citation-ready sample of how a topic is being discussed across different Facebook Pages โ€” useful for tracking sentiment or reach trends without accessing any private profile or gated group content. The postRecencyWindow filter lets a study scope its sample to a fixed recent window, and searchQuery on every row records which term produced each post for later cross-tabulation.

For AI engineers and agent builders

Agent builders can wire competitorQueries as a tool parameter so an LLM agent decides what to search for, then pass the returned text, likes, comments, and shares fields directly into a RAG index or a summarization prompt โ€” no HTML cleanup step. Because output is stable typed JSON with the same keys on every run, an agent can reliably parse PAGE-SUMMARY records to answer questions like "which page posts about this topic gets the most engagement?" without brittle scraping logic.

For developers building data products

Developers building a competitor-monitoring product or a lead-gen tool can schedule this Actor on a recurring basis, pass different competitorQueries per customer, and store the resulting posts, page rollups, and optional contact records in their own database. The optional enableContactLookup and maxCommentsPerPost fields let a data product add email/phone/website leads and comment-level detail on top of the base post-and-rollup pipeline, all from the same run. Because every field name and type stays fixed between runs, downstream ingestion code can be written once and left alone as the underlying scrape logic evolves.

How to scrape Facebook (step by step)

  1. Open Facebook Posts Search Scraper: Content Calendar Analysis on its Apify Store listing and start a new run.
  2. Provide competitorQueries โ€” the keywords, brand names, or competitor page names to search for (none are strictly required; the Actor defaults to football if left empty).
  3. Set filters: maxPostsPerQuery to cap results per query, postRecencyWindow to limit by recency, and comparePages if you want a ranked comparison table.
  4. Start the run.
  5. Download the post dataset as JSON or CSV, and read the PAGE-SUMMARY / COMPARISON-RANKING records from the run's Key-Value Store for the rollups.

What to do when Facebook changes its structure

Facebook Posts Search Scraper is actively maintained, and its output schema is kept stable โ€” field names and types don't change on your end even when the underlying extraction logic needs updates on ours. No specific turnaround time is promised for any given fix.

โฌ‡๏ธ Input

Required per the input schema: none โ€” every field below is optional, and the Actor runs with sensible defaults if you provide nothing.

ParameterRequiredTypeDescriptionExample Value
competitorQueriesNoarraySearch keywords or competitor/page names to discover posts for. Each entry runs as a separate search.["nike", "adidas"]
maxPostsPerQueryNointegerPosts to collect per keyword/competitor. Range 1โ€“5000; leave empty for the default of 50.20
postRecencyWindowNostring (enum)Recency filter: "" (all time, default), 24h, 7d, 30d, 90d."7d"
enablePageSummaryNobooleanGroup discovered posts by page and emit one summary record per page (post count, avg engagement, top post) to Key-Value Store record PAGE-SUMMARY. Default: on (code default true).true
enablePageProfileEnrichmentNobooleanFetch each distinct page's public profile once to add follower count and category to the page summary. Default: off.false
comparePagesNoarrayPage names, page URLs, or queries to rank side by side on engagement in Key-Value Store record COMPARISON-RANKING. Leave empty to disable.["nike", "adidas"]
targetCountryNostring (enum)Bias the discovery search toward a country's results (SERP gl param). Blank = no bias (default)."us"
targetLanguageNostring (enum)Language for the discovery search (SERP hl param). Blank = English (default)."en"
enableContactLookupNobooleanFetch each post's Facebook Page and extract public email/phone/website/address into contact. Missing fields are null, never fabricated. Default: false.false
maxCommentsPerPostNointegerTop-level comments to fetch per post (0โ€“500), saved to an uncharged comments-<runId> dataset. 0 (default) disables it.0
proxyConfigurationNoobjectProxy settings for Facebook requests. Default: { "useApifyProxy": true }.{ "useApifyProxy": true }

Example input:

{
"competitorQueries": ["nike", "adidas"],
"maxPostsPerQuery": 20,
"postRecencyWindow": "",
"enablePageSummary": true,
"enablePageProfileEnrichment": false,
"comparePages": ["nike", "adidas"],
"targetCountry": "",
"targetLanguage": "",
"enableContactLookup": false,
"maxCommentsPerPost": 0,
"proxyConfiguration": { "useApifyProxy": true }
}

The most common input mistake is listing the same names in both competitorQueries and comparePages expecting two separate result sets โ€” the Actor de-duplicates any comparePages entry that already appears in competitorQueries, so put every page/query you want ranked into comparePages and leave competitorQueries for the ones you only want discovered.

โฌ†๏ธ Output

Every run produces typed, normalized JSON exported as JSON or CSV from the dataset, plus two optional rollups written to the run's Key-Value Store. Only post rows in the primary dataset are charged (row_result); the PAGE-SUMMARY and COMPARISON-RANKING records and the child comments dataset add no extra charge.

Scraped Posts (primary dataset)

{
"facebookUrl": "https://www.facebook.com/nike",
"pageId": "15087023444",
"pageName": "Nike",
"facebookId": "15087023444",
"postId": "826453901928374",
"postFacebookId": "826453901928374",
"url": "https://www.facebook.com/nike/posts/826453901928374",
"topLevelUrl": "https://www.facebook.com/nike/posts/826453901928374",
"time": "2026-07-18 14:32:05",
"timestamp": 1784385125,
"likes": 18420,
"comments": 612,
"shares": 340,
"text": "New drop. Just do it.",
"link": "https://www.facebook.com/nike/posts/826453901928374",
"thumb": "https://scontent.fxyz1-1.fna.fbcdn.net/v/example.jpg",
"contact": { "email": null, "phone": null, "website": null, "address": null },
"commentsFetched": 0,
"scrapedAt": "2026-07-25T09:12:44.109384+00:00",
"searchQuery": "nike",
"isComparisonTarget": true
}

Page Summary (Key-Value Store record PAGE-SUMMARY)

{
"pageId": "15087023444",
"pageName": "Nike",
"facebookUrl": "https://www.facebook.com/nike",
"postCount": 20,
"avgLikes": 15230.45,
"avgComments": 480.2,
"avgShares": 265.8,
"totalLikes": 304609,
"totalComments": 9604,
"totalShares": 5316,
"topPostUrl": "https://www.facebook.com/nike/posts/826453901928374",
"topPostLikes": 18420,
"searchQueries": ["nike"],
"followersRaw": "42M",
"followersCount": 42000000,
"pageCategory": "Sportswear store",
"likesFromProfile": 41000000
}

Comparison Ranking (Key-Value Store record COMPARISON-RANKING)

{
"query": "nike",
"postsFound": 20,
"avgLikes": 15230.45,
"avgComments": 480.2,
"avgShares": 265.8,
"totalLikes": 304609,
"totalComments": 9604,
"totalShares": 5316,
"engagementScore": 15976.45,
"matchedPageNames": ["Nike"],
"rank": 1
}

Post Comments (uncharged child dataset comments-<runId>, when maxCommentsPerPost > 0)

{
"parentPostId": "826453901928374",
"parentPostUrl": "https://www.facebook.com/nike/posts/826453901928374",
"commentId": "Y29tbWVudDoxMjM0NTY3ODk=",
"feedbackId": "ZmVlZGJhY2s6ODI2NDUzOTAxOTI4Mzc0",
"commentUrl": "https://www.facebook.com/nike/posts/826453901928374?comment_id=123456789",
"commentDate": "2026-07-18T15:02:11+00:00",
"commentText": "Love these!",
"authorName": "Jordan Smith",
"authorId": "100004455667788",
"authorProfileUrl": "https://www.facebook.com/jordan.smith",
"authorProfilePicture": "https://scontent.fxyz1-1.fna.fbcdn.net/v/profile.jpg",
"likesCount": 12,
"repliesCount": 2,
"threadingDepth": 0,
"facebookCommentId": "123456789",
"keyword": "nike",
"isChild": true,
"type": "comment",
"scrapedAt": "2026-07-25T09:13:02.552112+00:00"
}

How many results can you scrape with Facebook Posts Search Scraper?

maxPostsPerQuery caps results at up to 5,000 posts per search query, with a default of 50 if left blank; there is no hard cap on the number of queries you can list in competitorQueries or comparePages, so total posts scale with however many queries you run. Internally, discovery paginates Google search result pages (10 Facebook URLs per page) up to a capped number of pages per query, stopping early once the target count is reached or after three consecutive empty result pages. maxCommentsPerPost separately caps top-level comments fetched per post at up to 500, written to an uncharged child dataset. Facebook itself does not publish a documented limit on how many of its posts are indexable through search, so the practical ceiling for any one query is whatever the discovery search surfaces. No benchmark run time is published โ€” actual duration depends on how many optional enrichments (comments, contact lookup, profile enrichment) are enabled alongside the post count.

Integrate Facebook Posts Search Scraper and automate your workflow

Facebook Posts Search Scraper works with any language or tool that can send an HTTP request, since it runs as a standard Apify Actor.

REST API integration

from apify_client import ApifyClient
client = ApifyClient("<APIFY_API_TOKEN>")
run = client.actor("<owner>/facebook-posts-search-scraper-content-calendar-analysis").call(
run_input={
"competitorQueries": ["nike", "adidas"],
"maxPostsPerQuery": 20,
"comparePages": ["nike", "adidas"],
}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["pageName"], item["likes"], item["comments"])

Works in Python, Node.js, Go, Ruby, cURL.

MCP for AI agents

Apify's MCP server (mcp.apify.com) exposes Apify Actors โ€” including this one โ€” as callable tools for MCP-compatible clients such as Claude Desktop, Cursor, and Windsurf. Add the Actor's name (as shown on its Apify Store page) to the server's actor list to make it callable as an agent tool without writing custom integration code.

Automation platforms (n8n, Make, LangChain)

In n8n, the community Apify node's "Run Actor" operation can call Facebook Posts Search Scraper by Actor ID and pass competitorQueries/maxPostsPerQuery as JSON, then feed the resulting dataset items and PAGE-SUMMARY record into downstream nodes. In Make, the Apify app's "Run an Actor or Task" module runs the same Actor and lets you map each returned post row into another scenario step, such as a spreadsheet row or a Slack alert when a competitor's engagementScore changes. Any LangChain agent that can call an HTTP tool can invoke the Actor through the Apify API and consume its dataset items directly as typed JSON, without a parsing step.

Scraping publicly accessible Facebook data is generally lawful, and Facebook Posts Search Scraper only returns posts and page information visible to a logged-out visitor โ€” no private profiles, no login-gated groups. Most output (post text, engagement counts, page name/category) is business or organizational data governed primarily by Facebook's Terms of Service rather than personal-data law. Two optional features do return personal data: enableContactLookup can surface a Page's public contact details, and maxCommentsPerPost returns commenters' names, IDs, and profile URLs โ€” this is personal data subject to GDPR/CCPA-style requirements around a lawful basis for storage and use. Consult legal counsel for commercial use cases involving bulk personal data.

Frequently asked questions

Does Facebook Posts Search Scraper work without a Facebook account?

Yes. It discovers posts through public search and fetches each post's public page HTML directly โ€” no Facebook login or account is required.

Is "content calendar analysis" a real posting-cadence feature?

Not in the sense of computed posting-frequency or day/hour scheduling patterns โ€” the Actor does not bucket posts by day of week, time of day, or posting interval. What it does compute, from the real scraped rows, is a per-page rollup (postCount, avgLikes, avgComments, avgShares, topPostUrl) and a competitor engagement ranking. Every post row also carries a timestamp, so you can build your own cadence analysis on top of the output, but that bucketing isn't done for you today.

How often is the scraped data updated?

Every run performs a live search and live page fetch โ€” nothing is served from a cache. Re-run the Actor to get current engagement counts and newly published posts.

What happens if a post is removed or a query returns no results?

If a post becomes unavailable mid-run, the fetch is skipped and logged as a warning; other posts in the same run are unaffected. If a query returns zero discoverable Facebook URLs (for example, if the search provider blocks the request), the Actor logs a warning and returns an empty result for that query rather than failing the whole run.

Can I scrape private or login-gated Facebook content?

No. Only content visible to a logged-out visitor is returned โ€” private profiles and login-gated groups are out of scope.

Does Facebook Posts Search Scraper work for AI agent workflows and LLM pipelines?

Yes. It's callable as an HTTP endpoint from any agent framework, and it's reachable through Apify's MCP server for MCP-compatible clients. Every response is typed JSON with stable field names โ€” no HTML, no parsing step before passing results into an LLM context or a RAG index.

How does Facebook Posts Search Scraper handle Facebook's anti-bot measures?

Discovery requests route through Apify's GOOGLE_SERP proxy group, page fetches use Apify Proxy (datacenter/residential as configured) with browser-like request headers, and each HTML fetch retries up to three times with exponential backoff on transient errors. Comment fetches use a residential proxy session when available.

Does Facebook Posts Search Scraper return data in a format LLMs can use directly?

Yes. Typed, normalized JSON with stable field names on every run โ€” pass it directly into an LLM context window, index it into a vector store, or route it through an agent tool without a parsing step.

Can I use Facebook Posts Search Scraper without managing proxies?

Yes. Apify Proxy is enabled by default (useApifyProxy: true), and the search-discovery step always uses Apify's GOOGLE_SERP proxy group regardless of your proxyConfiguration setting.

What happens when Facebook changes its structure or blocks the scraper?

The Actor is actively maintained, and its output schema stays stable โ€” field names and types don't change on your end when the underlying extraction logic is updated. No numeric turnaround time is promised for any given fix.

Your feedback

Found a bug or missing a field? We want to know. Reach out through the Actor's Apify Store page or issue tracker so we can look into it โ€” active maintenance is how this Actor stays reliable as Facebook's page structure evolves.