# Facebook Search Posts (`zacharysedillo31/facebook-lead-discovery-enhanced`) Actor

Search recent Facebook posts using configurable keywords, location UID, and time range. Returns clean, deduplicated post records with timestamps, contact details, source links, lead scoring, and optional screenshots.

- **URL**: https://apify.com/zacharysedillo31/facebook-lead-discovery-enhanced.md
- **Developed by:** [Z Sedillo](https://apify.com/zacharysedillo31) (community)
- **Categories:** Lead generation, Social media, Other
- **Stats:** 2 total users, 2 monthly users, 28.6% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Facebook Lead Discovery Enhanced

This is an original, self-contained Facebook browser crawler. It does **not** call another Apify Actor and does **not** use RapidAPI or any third-party search API.

The Actor launches Playwright Chromium, opens Facebook search pages directly, applies Facebook's current `location + recent_posts` filter combination, scrolls rendered results, extracts post data from the DOM, and saves real post-element screenshots. The requested rolling time window is then enforced exactly in code.

### Input

```json
{
  "searchKeyword": "opening soon, we are moving, relocating, new premises",
  "timeFrame": "24hrs",
  "resultMode": "allSearchMatches",
  "locationUID": "112483542097587",
  "maxPosts": 25,
  "screenshot": true,
  "maxScrolls": 20,
  "facebookCookies": [],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

`112483542097587` is the Facebook location UID used for the United Kingdom. Every accepted result is checked again against the exact rolling cutoff. Available windows are 1, 2, 6, 12, and 24 hours, plus 7 and 30 days.

`maxPosts` is a ceiling, not a guaranteed result count. The Actor exhausts the available rendered Facebook results up to `maxScrolls` and saves distinct posts with trustworthy timestamps inside the selected window.

`resultMode: "allSearchMatches"` maximizes output by retaining every in-range Facebook search result. Each row includes `qualifiedLead` and `leadScore`, so stronger opportunities can still be prioritized. Use `"qualifiedLeads"` to restore the stricter behavior that discards posts without an opening/moving lead signal.

The Actor requires 4 GB of run memory. Facebook's browser renderer can exceed 2 GB during deep result scrolling even when processed DOM rows are pruned; the Actor definition enforces the required allocation to prevent renderer crashes.

### Facebook access

Facebook frequently restricts post search to signed-in users. The Actor first attempts public access. If Facebook presents a login wall, provide your own session cookies through `facebookCookies`. These are applied only inside the run's private browser context.

Cookie example:

```json
[
  {
    "name": "c_user",
    "value": "YOUR_VALUE",
    "domain": ".facebook.com",
    "path": "/",
    "secure": true,
    "httpOnly": true,
    "sameSite": "None"
  },
  {
    "name": "xs",
    "value": "YOUR_VALUE",
    "domain": ".facebook.com",
    "path": "/",
    "secure": true,
    "httpOnly": true,
    "sameSite": "None"
  }
]
```

Enable an Apify proxy if Facebook blocks the cloud browser IP. Proxies and cookies are access configuration only—the lead data still comes directly from the rendered Facebook page.

### Output

Each accepted dataset row contains:

- Facebook page URL, page ID/name, and nullable metadata not exposed in search results
- Post ID, URL, type, raw timestamp, and normalized ISO timestamp
- Post text and external links
- Automatic contact extraction on every saved post from the expanded message, full rendered post card, link labels, `tel:` links, map links, UK phone formats, and probable UK addresses
- Automatic second-stage enrichment from each post author's Facebook profile About/contact page using the same signed-in browser session and proxy; repeated profiles are cached
- Easy primary contact fields (`phoneNumber`, `address`, and `contactDetailsFound`) plus the complete `detected_phone_numbers` and `detected_addresses` arrays

Every saved row contains these contact fields plus `contactSources`, `profileContactUrl`, and `contactEnrichmentStatus`. `phoneNumber` and `address` remain `null`, and their arrays remain empty, only when neither the post nor its public Facebook profile publishes that detail; the Actor never invents missing contact information. Set `enrichProfileContacts` to `false` only when faster runs are more important than profile-level enrichment.

- Matched keyword, detected opening/moving signals, score, and exact age
- Optional real PNG screenshot URL
- Cookie application status

The `OUTPUT` key-value-store record explicitly reports `externalActorCalls: 0` and `thirdPartyApiCalls: 0`.
Each search also reports extraction-gate metrics (rendered articles, post URLs, timestamps, timeframe, relevance, duplicates, and saved leads). A zero-result run stores a `ZERO_RESULTS_*.png` diagnostic screenshot instead of silently returning an unexplained empty dataset.
The summary includes `requestedMaxPosts`, `limitReached`, and `completionReason`, making it clear whether the requested ceiling was reached or Facebook's qualifying results were exhausted first.

### Run locally

Prerequisites: Node.js 22+, Apify CLI, and a locally installed Chromium browser compatible with Playwright.

```bash
npm install
npm test
apify run
```

### Deploy

```bash
apify login
apify push
```

# Actor input Schema

## `searchKeyword` (type: `string`):

Comma-separated phrases. Each phrase is searched separately and results are deduplicated.

## `timeFrame` (type: `string`):

The exact age limit applied after results are fetched.

## `resultMode` (type: `string`):

Save every timestamp-valid Facebook search result, or keep only posts that also pass the stricter business-lead scoring rules.

## `locationUID` (type: `string`):

Facebook location identifier. The default is the United Kingdom.

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

Upper limit on unique, in-range posts saved. The run can return fewer when Facebook exposes fewer matching posts; this value does not manufacture or guarantee that count.

## `screenshot` (type: `boolean`):

Save a real PNG screenshot of each accepted Facebook post element.

## `enrichProfileContacts` (type: `boolean`):

For every saved post, visit the author profile's Facebook About/contact page with the same browser session and merge public phone numbers and addresses into the result.

## `maxScrolls` (type: `integer`):

Stops direct Facebook scrolling after this many passes per search phrase.

## `facebookCookies` (type: `array`):

Your own Facebook session cookies as Playwright cookie objects. Public search is attempted without them first, but Facebook often requires sign-in.

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

Optional Apify proxy configuration used by the direct browser.

## Actor input object example

```json
{
  "searchKeyword": "opening soon, we are moving, relocating, new premises",
  "timeFrame": "24hrs",
  "resultMode": "allSearchMatches",
  "locationUID": "112483542097587",
  "maxPosts": 25,
  "screenshot": true,
  "enrichProfileContacts": true,
  "maxScrolls": 20,
  "facebookCookies": [],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Clean, deduplicated Facebook lead records that passed the exact rolling time filter.

## `evidence` (type: `string`):

Real PNG screenshots of accepted Facebook post elements plus access diagnostics.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("zacharysedillo31/facebook-lead-discovery-enhanced").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("zacharysedillo31/facebook-lead-discovery-enhanced").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call zacharysedillo31/facebook-lead-discovery-enhanced --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=zacharysedillo31/facebook-lead-discovery-enhanced",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/3i0GZCKQz43AsoYqn/builds/o9JLhs6dxpAgQDDrM/openapi.json
