# Facebook Posts Search Scraper (`socialdataapi/facebook-posts-search-scraper`) Actor

Facebook Posts Search Scraper — Search and extract Facebook posts by keywords, including post text, authors, page details, timestamps, reactions, comments, shares, media URLs, and post links. Useful for content research, competitor analysis, audience insights, and social media monitoring.

- **URL**: https://apify.com/socialdataapi/facebook-posts-search-scraper.md
- **Developed by:** [Social Data API](https://apify.com/socialdataapi) (community)
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

### Facebook Posts Search Scraper — Posts, Engagement and Page Contacts

Facebook Posts Search Scraper takes one or more keywords and returns every matching public post it can find, with page identity, engagement counts, and post text on each row. **No Facebook account or cookies are needed** — it reads only what's publicly visible on facebook.com. Every response is structured JSON — ready to pass directly to an LLM, index into a vector store, or feed a social-listening pipeline. Start with one keyword, then scale to a full brand-monitoring watchlist.

![Facebook Posts Search Scraper hero: keyword search posts, likes, comments and page contact as JSON](https://api.apify.com/v2/key-value-stores/WYkyEfqs10huyXYxr/records/b-facebook-posts-search-hero.webp)

***

### What data can I extract with Facebook Posts Search Scraper?

Using this Facebook Posts Search Scraper API, you can extract Facebook post data — the fields below cover everything the actor returns for each post:

| | | | |
|---|---|---|---|
| 👤 Page name | 🔗 Page URL | 🆔 Page ID | 📝 Post text |
| 📅 Publish time | ❤️ Likes | 💬 Comments | 🔄 Shares |
| 🔎 Search keyword | 🖼️ Post thumbnail | 🔗 Attached link | 📇 Page contact (email, phone, website, address) |
| 💬 Comments fetched (child dataset) | 🕒 Scraped at | 🆔 Post ID | 📎 Post URL |

***

### How to use Facebook Posts Search Scraper

Enter one or more keywords and run a Facebook keyword search that returns every matching public post it can find — with page identity, engagement counts, and text — written to the dataset as each post is scraped, not held back to the end of the run.

**Copy to your AI assistant:**

```text
facebook-posts-search-scraper (Apify Actor ID: socialdataapi/facebook-posts-search-scraper, https://apify.com/socialdataapi/facebook-posts-search-scraper) is an Apify Actor that returns matching public Facebook posts as structured JSON: page name, post text, likes, comments, shares, publish time, and a direct post link. Use it whenever someone needs Facebook post data without cookies, a login, or a browser - social listening on a brand or topic, competitor content tracking, and building a contact list for outreach. Inputs: searchQueries (array of keywords, default [""] which falls back to "football"), maxPosts (integer, 1-5000, default 10), postTimeRange (enum "" | "24h" | "7d" | "30d" | "90d", default ""), targetCountry (enum of 19 country codes, default ""), targetLanguage (enum of 16 language codes, default ""), enableContactLookup (boolean, default false), maxCommentsPerPost (integer, 0-500, default 0), proxyConfiguration (object, default useApifyProxy true). When maxCommentsPerPost is above 0, each post's top-level comments are written to a separate, uncharged comments-<runId> dataset instead of the main one. maxPosts is a per-keyword cap, not a total, so adding more searchQueries entries multiplies how many charged rows one run can produce.
```

#### Facebook Posts Search Scraper MCP Server: use these Actors from ChatGPT, Claude or Cursor

Point your AI assistant at the Apify MCP server and it can find and call this Actor on its own, directly from a prompt — no glue code, no scraping logic to write.

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=socialdataapi/facebook-posts-search-scraper"
```

#### Step by step

1. [Create a free Apify account](https://console.apify.com/sign-up).
2. Open [Facebook Posts Search Scraper](https://apify.com/socialdataapi/facebook-posts-search-scraper) in the Apify Store.
3. Enter one or more Facebook search keywords.
4. Click **Start** (or send your API request).
5. Download or stream your results in JSON, CSV or Excel.

#### How to scale Facebook Posts Search Scraper to bulk

Add more entries to `searchQueries` to scrape Facebook posts by keyword across many topics in one run — each keyword runs as its own independent search, so a run with ten keywords returns results for all ten without ten separate runs. For a recurring brand-monitoring or social-listening workflow, schedule the actor with the same `searchQueries` list on a daily or weekly interval and compare `pageName` and `text` week over week. There's no published rate limit beyond `maxPosts` itself, so the practical ceiling on one run is `maxPosts` multiplied by the number of `searchQueries` entries.

***

### ✨ Features

As a Facebook posts scraper built around free-text keyword search, it fetches clean, structured post data without needing a list of Page URLs. It's ideal for social listening, market research, Facebook lead generation, and grounding context for AI agents.

It extracts, per post:

- **Page name and ID** – who posted it, for de-duplicating across posts
- **Likes, comments and shares** – counts a Facebook engagement scraper needs for ranking posts at scrape time
- **Post text and thumbnail** – the caption and attached media
- **Publish time** – a real timestamp, not an estimate
- **Page contact** – email, phone, website and address when lookup is on

⚡ A recency filter is enforced before a post is ever saved, so an out-of-window post never reaches the dataset or gets charged.

***

### Use cases 💡

- **Social listening analyst** — run it as a Facebook social listening tool to track a brand keyword and read post text and likes in one feed.
- **Market researcher** — compare post volume and engagement across countries with `targetCountry`.
- **Lead-generation agency** — use it as a Facebook lead generation scraper: turn on contact lookup and export page emails and phone numbers.
- **Competitor tracker** — run competitor names as `searchQueries` and watch shares trend weekly.
- **AI agent / RAG pipeline** — feed matching posts as grounding context for summarization or trend-alerting.

Building an AI agent? [Connect Facebook Posts Search Scraper over MCP](#facebook-posts-search-scraper-mcp-server-use-these-actors-from-chatgpt-claude-or-cursor) and let it call the actor on its own.

***

### Why choose this actor?

- **Finds posts by topic, not by Page.** This Facebook post search scraper needs no list of Facebook Page URLs — enter a keyword and get back matching public posts with page identity, text and engagement counts, up to 5,000 posts per keyword.
- **Twenty fields per post, outreach-ready.** Each row carries up to 20 fields, including likes, comments, shares, publish time, and an optional page contact object with email, phone, website and address.
- **Three optional layers on one search.** A recency filter enforced before a row is ever saved, an uncharged child comment feed, and page-contact lookup — each one turned on independently from the same input.

***

### ⬇️ Input

![Facebook Posts Search Scraper input: searchQueries, maxPosts, postTimeRange and enableContactLookup](https://api.apify.com/v2/key-value-stores/WYkyEfqs10huyXYxr/records/b-facebook-posts-search-input.webp)

Enter one or more search keywords in `searchQueries` — every other field is optional and falls back to a sensible default.

| Parameter | Required | Type | Description | Example Value |
| --- | --- | --- | --- | --- |
| `searchQueries` | No | array | Keywords/topics to search for on Facebook. Each keyword runs its own search. Default `[""]` (falls back to `"football"` if left empty at run time). | `["digital marketing", "coffee shop"]` |
| `maxPosts` | No | integer | Max posts to collect per keyword, 1–5,000. Default `10`. | `25` |
| `postTimeRange` | No | string (enum) | Recency window enforced before rows are saved: `""` (all time), `24h`, `7d`, `30d`, `90d`. Default `""`. | `"30d"` |
| `targetCountry` | No | string (enum) | Biases the initial keyword-search step toward a country's results. Default `""` (no bias). | `"us"` |
| `targetLanguage` | No | string (enum) | Sets the language used for the initial keyword-search step. Default `""` (English). | `"es"` |
| `enableContactLookup` | No | boolean | When `true`, fetches each post's Page and attaches a `contact` object (email/phone/website/address). Default `false`. | `true` |
| `maxCommentsPerPost` | No | integer | Max top-level comments to fetch per post, 0–500, saved to an uncharged `comments-<runId>` dataset. Default `0` (disabled). | `10` |
| `proxyConfiguration` | No | object | Proxy used to fetch each discovered post/Page's HTML. The initial keyword-search step always uses a separate, fixed Apify proxy setup, independent of this setting. Default `{ "useApifyProxy": true }`. | `{ "useApifyProxy": true }` |

#### Free plan limits

Free plan: up to 20 posts per run (all keywords together) and 200 per month; paid plans have no limit.

#### Example input

```json
{
  "searchQueries": ["digital marketing", "coffee shop"],
  "maxPosts": 25,
  "postTimeRange": "30d",
  "targetCountry": "us",
  "targetLanguage": "en",
  "enableContactLookup": true,
  "maxCommentsPerPost": 10,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

**Common pitfall:** `maxPosts` is a per-keyword limit, not a total — if `searchQueries` has 5 entries and `maxPosts` is 25, the run can produce up to 125 charged rows, not 25. Size `maxPosts` and the length of `searchQueries` together before starting a large run.

***

### ⬆️ Output

![Facebook Posts Search Scraper output: pageName, likes, searchQuery and contact fields](https://api.apify.com/v2/key-value-stores/WYkyEfqs10huyXYxr/records/b-facebook-posts-search-output.webp)

Every scraped post is one typed, normalized JSON item with the same schema on every run. Export the dataset as JSON, Excel, or download Facebook posts to CSV directly from the Console, or fetch items via the Apify API. When `maxCommentsPerPost` is above `0`, each post's top-level comments go to a separate, uncharged `comments-<runId>` dataset instead of the main one.

#### Example output

```json
{
  "facebookUrl": "https://www.facebook.com/examplepage",
  "pageId": "123456789",
  "pageName": "Example Page",
  "facebookId": "123456789",
  "postId": "987654321",
  "postFacebookId": "987654321",
  "url": "https://www.facebook.com/examplepage/posts/987654321",
  "topLevelUrl": "https://www.facebook.com/examplepage/posts/987654321",
  "time": "2026-06-01 14:32:10",
  "timestamp": 1748788330,
  "likes": 542,
  "comments": 38,
  "shares": 12,
  "text": "Excited to announce our new store opening...",
  "link": null,
  "thumb": "https://scontent.xx.fbcdn.net/v/example_thumb.jpg",
  "searchQuery": "coffee shop",
  "contact": {
    "email": "hello@example.com",
    "phone": null,
    "website": "https://example.com",
    "address": null
  },
  "commentsFetched": 10,
  "scrapedAt": "2026-07-25T10:12:03+00:00"
}
```

***

### How does it work?

Facebook Posts Search Scraper runs an initial keyword-search step to locate matching public post pages, then opens each discovered post directly over plain HTTP requests — no browser — to read its text, engagement counts, and page identity. Requests rotate through proxies, and a request that comes back blocked or login-walled is retried on a fresh proxy session instead of being saved as-is. The actor returns only Facebook public post data — the same content any visitor sees without logging in — and a field Facebook genuinely doesn't expose on a given post comes back `null` rather than a guessed value. The output schema stays the same shape run after run, even as Facebook's own page layout changes, because that normalization work happens on the actor's side, not yours.

***

### How do you integrate Facebook Posts Search Scraper into your stack?

Facebook Posts Search Scraper works with what you already use: a REST API callable from any language, an MCP server for AI agents, and no-code automation tools.

#### Using Facebook Posts Search Scraper with the Apify API

```python
from apify_client import ApifyClient

client = ApifyClient("APIFY_TOKEN")

## Replace "actor_id" with this Actor's ID from your own Apify account
run = client.actor("actor_id").call(run_input={
    "searchQueries": ["digital marketing"],
    "maxPosts": 25,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["pageName"], item["likes"], item["text"][:80])
```

*Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request.*

#### MCP integration for AI agents

Point your AI assistant at the Apify MCP server and it can find and call Facebook Posts Search Scraper on its own, directly from a prompt — no glue code, no scraping logic to write. Works with Claude Code, Cursor, and Windsurf.

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=socialdataapi/facebook-posts-search-scraper"
```

#### No-code tools (n8n, Make, LangChain)

In n8n, use the Apify node's "Run an Actor" operation, or the HTTP Request node pointed at the run-sync endpoint with your token. In Make, use the Apify app's "Run an Actor" module followed by "Get Dataset Items." In LangChain, install `langchain-apify` and point its `ApifyActorsTool` at this Actor once you have its id.

***

### Is it legal to scrape Facebook data?

Yes — scraping publicly visible Facebook posts is generally legal, since the same data is visible to any visitor without logging in. Facebook Posts Search Scraper returns only what's publicly available on facebook.com; it does not access anything behind a login wall. That said, a scraped row can include personal data — a page owner's name, and when contact lookup is on, an email, phone number, or address. GDPR and CCPA generally permit scraping public data, but storing and using it still requires a lawful basis and honoring deletion/access requests. Consult legal counsel if your use case involves bulk storage of personal data.

***

### Frequently asked questions

#### What fields does Facebook Posts Search Scraper return?

Every row includes page name, post text, likes, comments and shares, plus page identity and media fields. See [the data fields section](#what-data-can-i-extract-with-facebook-posts-search-scraper) for the full list.

#### Does Facebook Posts Search Scraper require a Facebook account or login?

No. Only public post data is extracted. No Facebook credentials are needed to run it.

#### What happens if a keyword returns no matching posts?

The run moves on to the next keyword, and the dataset simply has no rows for that one. A field Facebook genuinely didn't expose on a given post — for example likes or comments — comes back `null` rather than a fabricated zero.

#### Can I scrape multiple Facebook keywords at once?

Yes — `searchQueries` accepts an array of keywords, and each entry runs as its own independent search within the same run.

#### Does Facebook Posts Search Scraper work with Claude, ChatGPT, and other AI agent tools?

Yes — it's available as an MCP tool. Run `claude mcp add --transport http apify "https://mcp.apify.com?tools=socialdataapi/facebook-posts-search-scraper"` to register the Apify MCP server in Claude Code, Cursor, or Windsurf. Any agent that can call an HTTP endpoint can use the REST API directly.

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

Yes. Every response is typed, normalized JSON with consistent field names. No HTML parsing, no selectors — pass it straight to an LLM, index it into a vector store, or feed it to an agent tool with no transformation step.

#### What happens when Facebook changes its layout or updates its anti-bot system?

This actor is maintained and updated when Facebook changes its page layout or defenses — your calls keep returning the same JSON schema with no changes on your end.

#### Can I use Facebook Posts Search Scraper without managing proxies or browser infrastructure?

Yes. Proxy rotation and retry handling run on the actor's side, and it uses plain HTTP requests rather than a headless browser — you send one request and get structured JSON back, with no browser infrastructure to manage at all.

#### Which Facebook Posts Search Scraper fields work best for AI training data and RAG indexing?

For RAG indexing: the post text and page name give rich entity context. For training data: the likes, comments and shares counts, plus the publish timestamp, are the most structurally consistent fields across posts. All fields are typed primitives — strings, integers, booleans — no normalization needed.

***

### Your feedback

Found a bug or missing a field? Let us know from this Actor's page in the Apify Console. We read every report and ship fixes — this is how the normalized schema in the data fields section above stays accurate as Facebook's own pages change.

# Changelog

This Actor's version history is a separate document: https://apify.com/socialdataapi/facebook-posts-search-scraper/changelog.md

# Actor input Schema

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

One or more topics to search for on Facebook. Examples: football, cricket, tech news, recipes, travel. Each keyword runs its own search, so adding more keywords finds more posts.

## `maxPosts` (type: `integer`):

How many posts to collect per keyword, from 1 to 5,000. Default 10. Free plan: up to 20 posts per run (all keywords together) and 200 per month; paid plans have no limit.

## `postTimeRange` (type: `string`):

Only keep posts published within this recency window, genuinely enforced before a post is saved (not just logged). Leave as all time for no filter.

## `targetCountry` (type: `string`):

Bias the search toward a country's results. Leave blank for no country bias (default).

## `targetLanguage` (type: `string`):

Language for the search results. Leave blank to use the default (English).

## `enableContactLookup` (type: `boolean`):

When on, fetches each post's Facebook Page and extracts public email, phone, website, and address from the page's own intro/contact card, attached as contact on the row. Off by default (no extra page fetches). Fields that are genuinely not published are null, never fabricated.

## `maxCommentsPerPost` (type: `integer`):

Maximum number of top-level comments to fetch per post, saved to a separate comments dataset for this run that is not charged. Set to 0 (default) to disable comment fetching entirely.

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

Proxy used to fetch each discovered post or Page's HTML. Optional — Apify Proxy is used by default.

## Actor input object example

```json
{
  "searchQueries": [
    "football"
  ],
  "maxPosts": 10,
  "postTimeRange": "",
  "targetCountry": "",
  "targetLanguage": "",
  "enableContactLookup": false,
  "maxCommentsPerPost": 0,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped items in the Actor's default dataset.

# 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": [
        "football"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("socialdataapi/facebook-posts-search-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": ["football"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("socialdataapi/facebook-posts-search-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": [
    "football"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call socialdataapi/facebook-posts-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,socialdataapi/facebook-posts-search-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/kaYIAMNyJfdQ9yVOO/builds/oZlaQaphc08HO36J3/openapi.json
