# Facebook Search Posts Scraper - Keyword, Date & Location (`topapi/facebook-search-posts-scraper`) Actor

Search public Facebook posts by keyword and get one row per post: text, author Page or profile, date, reactions by type, comments, shares, video views, photos, video and link attachments, group and place. Recent-first, date and location filters, monitor mode. No login or cookies.

- **URL**: https://apify.com/topapi/facebook-search-posts-scraper.md
- **Developed by:** [Top Api](https://apify.com/topapi) (community)
- **Categories:** Social media, Marketing, Lead generation
- **Features:** Limited permissions
- **Stats:** 586 total users, 398 monthly users, 69.7% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.40 / 1,000 post scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Facebook Search Posts Scraper do?

**Facebook Search Posts Scraper** searches public Facebook posts by keyword and turns every hit into a structured row: one row per post with the full text, the author Page or profile, the publish date, reactions by type, comments, shares, video views, photos, video and link attachments, and the group or place the post belongs to. Built for brand monitoring, market research and lead-generation teams that need Facebook posts data without a login, cookies or an API key.

Facebook Posts Search - Facebook Keyword Search Scraper - Facebook Post Search API - Facebook Mentions Monitor

<a href="https://console.apify.com/actors/I5iV2ajKeIfaf4DBs"><img src="https://api.apify.com/v2/key-value-stores/qNQ9zP0xaj2yxGeMY/records/facebook-search-posts-scraper-source.png" alt="Facebook search results for a keyword that Facebook Search Posts Scraper turns into rows" style="width:70%"></a>

- **Facebook's own search, not a page crawl:** the public posts search Facebook runs for your keyword, ranked by relevance or newest first, 5-6 posts per page, deep pagination (41 posts from 5 keywords in 55 seconds on a test run).
- **Every engagement number:** reactions with the like / love / care / haha / wow / sad / angry breakdown, comments, shares and video views - filled on 100% of a 100-post test run (breakdown on 97%).
- **One better than the rest:** `matches_query` says whether the text really contains your keyword; `group`, `location`, `author.is_business_page` and `engagement_count` come on every row; the details add-on adds top comments and video SD/HD files.
- **Filters:** date window, strict keyword match, post type, source (groups, Pages, profiles) and minimum reactions.
- **Monitor mode:** remembers what it delivered per keyword and returns only new posts - pair it with a schedule for a feed of fresh mentions.
- **No login, cookies or Facebook API key:** the actor reads only what Facebook shows a signed-out visitor.
- **Export anywhere:** JSON, CSV, Excel, XML, RSS; schedules, webhooks, Make, Zapier, n8n, Google Sheets, Slack.
- **Works with AI agents:** call it through the Apify API or the MCP server; `compact` trims rows for LLM context windows.

### What data can you get from Facebook posts search?

<table>
<tr>
<td>🔗 Post URL and id (`url`, `post_id`)</td>
<td>📝 Full text (`message`), hashtags, mentions</td>
<td>📅 Publish date (`timestamp`, `published_at`)</td>
</tr>
<tr>
<td>👤 Author id, name, URL, avatar, type</td>
<td>🏢 Business Page flag (`author.is_business_page`)</td>
<td>👍 Reactions total and by type (`reactions`)</td>
</tr>
<tr>
<td>💬 Comments and shares (`comments_count`, `reshare_count`)</td>
<td>▶️ Video views, duration, thumbnail, captions URL</td>
<td>🖼️ Photos and albums (`image`, `images`, `album_count`)</td>
</tr>
<tr>
<td>🌐 Outbound link with title, source, preview (`external_link`)</td>
<td>🔁 Shared post URL and author (`attached_post`)</td>
<td>👥 Public group id, name, URL (`group`)</td>
</tr>
<tr>
<td>📍 Tagged place (`location`)</td>
<td>🎯 Contains your keyword? (`matches_query`)</td>
<td>💬 Top comments, video files (details add-on)</td>
</tr>
</table>

On a 100-post test run for "coffee" every row had text, author, date, reactions, comments and shares; 73% carried an image, 47% came from public groups, 11% were videos (views on 10 of 11), 52% had hashtags and 91% contained the word "coffee".

### How to scrape Facebook posts by keyword with Facebook Search Posts Scraper

1. [Create a free Apify account](https://console.apify.com/sign-up) - $5 of monthly credit, no card needed.
2. Open [Facebook Search Posts Scraper](https://apify.com/topapi/facebook-search-posts-scraper) and click **Try for free**.
3. Paste your keywords into **Search queries** (one per line) and set **Max posts per query**.
4. Pick **Sort by** (Facebook's top posts or most recent first), optionally a date window and a location.
5. Click **Start**. Rows stream into the dataset as each page of results arrives.
6. Open the **Storage** tab and **Export** as JSON, CSV or Excel - or let a schedule run it for you.

### ⬇️ Input

| Parameter | Type | Description |
|---|---|---|
| **🔍 What to scrape** | | |
| `searchQueries` | List | **Required** (defaults to the sample "coffee"). Keywords, phrases or hashtags, e.g. `coffee`, `#blackfriday`, `iPhone 17 battery`; a Facebook search URL also works. |
| **🎯 Filters** (applied by Facebook inside the search) | | |
| `sortBy` | Select | `top` = Facebook's relevance ranking (default), `recent` = most recent first. |
| `startDate` / `endDate` | String | `2026-09-01`, `7 days`, `3 weeks`, or a day count. Sent to Facebook as its date filter and re-checked on every post. An end date includes that whole day; the same date in both gives a single day. |
| `locationUid` | String | Facebook's numeric place id, e.g. `108424279189115` (New York, NY). |
| **✂️ Refine results** | | |
| `mustContainQuery` | Boolean | Keep only posts whose text contains the query. Default `false`. |
| `keywordFilter` | String | Keep only posts whose text, author, link title or group name contain a word (`discount, sale` = any). |
| `postType` | Select | `all`, `photo`, `video`, `link` or `text`. |
| `postSource` | Select | `all`, `groups`, `pages_and_profiles` or `business_pages`. |
| `minReactions` | Integer | Keep only posts with at least this many reactions. Default `0`. |
| **➕ Extra data** | | |
| `includePostDetails` | Boolean | Adds `top_comments`, `video_files` (SD/HD) and the view count from each post's public page - charged as **post-details** at $0.001 per post that gets details. |
| **🔁 Monitoring** | | |
| `monitorMode` | Boolean | Return only posts not delivered by previous runs with the same memory. Pair with a schedule. Each run reads a feed only until it reaches posts it has already checked. |
| `monitorStoreName` | String | Key-value store that keeps the per-query memory. Default `facebook-search-posts-monitor`. |
| **📦 Output** | | |
| `maxPostsPerQuery` | Integer | Default `50`; `0` = as many as Facebook serves, up to 1,000 per query (5-6 per page). |
| `maxItems` | Integer | Hard cap for the whole run. `0` = none. |
| `compact` | Boolean | Core fields only, sized for AI agents and MCP. |
| **⚙️ Advanced** | | |
| `proxyConfiguration` | Object | Apify datacenter proxies by default. Since November 2026 Facebook answers the search itself only to residential addresses, so the actor opens the session on the datacenter group and moves the search pages to Apify RESIDENTIAL the moment Facebook refuses them; the proxy cost is included in the price. Runs started by the API, a schedule or a webhook read those pages over a slower connection that transfers about a third less (174 KB a page against 264 on a test run); a run started from the Console takes the faster one. Your own proxy URLs are used for everything if you give them. |
| `maxConcurrency` | Integer | Kept for compatibility: the actor reads all queries in parallel on its own. |

#### Input JSON

```json
{
  "searchQueries": ["coffee", "cold brew"],
  "sortBy": "recent",
  "startDate": "7 days",
  "mustContainQuery": true,
  "maxPostsPerQuery": 50,
  "monitorMode": true
}
```

#### Put one keyword per line, not one long phrase

Facebook matches the query against the post text and ranks loosely related posts too. Single words match almost always (94% of "coffee" and "pizza" results contained the word on a 307-post test); long phrases rarely ("hiring now apply" matched 0 of 10). **Do:** `cold brew` and `pumpkin spice latte` as two lines. **Don't:** `coffee shop hiring barista downtown`. Turn on `mustContainQuery` when every row must contain the exact words.

#### Use "Most recent first" for monitoring, "Top" for research

`top` is Facebook's relevance ranking: popular posts of any age, right for research and content discovery. `recent` returns the newest public posts first; with `monitorMode` the run stops as soon as it reaches a page it already checked, so a scheduled check costs one or two pages. On a frequent schedule (every few minutes), a query is checked on every run while it keeps bringing new posts; once it has answered "nothing new" twice in a row it is checked every 15 minutes, then every 30, then every hour, and the first new post resets it to every run. Hourly or slower schedules are checked on every run. The status message of a run names the queries that were not due and when the next check is.

#### Find a location id before you use the location filter

`locationUid` wants Facebook's numeric id of a city or region, not its name. On facebook.com, run the search, apply the city filter, open a result's About tab and click the city: the number at the end of that page's URL is the id. Tested: `108424279189115` (New York) returned pizza posts tagged "New York, NY, United States". Leave it empty for a global search.

### ⬆️ Output

Every post becomes one dataset item. Here is the table view of a run for `Tesla` and `plumber near me` (most recent first, last 7 days):

<a href="https://console.apify.com/actors/I5iV2ajKeIfaf4DBs"><img src="https://api.apify.com/v2/key-value-stores/qNQ9zP0xaj2yxGeMY/records/facebook-search-posts-scraper-output.png" alt="Facebook Search Posts Scraper output table with posts, authors, reactions, comments and shares" style="width:70%"></a>

And one real row from the 100-post "coffee" run (trimmed):

```json
{
  "post_id": "1113407151220671",
  "type": "photo",
  "url": "https://www.facebook.com/greenhousecoffeebar21/posts/pfbid034DHRsirpdQQZBg84SYp3rXU1mD6xu1tMc8CsJ4gcgjiuWGeS2JMQnwV6eV81wfCBl",
  "message": "As we reflect on the last 4.5 years of Greenhouse we are filled with so much gratitude ...",
  "published_at": "2026-09-28T20:20:22.000Z",
  "author": { "id": "100076541894287", "name": "Greenhouse Coffee Bar", "url": "https://www.facebook.com/greenhousecoffeebar21", "type": "user", "is_business_page": false },
  "reactions_count": 48,
  "comments_count": 56,
  "reshare_count": 5,
  "reactions": { "like": 22, "love": 24, "care": 1, "haha": 0, "wow": 1, "sad": 0, "angry": 0 },
  "image": { "uri": "https://scontent-mia3-3.xx.fbcdn.net/v/t39.99422-6/...", "width": 526, "height": 701 },
  "is_group_post": false,
  "privacy": "Public",
  "hashtags": ["nationalcoffeeday"],
  "matches_query": true,
  "search_query": "coffee"
}
```

#### Facebook post fields

| Field | Type | What it is | Fill on the 100-post run |
|---|---|---|---|
| `post_id`, `url`, `story_id`, `comments_id` | string | Post id, permalink, story id, feedback id | 100% |
| `type` | string | `photo`, `album`, `video`, `link`, `marketplace`, `event`, `share` or `status` | 100% |
| `message` | string | Full text, never truncated (longest seen 3,160 characters) | 100% |
| `timestamp`, `published_at` | integer, ISO 8601 | Publish time | 100% |
| `author` | object | `id`, `name`, `url`, `profile_picture_url`, `type` (`page`, `user`, `anonymous`), `is_business_page` | 100% |
| `author_title` | string | Facebook's header line, e.g. "Iron Bloom Coffee Bar is in Elyria, OH." | 9% |
| `reactions_count`, `comments_count`, `reshare_count`, `engagement_count` | integer | Totals; engagement = reactions + comments + shares | 100% |
| `reactions` | object | `like`, `love`, `care`, `haha`, `wow`, `sad`, `angry`; an unlisted type is `0` when the listed ones add up to the total, else `null` | 97% |
| `video_view_count`, `video`, `video_id`, `video_thumbnail`, `video_duration_ms`, `video_captions_url` | mixed | Video posts only | 10-11% (every video post) |
| `video_files` | object | `video_sd_file`, `video_hd_file` - details add-on | 3 of 3 videos on the details run |
| `image`, `images`, `album_count`, `image_alt` | object, array | First image, every image of the post or album, accessibility caption | 73% / 81% |
| `external_url`, `external_link` | string, object | Outbound link (unwrapped) with title, description, source, preview image | 1% on "coffee", 7% across 307 mixed posts |
| `attached_post_url`, `attached_post` | string, object | The original post when this one is a share | 1% |
| `attachments` | array | Every attachment: kind, url, title, image, id | 92% |
| `is_group_post`, `group` | boolean, object | Public group `id`, `name`, `url` | 47% |
| `location` | object | Tagged place `id`, `name`, `url` | 2% on "coffee", 5% across 307 posts |
| `privacy` | string | `Public` or `Public group` | 100% |
| `hashtags`, `mentions` | array | Parsed from the text | 52% / 2% |
| `top_comments` | array | Up to ~10 public top comments: id, text, date, author, reactions - details add-on | 10 of 16 posts had one on the details run |
| `matches_query`, `search_query`, `sort`, `search_source`, `scraped_at` | mixed | Exact-match flag, the query and sort that produced the row, `facebook_posts_search` | 100% |

### How can I use Facebook posts search data?

- 🎯 **Brand and competitor monitoring** - schedule `recent` + `monitorMode` for your brand names and get every new public mention with its reach.
- 📊 **Market and sentiment research** - pull the top posts for a topic and read `message`, `reactions` by type and `comments_count`.
- 🔎 **Lead generation** - search "looking for a plumber" or "recommend a dentist" with `postSource: groups`; `group`, `author` and `url` point you to the conversation.
- 🏢 **Local business discovery** - `locationUid` plus `postSource: business_pages` lists Pages posting about a topic in one city.
- 📰 **Content and creator discovery** - `postType: video` with `minReactions` finds the videos that work; `video_view_count` and `video_files` make them comparable.
- 🤖 **AI and research teams** - feed `compact` rows to an LLM for summaries or classification; `matches_query` and `hashtags` are ready-made labels.
- 📈 **Trend tracking** - run the same keywords weekly and compare `reactions_count` and the number of posts per week.

### How much does it cost to scrape Facebook posts search?

Facebook Search Posts Scraper is pay-per-result: **$2.40 per 1,000 posts**, no start fee. You only pay for the results you get. The optional post details are **$1.00 per 1,000 posts** that receive them.

| Posts | Cost | With post details |
|---:|---:|---:|
| 10 | $0.024 | $0.034 |
| 100 | $0.24 | $0.34 |
| 1,000 | $2.40 | $3.40 |
| 10,000 | $24.00 | $34.00 |

There is nothing else to pay: Apify platform usage (compute, proxy) is included in these prices. A run stops taking new pages once its own platform cost has passed what it has earned (after an allowance for a normal start); it then delivers what it has and says so in its status. Measured on the platform at the default 128 MB (November 7, 2026): a 12-post run takes 12 seconds, 41 posts from five queries 55 seconds, 30 posts from a three-query monitor run 22 seconds, and a monitor check that finds nothing new 7 seconds. Post details are heavier: 20 posts with details take about 95 seconds at 128 MB and 31 seconds at 256 MB, so set the run's memory to 256 MB when you use them.

### Facebook posts in your tools: integrations, API, scheduling & MCP

- **Schedules:** run it hourly, daily or weekly from the **Schedules** tab; combine with `monitorMode` and `sortBy: recent` to get only new posts each time.
- **Webhooks:** fire a URL when a run finishes - push new mentions to your CRM, Slack or a sheet.
- **No-code:** Make, Zapier, n8n, Google Sheets, Airtable, Slack via [Apify integrations](https://docs.apify.com/integrations).
- **API:** call it from Node.js or Python with `apify-client` - code on the [API tab](https://apify.com/topapi/facebook-search-posts-scraper/api/python) and the [Apify API reference](https://docs.apify.com/api/v2). Run the default build (`latest`): Apify removes older builds after about two weeks, so a run pinned to a build number stops starting, and older builds lack the current speed and fixes.
- **MCP / AI agents:** connect Claude, Cursor or any MCP client through the [MCP tab](https://apify.com/topapi/facebook-search-posts-scraper/api/mcp) and ask for Facebook posts about a topic in plain language; set `compact: true` to keep rows small.

### More social media scrapers by TopApi

<table>
<tr>
<td>📍 <a href="https://apify.com/topapi/google-maps-reviews-scraper">Google Maps Reviews Scraper</a> - reviews, ratings, owner replies and dates for any place</td>
<td>🎵 <a href="https://apify.com/topapi/tiktok-scraper">TikTok Scraper</a> - videos, hashtags, profiles and search with transcripts</td>
<td>📸 <a href="https://apify.com/topapi/instagram-scraper">Instagram Scraper</a> - posts, reels, hashtags and profiles without login</td>
</tr>
<tr>
<td>🔎 <a href="https://apify.com/topapi">All TopApi actors</a> - monitor-ready scrapers built for schedules, APIs and AI agents</td>
<td></td>
<td></td>
</tr>
</table>

### Limits & empty runs

- **Results per query:** 5-6 posts per page, up to 1,000 per query; consecutive pages measured without a duplicate (16 unique posts over 3 pages, 41 over 9). Split a broad topic into several keywords to go wider.
- **Relevance is Facebook's:** the search also returns loosely related posts, and even a nonsense term returns posts. `matches_query` marks the exact matches; `mustContainQuery` keeps only those.
- **Reactions by type** are the types Facebook lists on the post; when they do not add up to the total, the unlisted types are `null`, not zero.
- **Business Page flag** comes from Facebook's "additional profile" marker, so creator pages can appear as `user`.
- **Post details** open each post's public page (about 0.8 MB each); comments are the top-level ones Facebook shows a visitor (0-10 per post), not the full thread.
- **Empty dataset:** Facebook returned no posts, every post was removed by your filters, or monitor mode found nothing new - the status message says which.
- **Was the search finished?** Every run that made a request writes a `RUN_SUMMARY` record to its key-value store (and the same totals to the log). Per query it gives `status` (`ok`, `empty`, `partial`, `blocked`, `not_due`), `complete` (true only when Facebook ran out of posts or your cap was reached), `read`, `delivered`, `pages`, `filtered` and `error`; for the run, `allQueriesComplete` and `incompleteQueries`. A run can end SUCCEEDED with a `partial` query: the run's cost cap, its time limit or a refusal stopped it early (the status message says "cut short"). Re-run that query, or for date windows run a narrower window per run; nothing unread is charged.
- **Cost cap:** the run reads further only from what it delivers (every residential page is paid out of delivered posts), so a query where most posts fall outside your filters can stop before Facebook runs out. `maxTotalChargeUsd` (Maximum cost per run) is your own hard cap on top of that.
- **Not available signed-out:** full comment threads, reactor lists, private groups, restricted-audience posts. Media and avatar URLs are signed CDN links that expire after a few hours.

### FAQ

#### How many Facebook posts can Facebook Search Posts Scraper collect in one run?

Up to 1,000 posts per search query (`maxPostsPerQuery: 0`) and as many queries as you list, within the run's time limit. A 100-post run took 34 seconds on the platform.

#### Can I run Facebook Search Posts Scraper on a schedule to get new posts automatically?

Yes. Save your input as a task with `sortBy: recent` and `monitorMode: true`, open **Schedules**, pick the cadence, and each run delivers only posts it has not delivered before. A run that finds nothing new bills nothing. Give each feed its own `monitorStoreName`. On schedules faster than hourly, a query that keeps finding nothing new is re-checked every 15 to 60 minutes rather than on every run (see "Use Most recent first for monitoring" above).

#### Can I filter Facebook posts by date with Facebook Search Posts Scraper?

Yes. `startDate` and `endDate` accept absolute dates or relative values such as `7 days`. The window is sent to Facebook and re-checked on every post; on a test run the 7-day window removed 12 older posts Facebook had still ranked.

#### Does Facebook Search Posts Scraper return comments?

Post rows carry the comment count. With `includePostDetails` the actor adds `top_comments` (the top-level comments Facebook shows signed-out, up to about 10, with text, date, author and reactions) plus `video_files` and the view count for videos. Full threads need a dedicated comments scraper.

#### Can I integrate Facebook Search Posts Scraper with other apps?

Yes - Make, Zapier, n8n, Google Sheets, Slack and more via [Apify integrations](https://docs.apify.com/integrations), or use [webhooks](https://docs.apify.com/integrations/webhooks) to trigger an action when a run finishes.

#### Can I use Facebook Search Posts Scraper with the Apify API?

Yes. Use `apify-client` for [Node.js](https://apify.com/topapi/facebook-search-posts-scraper/api/javascript) or [Python](https://apify.com/topapi/facebook-search-posts-scraper/api/python); the API tab has ready-to-paste code for starting runs and fetching datasets.

#### Can I use Facebook Search Posts Scraper through an MCP server?

Yes. Open the [MCP tab](https://apify.com/topapi/facebook-search-posts-scraper/api/mcp), connect your MCP client (Claude Desktop, Cursor, LibreChat and others) and ask for Facebook posts about a topic in plain language. `compact: true` returns a fifth of the bytes per row.

#### Do I need a Facebook account, cookies or an API key for Facebook Search Posts Scraper?

No. The actor reads only what Facebook shows a signed-out visitor; you pass keywords and nothing else. It never asks for your cookies or session.

#### Why did my Facebook Search Posts Scraper run return no results?

Most often every post was removed by `mustContainQuery` or another refine filter (the status message lists the counts), the date window was too narrow for a rare keyword, or monitor mode had already delivered everything new. The run log names the cause.

#### How is Facebook Search Posts Scraper different from other Facebook post search scrapers?

It runs Facebook's own public posts search without a login, returns reactions by type, comments, shares and video views on every row (100% on a 100-post test), adds `matches_query`, `group`, `location`, `author.is_business_page` and `engagement_count`, filters by date, keyword match, post type, source and reactions, and has monitor mode and a details add-on with top comments and video files.

#### Is it legal to scrape Facebook posts data?

Facebook Search Posts Scraper extracts only publicly available posts; it does not log in or collect private data. Results may still contain personal data, which is regulated (for example by GDPR). Make sure you have a legitimate purpose before you use it, and consult a lawyer if you are unsure.

#### Your feedback

We keep improving Facebook Search Posts Scraper. Found a bug or missing a field? Open an issue on the [Issues tab](https://apify.com/topapi/facebook-search-posts-scraper/issues/open) - we answer within one business day.

# Actor input Schema

## `searchQueries` (type: `array`):

Keywords, phrases or hashtags, one per line, e.g. "coffee", "#blackfriday", "iPhone 17 battery". A Facebook search URL such as https://www.facebook.com/search/posts/?q=coffee also works. Facebook's search is fuzzy: it ranks related posts, so turn on 'Only posts that contain the query' for strict results.

## `sortBy` (type: `string`):

"Top" is Facebook's default ranking (popular posts, any age). "Most recent first" returns the newest public posts and pairs with monitor mode for a feed of new mentions.

## `startDate` (type: `string`):

Absolute date (2026-09-01) or relative to now (7 days, 3 weeks, 2 months, 1 year) or a day count (1 = today, 2 = yesterday and today). Sent to Facebook as its date filter and re-checked on every post. Leave empty for no lower bound.

## `endDate` (type: `string`):

Absolute date or relative (e.g. 30 days). A date includes that whole day. Combine with 'Posted after' for a window such as startDate 2026-01-01 + endDate 2026-06-30, or the same date in both for a single day.

## `locationUid` (type: `string`):

Facebook's numeric id of a city or region to restrict the search to posts tagged there, e.g. 108424279189115 (New York, NY). Find it on facebook.com: search, open the city filter and copy the number at the end of the location page URL. Leave empty for a global search.

## `mustContainQuery` (type: `boolean`):

Keep only posts whose text contains the search query (case-insensitive). Facebook's search also returns related posts without the exact words; this makes the result strict. Measured on 307 posts: single words matched 94% (coffee, pizza), multi-word phrases far less ("hiring now apply" 0%, "zillow listing" 40%).

## `keywordFilter` (type: `string`):

Keep only posts whose text, author name or link title contain this word or phrase, case-insensitive, e.g. "recipe" or "discount, sale, promo" (comma = any of them). Leave empty for no filter.

## `postType` (type: `string`):

Keep only one kind of post. Marketplace listings and event posts count as 'photo' when they carry an image.

## `postSource` (type: `string`):

Where the post was published. Measured on 307 search results: 25% were public-group posts, 4% came from business Pages, the rest from profiles and creator pages.

## `minReactions` (type: `integer`):

Keep only posts with at least this many reactions, e.g. 100 to keep popular posts only. 0 = no minimum.

## `includePostDetails` (type: `boolean`):

Opens each post's public page and adds the top comments Facebook shows signed-out (up to about 10: text, author, date, reactions), the video SD/HD file URLs and the video view count. Charged as the post-details event only for posts that received details. About one extra request (0.8 MB) per post.

## `monitorMode` (type: `boolean`):

Remembers, per search query, which posts were already delivered (in the named key-value store below) and returns only new ones. Works best with 'Most recent first': the run stops as soon as a whole page was already checked, so a scheduled check costs one or two pages. A run that finds nothing new delivers nothing. On schedules faster than hourly, a query is checked on every run while it brings new posts; after two checks in a row with nothing new it is checked every 15 minutes, then every 30, then every hour, until a new post resets it (hourly or slower schedules are checked on every run).

## `monitorStoreName` (type: `string`):

Name of the key-value store that keeps the per-query memory for monitor mode. Give each separate feed (a brand, a client, a Slack channel) its own name so they do not hide posts from each other. Letters, digits and hyphens.

## `maxPostsPerQuery` (type: `integer`):

Cap per search query after filters (your main cost control; you pay per delivered post). Facebook serves 11-12 posts per page; deep pagination measured to 8+ pages. 0 = as many as Facebook serves, up to 1,000 per query.

## `maxItems` (type: `integer`):

Hard cap for the whole run across all queries. 0 = no total cap (each query is still capped above).

## `compact` (type: `boolean`):

Core fields only (post_id, type, url, message, published_at, author name/url/type, reactions, comments, shares, views, image, video, external_url, group, location, hashtags, search_query): about a fifth of the bytes, sized for AI agents and MCP clients.

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

Apify datacenter proxies by default. Facebook now answers the search itself only to residential addresses, so the actor opens its session on the datacenter group and moves the search pages to Apify RESIDENTIAL the moment Facebook refuses them (included in the price; no setting needed). Your own proxy URLs, if given, are used for everything.

## `maxConcurrency` (type: `integer`):

Kept for compatibility. The actor reads all queries in parallel on its own (up to 6 at 128 MB, 10 at 256 MB), so this value no longer changes a run.

## Actor input object example

```json
{
  "searchQueries": [
    "coffee"
  ],
  "sortBy": "top",
  "mustContainQuery": false,
  "keywordFilter": "",
  "postType": "all",
  "postSource": "all",
  "minReactions": 0,
  "includePostDetails": false,
  "monitorMode": false,
  "monitorStoreName": "facebook-search-posts-monitor",
  "maxPostsPerQuery": 12,
  "maxItems": 0,
  "compact": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 2
}
```

# Actor output Schema

## `posts` (type: `string`):

The dataset of Facebook posts found by the search (one item per post).

## `summary` (type: `string`):

Per-query counts (read, filtered, already delivered, delivered), pages, requests made, sessions used and bytes transferred. Written for runs started in the Console, runs of 50+ posts and runs with a problem; small API, scheduled and webhook runs report the same counts in their status message and log.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQueries": [
        "coffee"
    ],
    "maxPostsPerQuery": 12
};

// Run the Actor and wait for it to finish
const run = await client.actor("topapi/facebook-search-posts-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQueries": ["coffee"],
    "maxPostsPerQuery": 12,
}

# Run the Actor and wait for it to finish
run = client.actor("topapi/facebook-search-posts-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "coffee"
  ],
  "maxPostsPerQuery": 12
}' |
apify call topapi/facebook-search-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,topapi/facebook-search-posts-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/I5iV2ajKeIfaf4DBs/builds/fbqrWCqyGjtfbodjM/openapi.json
