# Deal Finder — Private Sellers Only (Marketplace + Groups) (`ferryman-labs/deal-finder-private-sellers`) Actor

Scrapes Facebook Marketplace and Facebook Groups, then filters to genuine private-seller deals: dealers removed, real asking price parsed, accessories dropped, region matched.

- **URL**: https://apify.com/ferryman-labs/deal-finder-private-sellers.md
- **Developed by:** [Stanley Li](https://apify.com/ferryman-labs) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% 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/actors/running/actors-in-store.md#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

## Deal Finder — Private Sellers Only

Every other Facebook scraper hands you **every post in the group**. You still have to read 200 dealer ads to find the three real people selling.

This one does the reading.

It scrapes **Facebook Marketplace** and **Facebook Groups**, then applies a judgment layer before anything reaches your dataset:

| Filter | What it does |
|---|---|
| **Dealer detection** | Drops shops and resellers. Trained on the language they actually use — *brand new, in stock, wholesale, warranty, model no., free shipping, 全新, 原廠, 現貨, 保固, 免運*. |
| **Real price parsing** | Pulls the actual asking price out of free text. A listing that says *"原價 6,500，便宜售"* returns **no price**, not 500. Discounted cards return the current price, not the strikethrough one. |
| **Accessory removal** | Searching `mattress` stops returning mattress cleaners and fitted sheets. Searching `iPhone` stops returning cases. |
| **Region matching** | Keep only what you can actually drive to. |

You are charged **only for listings that pass every filter**. Everything it throws away is free.

### Use cases

- **Resellers** — find under-priced private listings before the flippers do
- **Furniture / appliance flipping** — free giveaways and sub-$50 items, dealers removed
- **Second-hand phones & laptops** — private sellers only, accessories stripped out
- **Local buying agents** — one run covers several cities and groups

### Input

```json
{
  "keyword": "mattress",
  "marketplaceLocations": ["taipei", "taoyuan", "hsinchu"],
  "groupUrls": ["https://www.facebook.com/groups/1274386926940537"],
  "maxPrice": 3000,
  "regions": ["台北", "新北", "桃園"],
  "excludeDealers": true,
  "excludeAccessories": true
}
```

Give it Marketplace city slugs, group URLs, or both. Public Marketplace works without cookies; private groups need cookies from an account that is a member.

### Output

```json
{
  "source": "facebook_marketplace",
  "title": "二手單人床墊 九成新 自取",
  "price": 800,
  "isFree": false,
  "isDealer": false,
  "region": "桃園",
  "authorName": "",
  "url": "https://www.facebook.com/marketplace/item/...",
  "images": ["https://scontent..."],
  "passed": true,
  "filteredReasons": []
}
```

Set `includeFilteredOut: true` while you tune — every dropped item comes back with `filteredReasons` telling you exactly which rule removed it.

### Notes

- `i_user` cookies are stripped automatically. Browsing as a Facebook **Page** gets you blocked from Marketplace (`Pages can't use Marketplace`) — a failure mode that silently returns zero results.
- Group feeds are virtualised, so posts are collected **while scrolling**, not after. "See more" is expanded before reading, so post text is never truncated.
- Group post text contains invisible U+034F characters; they are cleaned before parsing.

### Pricing

| Event | Price |
|---|---|
| Actor start | $0.005 |
| Qualified deal | $0.002 |

A run over 3 cities and 2 groups that surfaces 15 real deals costs about **$0.035**.

# Actor input Schema

## `keyword` (type: `string`):

What you are hunting for, e.g. "mattress", "iPhone 13", "床墊", "冰箱".

## `marketplaceLocations` (type: `array`):

Facebook city slugs, e.g. taipei, taoyuan, hsinchu, losangeles. Leave empty to skip Marketplace.

## `groupUrls` (type: `array`):

Public group URLs. Private groups need cookies from an account that is a member.

## `maxPrice` (type: `integer`):

Skip listings above this. Leave empty for no cap.

## `minPrice` (type: `integer`):

Skip listings below this (filters out junk / accessories).

## `regions` (type: `array`):

Substring match against the listing text, e.g. 台北, 新北, 桃園, 新竹. Empty = anywhere.

## `excludeDealers` (type: `boolean`):

Drop listings that read like a shop: brand new, in stock, wholesale, warranty, model numbers, free shipping…

## `excludeAccessories` (type: `boolean`):

Drop cases, covers, spare parts, cleaning services and "wanted to buy" posts.

## `requirePrice` (type: `boolean`):

Only keep listings where an explicit asking price was found. "Original price 6,500" never counts as an asking price.

## `extraDealerWords` (type: `array`):

Your own dealer signals, added to the built-in list.

## `extraExcludeTerms` (type: `array`):

Anything else you never want to see.

## `maxItemsPerSource` (type: `integer`):

How many listings to read from each source before stopping. Higher = slower but more coverage.

## `includeFilteredOut` (type: `boolean`):

Useful for tuning: returns everything with filteredReasons explaining each drop.

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

Playwright-format cookies. Required for private groups. Public Marketplace works without them.

## `locale` (type: `string`):

Language of the pages being scraped, e.g. zh-TW, en-US. Affects how prices and dates are read.

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

Proxy used for scraping. Apify Proxy is recommended — Facebook blocks datacenter IPs quickly.

## Actor input object example

```json
{
  "keyword": "床墊",
  "marketplaceLocations": [
    "taipei",
    "taoyuan"
  ],
  "excludeDealers": true,
  "excludeAccessories": true,
  "requirePrice": false,
  "maxItemsPerSource": 40,
  "includeFilteredOut": false,
  "locale": "zh-TW",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `deals` (type: `string`):

Every listing that passed all filters: private seller, price parsed, region matched, accessories removed.

## `dealsCsv` (type: `string`):

Same rows as a spreadsheet you can open directly.

## `datasetView` (type: `string`):

Browse the results as a table, with the link to each original listing.

# 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 = {
    "keyword": "床墊",
    "marketplaceLocations": [
        "taipei",
        "taoyuan"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ferryman-labs/deal-finder-private-sellers").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 = {
    "keyword": "床墊",
    "marketplaceLocations": [
        "taipei",
        "taoyuan",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("ferryman-labs/deal-finder-private-sellers").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 '{
  "keyword": "床墊",
  "marketplaceLocations": [
    "taipei",
    "taoyuan"
  ]
}' |
apify call ferryman-labs/deal-finder-private-sellers --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ferryman-labs/deal-finder-private-sellers"
        }
    }
}
```

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/LSR2aJYiWcWrmZBBn/builds/Uw3x1Uz69JQ7AYKuk/openapi.json
