# Facebook Marketplace Scraper - Prices & Price Drops, No Login (`cliqtomedia/facebook-marketplace`) Actor

Scrape Facebook Marketplace listings by city, keyword, category and price without login: title, price, location, photos, post date, plus condition, description and all photos on request. New-listing and price-drop monitoring, market price summary. No seller data.

- **URL**: https://apify.com/cliqtomedia/facebook-marketplace.md
- **Developed by:** [Cliqto Media](https://apify.com/cliqtomedia) (community)
- **Categories:** E-commerce, Real estate
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.62 / 1,000 listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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 Marketplace Scraper collects public Facebook Marketplace listings by city and search words, without a Facebook login, and returns one row per listing with the price, photos, location, delivery options and a market price comparison.

Use it to watch a local market, find new listings and price drops, or export Marketplace prices to a spreadsheet. The smallest run (Pattaya, "motorbike", 10 listings) takes under 10 seconds and costs about $0.017 on the Free plan.

[![Facebook Marketplace Scraper: city and search words in, listings with prices, new-listing and price-drop flags out, export to JSON or CSV](https://api.apify.com/v2/key-value-stores/5ZAH3jqwtgTbJtPKj/records/hero-20261101.png)](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)

### Table of contents

- [What it does](#what-it-does)
- [How it works](#how-it-works)
- [Quick start](#quick-start)
- [Use cases](#use-cases)
- [Input](#input)
- [Output](#output)
- [Pricing](#pricing)
- [Limits](#limits)
- [API, export and integrations](#api-export-and-integrations)
- [Troubleshooting](#troubleshooting)
- [FAQ](#faq)
- [Related Actors](#related-actors)
- [Support](#support)

### What it does

The Actor opens Facebook Marketplace as a logged-out visitor in the city you name, runs your search and saves the listings it finds: title, price (also in US dollars when Facebook shows it), photos, city, category, delivery options, posting time and a link to the listing. It can also open each listing page for the description, condition, exact distance and vehicle details.

For monitoring, it remembers what it saw before. A repeat run can return only new listings, or mark price drops, price rises and removed listings.

It never logs in and never saves seller names, profiles or contact details.

#### Good fit

- Watch a city for new listings of a product and get only the new ones on every scheduled run.
- Track price drops on used cars, motorbikes, phones or furniture you are following.
- Compare asking prices in one or several cities: every search gets a median price, and every listing shows how far below that median it is.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### How it works

1. You give a city and search words (or paste Marketplace links from your browser). Several cities and several search words are combined into separate searches.
2. The Actor reads the public Marketplace search pages for each search, applies your filters (price, condition, delivery, age, availability) and drops reposts of the same item. If you asked for details, it also opens each listing page.
3. It saves one Dataset row per listing, a market price summary per search (`MARKET_SUMMARY`) and a run report (`RUN_SUMMARY`) with the status of every search. In monitor mode it also stores what it saw, so the next run can find new listings and price changes.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### Quick start

[![Input form: box 1 is the City field, box 2 is Search words, box 3 is Max listings](https://api.apify.com/v2/key-value-stores/5ZAH3jqwtgTbJtPKj/records/quick-start-form-20261101.png)](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)

1. Open the **Input** tab. **City** is prefilled with `pattaya` (box 1). Any city name works, for example `london` or `los angeles`.
2. Keep **Search words** = `motorbike` or type your own (box 2).
3. Keep **Max listings** = `10` from the form (box 3). If you leave it empty, the Actor saves up to 50 listings per search.
4. Click **Start**.
5. Open the **Output** tab. Switch views with the tabs (box 1), check **Title**, **Price** and **Currency** (box 2) and **Below median %** (box 3).

   [![Output table: box 1 the view tabs, box 2 title, price and currency, box 3 percent below the search median](https://api.apify.com/v2/key-value-stores/5ZAH3jqwtgTbJtPKj/records/output-table-20261101.png)](https://api.apify.com/v2/key-value-stores/5ZAH3jqwtgTbJtPKj/records/output-table-20261101.png)

Expected result: 10 motorbike listings from Pattaya with prices in Thai baht, links and photos, in under 10 seconds.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### Use cases

| Buyer job | Input path | Output entity | Key fields | Next integration |
| --- | --- | --- | --- | --- |
| Export listings for a city and product | `city`, `query`, `maxItems` | Listing | `title`, `price`, `currency`, `url`, `postedAt` | CSV or Excel export |
| Get only new listings on a schedule | `onlyNew` + Apify schedule | New listing | `listingId`, `title`, `price`, `firstSeenAt` | Slack or Notion via `deliveryConnector` |
| Track price drops and removed listings | `trackChanges`, `monitorName` | Changed listing | `changeType`, `previousPrice`, `priceDropPercent` | Webhook or Slack |
| Find underpriced items | `query`, `priceMin`, `priceMax` | Listing with market comparison | `marketMedianPrice`, `belowMarketPercent` | Spreadsheet |
| Compare markets across cities | `cities`, `queries` | Market summary per search | `MARKET_SUMMARY`: `median`, `p25`, `p75`, `count` | API |
| Read full listing pages | `includeDetails` or `startUrls` with item links | Detailed listing | `description`, `condition`, `distanceKm`, `vehicle` | Database |

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### Input

#### Input fields

A run needs a place (`city`, `cities`, `locationId` or a Marketplace link) and a search word (`query`, `queries`) or a `category`. Everything else is optional.

| Field | Plain name | Type | Required | Default / prefill | Allowed values | Effect | Example | Recommendation |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| `city` | City | text | one place is required | prefill `pattaya` | city name | Where to search | `london` | Use the city name people use in English |
| `query` | Search words | text | `query` or `category` | prefill `motorbike` | any words | What to search for | `iphone 15` | Short words find more |
| `category` | Category | select | no | none | 18 Marketplace categories, e.g. `vehicles`, `electronics`, `propertyrentals` | Search inside one category | `vehicles` | Can be used without `query` |
| `priceMin`, `priceMax` | Price range | whole number | no | none | 0 or more, local currency | Keeps listings in this price range | `5000`, `30000` | Use the city's currency |
| `maxItems` | Max listings | whole number | no | default 50, prefill 10 | 1–5000 | Listings saved per search | `200` | Raise the run timeout for big runs |
| `onlyNew` | Only new listings | yes/no | no | `false` | | Returns only listings not seen in earlier runs | `true` | For scheduled runs |
| `trackChanges` | Track price drops and removals | yes/no | no | `false` | | Marks new, price-down, price-up and removed listings | `true` | For price watching |
| `includeUnchanged` | Include unchanged listings | yes/no | no | `false` | | With `trackChanges`, also saves listings that did not change | `true` | Only if you need the full list each time |
| `monitorName` | Monitor name | text | no | none | letters, digits, spaces, `-`, `_` | Keeps this monitor's memory apart | `pattaya-bikes` | Use one name per monitor |
| `dedupeReposts` | Skip reposts | yes/no | no | `true` | | Drops the same item posted again | `true` | Keep it on |
| `maxRemovedChecks` | Max removal checks | whole number | no | 20 | 0–200 | How many missing listings are checked before being marked removed | `50` | Each check is paid |
| `includeDetails` | Include details | yes/no | no | `false` | | Opens each listing page for description, condition, distance, vehicle data | `true` | Costs more per listing |
| `radiusKm` | Radius (km) | whole number | no | none | 1–500 | Keeps listings within this distance of the city | `20` | Turns on details |
| `condition` | Condition | list | no | any | `new`, `used_like_new`, `used_good`, `used_fair` | Item condition filter | `["new"]` | |
| `delivery` | Delivery | select | no | any | `local_pick_up`, `shipping` | Delivery filter | `shipping` | |
| `daysSinceListed` | Listed within | select | no | any | `1`, `7`, `30` days | Marketplace age filter | `7` | |
| `maxAgeHours` | Posted within (hours) | whole number | no | none | 1–8760 | Drops listings older than this | `48` | |
| `availability` | Availability | select | no | `available` | `available`, `sold` | Active or sold listings | `sold` | |
| `strictQuery` | Title must contain all words | yes/no | no | `false` | | Drops listings whose title lacks any of your words | `true` | Facebook search is loose |
| `sortBy` | Sort | select | no | `best_match` | `best_match`, `creation_time_descend`, `price_ascend`, `price_descend`, `distance_ascend` | Order Facebook returns | `creation_time_descend` | Newest first for monitors |
| `cities` | More cities | list | no | none | city names | Extra cities | `["bangkok", "chiang mai"]` | Each city × word is one search |
| `queries` | More search words | list | no | none | words | Extra search words | `["honda", "yamaha"]` | |
| `startUrls` | Marketplace links | list | no | none | facebook.com/marketplace search, category or item links | Runs your browser links; filters in the link are kept | `https://www.facebook.com/marketplace/bangkok/search/?query=honda` | Easiest way to copy a search |
| `locationId` | Location id | text | no | none | numeric id or city slug from a Marketplace link | Exact Marketplace location | `112306758786227` | When a city name is ambiguous |
| `outputFormat` | Row format | select | no | `flat` | `flat`, `nested` | Flat columns or grouped objects | `nested` | `flat` is best for spreadsheets |
| `deliveryConnector` | Send results to | MCP connector | no | none | your connector | Posts a short summary after the run | | See below |
| `deliveryTarget` | Notion page or channel | text | no | none | Notion page link or Slack channel ID | Where the summary goes | | |

Input field names used by other Marketplace scrapers also work: `urls` for `startUrls`, `resultsLimit` for `maxItems`, `includeListingDetails` or `getListingDetails` for `includeDetails`.

#### Interacting settings

| When | Input A | Input B | Effective behavior | Example | Cost/result effect |
| --- | --- | --- | --- | --- | --- |
| Several places and words | `cities` | `queries` | Every city × word pair is a separate search, 50 at most | 3 cities × 2 words = 6 searches | One search fee each; `maxItems` applies per search |
| Both monitor options | `onlyNew` | `trackChanges` | `trackChanges` wins: known listings are compared, not dropped | | Unchanged listings are paid as cheap checks |
| Radius filter | `radiusKm` | `includeDetails` | Radius needs the listing page, so details are read | `radiusKm: 20` | Listings outside the radius are paid as page checks |
| Link with filters | `startUrls` | `query`, `priceMin`… | Filters written in the link are used for that link | `…/search/?query=honda&maxPrice=50000` | |
| Item links | `startUrls` with `/marketplace/item/…` | | Each item page is read, up to 500 per run | | Charged as detailed listings |

#### Input examples

##### Smallest run

```json
{
  "city": "pattaya",
  "query": "motorbike",
  "maxItems": 10
}
```

Expected behavior: one search in Pattaya.
Expected output: 10 listings with `title`, `price`, `currency`, `url`, `primaryImage`.
Limit or cost note: under 10 seconds and $0.017 on Free.

##### New listings every morning

```json
{
  "city": "los angeles",
  "query": "couch",
  "maxItems": 100,
  "onlyNew": true,
  "sortBy": "creation_time_descend",
  "monitorName": "la-couches"
}
```

Expected behavior: the first run saves up to 100 listings; later runs save only listings that were not there before.
Expected output: new listings with `firstSeenAt`.
Limit or cost note: listings already seen are skipped free; you pay the search fee and the new rows.

##### Price watch with details

```json
{
  "city": "bangkok",
  "query": "iphone 15",
  "strictQuery": true,
  "trackChanges": true,
  "includeDetails": true,
  "maxItems": 50,
  "monitorName": "bkk-iphone"
}
```

Expected behavior: saves listings with description and condition; later runs mark `priceDown`, `priceUp`, `new` and `removed`.
Expected output: `changeType`, `previousPrice`, `priceDropPercent`, `condition`, `description`.
Limit or cost note: detailed listings cost more; unchanged listings are paid as checks only.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### Output

#### Output fields

These are the flat row fields (`outputFormat: "flat"`). With `nested` the same data is grouped into objects such as `price` and `market`.

| Field | Meaning | Type | Can be empty? | Example / enum | Source / notes |
| --- | --- | --- | --- | --- | --- |
| `listingId` | Marketplace listing id | text | no | `1347713167500771` | |
| `url` | Link to the listing | text | no | `https://www.facebook.com/marketplace/item/…/` | |
| `title` | Listing title | text | no | `2012 Honda Click 125` | As written by the seller |
| `price` | Asking price | number | yes | `18900` | `0` when Facebook shows ฿0 (free or "ask for price"); placeholders like `9999999` are kept as the seller wrote them |
| `currency` | Currency code | text | yes | `THB` | |
| `priceText` | Price as shown | text | yes | `฿18,900` | |
| `priceUsd` | Price in US dollars | number | yes | `556.2` | Only when Facebook shows it |
| `originalPrice` | Earlier price shown by Facebook | number | yes | `21000` | When the seller lowered it |
| `location`, `city`, `state`, `country` | Listing place | text | yes | `Pattaya`, `TH` | |
| `latitude`, `longitude`, `distanceKm` | Coordinates and distance from the searched city | number | yes | `9.7` | With details |
| `category`, `categoryId` | Marketplace category | text | yes | `vehicles` | `category` is empty when Facebook uses an id outside the 18 known categories; `categoryId` is still set |
| `condition` | Item condition | text | yes | `used_like_new` | With details |
| `deliveryTypes`, `shippingOffered` | Pickup or shipping | list / yes-no | yes | `["IN_PERSON"]` | |
| `postedAt` | When it was listed | date-time | yes | `2026-06-28T11:02:15.000Z` | |
| `status` | Listing status | text | no | `active`, `sold`, `pending`, `removed` | |
| `subtitle` | Extra line under the title | text | yes | `20K km` | Often mileage for vehicles |
| `primaryImage`, `images`, `hasVideo` | Photos | link / list / yes-no | yes | | Facebook image links expire after some days |
| `description` | Listing text | text | yes | | With details |
| `vehicle` | Make, model, mileage, transmission, fuel, colours | object | yes | `{"make":"Honda","model":"Forza",…}` | Vehicle listings with details |
| `changeType` | What changed since the last run | text | yes | `new`, `priceDown`, `priceUp`, `removed`, `stillActive` | Monitor mode only |
| `firstSeenAt`, `previousPrice`, `priceDropPercent` | Monitor history | date-time / number | yes | `8.2` | Monitor mode only |
| `marketMedianPrice` | Median price of this search | number | yes | `26900` | From the listings read in the search. Prices of 0 and 1, placeholders like `9999999` and prices over 50x the median are left out |
| `belowMarketPercent` | How far below the median | number | yes | `29.7` | Only when at least 5 priced listings; empty for prices left out of the median. Negative means the price is above the median |
| `isRepost` | Looks like a repost of an earlier item | yes/no | yes | `null` | Only in monitor mode (`onlyNew` or `trackChanges`) |
| `searchQuery`, `searchLocation`, `searchCategory` | Which search found it | text | yes | `motorbike`, `Pattaya` | |
| `detailsStatus` | Was the listing page read | text | no | `not_requested`, `ok`, `gone`, `failed` | |
| `fetchedAt` | When the row was saved | date-time | no | | |

#### Output entities and surfaces

| Situation | Dataset/API/KVS/live view | Result shape | User action |
| --- | --- | --- | --- |
| Normal item | Dataset, views **Listings**, **With details**, **Changes** | One row per listing | Open, export or filter |
| Market prices | Key-value store `MARKET_SUMMARY` | Per search: currency, count, min, p25, median, p75, max, mean | Compare cities or products |
| Domain-empty result | Dataset empty, `RUN_SUMMARY` status `NO_RESULTS` | Search list with `found: 0` | Try other words or a bigger city |
| Partial result | Rows saved, `RUN_SUMMARY` status `PARTIAL` with a reason (`MAX_ITEMS`, `TIME_LIMIT`, `CHARGE_LIMIT`, `LOGIN_WALL`, `UNKNOWN_LOCATION`, `SOURCE_ERROR`) | Saved rows are kept | Read the reason, then raise the limit or retry |
| Technical failure | `RUN_SUMMARY` status `ERROR` or `INVALID_INPUT`, run marked failed | Message in the summary and log | Fix the input or retry later |

#### Output example

```json
{
  "listingId": "1347713167500771",
  "url": "https://www.facebook.com/marketplace/item/1347713167500771/",
  "title": "2012 Honda Click 125",
  "price": 18900,
  "currency": "THB",
  "priceText": "฿18,900",
  "priceUsd": 556.2,
  "originalPrice": null,
  "city": "Pattaya",
  "country": "TH",
  "category": "vehicles",
  "condition": null,
  "deliveryTypes": ["IN_PERSON"],
  "postedAt": "2026-06-28T11:02:15.000Z",
  "status": "active",
  "subtitle": "20K km",
  "primaryImage": "https://scontent…fbcdn.net/…jpg",
  "description": null,
  "changeType": null,
  "marketMedianPrice": 26900,
  "belowMarketPercent": 29.7,
  "isRepost": null,
  "searchQuery": "motorbike",
  "searchLocation": "Pattaya",
  "detailsStatus": "not_requested"
}
```

This trimmed row comes from the smallest run above. `null` means Marketplace did not show that value on the search page: `condition`, `description` and coordinates come only with `includeDetails`, and monitor fields only with `onlyNew` or `trackChanges`.

#### Send results to Slack or Notion

Pick your connector in the optional `deliveryConnector` field. After the run saves its data, the Actor posts a short summary (up to 25 rows and a link to the full dataset) there. Put a Notion page link or a Slack channel ID in `deliveryTarget`: in Notion every run is added on top of that one page, so your workspace does not fill up with new pages. A delivery error never fails the run and costs nothing extra. Connect a service once in Apify Console → MCP connectors.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### Pricing

#### Pricing unit

You pay per event. Apify platform usage is included: there is no separate compute charge and no start fee.

| Event | When it is charged | Free | Bronze | Silver | Gold and up |
| --- | --- | ---: | ---: | ---: | ---: |
| `search` | Once per search (city × search words), after Facebook answered with a results page | $0.008 | $0.0072 | $0.0064 | $0.0056 |
| `listing` | Each saved listing from search pages | $0.00089 | $0.000801 | $0.000712 | $0.000623 |
| `listing-details` | Each saved listing with its page read (instead of `listing`, not on top) | $0.008 | $0.0072 | $0.0064 | $0.0056 |
| `listing-checked` | Each unchanged listing confirmed in `trackChanges` mode | $0.0004 | $0.00036 | $0.00032 | $0.00028 |
| `listing-page-check` | Each listing page Facebook answered that is not saved: a removal check, or a listing outside `radiusKm` | $0.008 | $0.0072 | $0.0064 | $0.0056 |

- A search that finds nothing, or where no listing passes your filters, costs only the search fee ($0.008 on Free).
- With `onlyNew`, listings you already have are skipped free: a repeat run with nothing new costs only the search fee.
- Removed listings found by a removal check are saved free; the check itself is paid.
- Invalid input fails before any search and costs nothing.
- A search that Facebook refused (login page, block, no answer after retries) or a city Facebook did not accept costs nothing.
- If your run's maximum charge is reached, the Actor stops, keeps what it saved and reports `PARTIAL` with `CHARGE_LIMIT`.

#### Cost examples

Measured on real runs, Free plan prices.

| Scenario | Input scope | Expected item/event count | Base charge | Optional charge | Stop/cap behavior |
| --- | --- | ---: | ---: | ---: | --- |
| Smallest run | Pattaya, "motorbike", 10 listings | 1 search + 10 listings | $0.017 | none | Under 10 s |
| Nothing found | Nonsense search words | 1 search | $0.008 | none | `NO_RESULTS` |
| Medium export | Los Angeles, "couch", 200 listings | 1 search + 200 listings | $0.186 | none | About 15 s |
| Details | 20 listings with `includeDetails` | 1 search + 20 detailed | $0.168 | none | About 25 s |
| Monitor repeat | `onlyNew`, 10 seen skipped, 10 new saved | 1 search + 10 listings | $0.017 | none | Seen listings free |
| Price watch, nothing changed | `trackChanges`, 98 known listings | 1 search + 98 checks | $0.047 | removal checks if any | About 15 s |
| Large export | 3 cities × 2 words, 1000 each | 6 searches + 3227 listings | $2.92 | none | About 8 min; raise the timeout |

One search with N listings, by plan:

| Plan | 10 listings | 100 listings | 1000 listings |
| --- | ---: | ---: | ---: |
| Free | $0.017 | $0.097 | $0.898 |
| Bronze | $0.015 | $0.087 | $0.808 |
| Silver | $0.014 | $0.078 | $0.718 |
| Gold and up | $0.012 | $0.068 | $0.629 |

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### Limits

- Public listings only. The Actor never logs in, so anything Facebook shows only to signed-in users is not available, and no seller name, profile or contact is saved.
- Up to 50 searches per run (cities × search words), up to 5000 listings per search, up to 500 item links per run.
- The default run timeout is 5 minutes, enough for a few hundred listings. For thousands, raise the timeout in the run options; one run works for 30 minutes at most. When time runs out, saved rows are kept and the search is marked `PARTIAL` with `TIME_LIMIT`.
- Facebook decides which listings appear and in what order. A search can show fewer listings than the city has, and rows are not strictly sorted even with `sortBy`.
- `priceUsd` appears only when Facebook shows a dollar price. Photo links are Facebook links that expire after some days; download photos you want to keep.
- Monitor memory keeps up to 5000 listings per search, in a store named `facebook-marketplace-state` in your own Apify account.
- Description, condition, exact distance and vehicle details need `includeDetails` (or `radiusKm`), which costs more per listing.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### API, export and integrations

- **API:** start a run with the input JSON above through the Apify API or client libraries; read rows from the run's Dataset.
- **Export:** download the Dataset as JSON, CSV, Excel, XML or HTML from the **Output** tab or the API.
- **Scheduling:** create an Apify schedule with `onlyNew` or `trackChanges` and a `monitorName`; each run continues from the previous one.
- **Webhooks / no-code:** use an Apify webhook on run success to pass the Dataset to Make, Zapier, n8n or your own endpoint. `changeType` tells the next step what happened.
- **Slack / Notion:** set `deliveryConnector` and `deliveryTarget` (see [Send results to Slack or Notion](#send-results-to-slack-or-notion)).

#### Use with AI agents (MCP)

- MCP server URL with only this Actor: `https://mcp.apify.com?tools=cliqtomedia/facebook-marketplace`.
- Smallest useful input: `{"city": "pattaya", "query": "motorbike", "maxItems": 10}`.
- Key output fields: `title` (what is sold), `price` and `currency` (asking price), `url` (listing link), `belowMarketPercent` (how much cheaper than the search median), `changeType` (new or changed, in monitor mode).
- A small run takes under 10 seconds and costs about $0.017 on Free. Keep `maxItems` small for quick answers; 50 searches per run at most.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### Troubleshooting

#### No listings

Symptom: the run succeeds, the Dataset is empty, `RUN_SUMMARY` says `NO_RESULTS`.
Likely reason: Facebook has no listings for these words in this city, or your filters (`strictQuery`, price, condition, `maxAgeHours`) removed all of them.
Check: `searches[].found` in `RUN_SUMMARY` shows how many listings were read before filters.
Action: use shorter or English search words, turn off `strictQuery`, widen the price range or try a bigger city.

#### City not found

Symptom: the search is marked `UNKNOWN_LOCATION`.
Likely reason: Facebook has no Marketplace page under this city name.
Check: open Marketplace in your browser, pick the city and look at the link.
Action: paste that link into `startUrls`, or copy the number or slug after `/marketplace/` into `locationId`.

#### Run stopped early

Symptom: `PARTIAL` with `TIME_LIMIT`.
Likely reason: the run timeout (5 minutes by default) ended before all listings were read.
Check: `RUN_SUMMARY.searches[].pagesRead` and the run duration.
Action: raise the timeout in the run options, lower `maxItems` or split the cities into several runs. Saved rows are kept.

#### Charge limit reached

Symptom: `PARTIAL` with `CHARGE_LIMIT`.
Likely reason: the maximum cost per run you set was reached.
Check: the run's charged events.
Action: raise the maximum charge or ask for fewer listings.

#### Facebook asked to log in

Symptom: `PARTIAL` or `ERROR` with `LOGIN_WALL`.
Likely reason: Facebook showed a login page instead of listings for this request.
Check: the run log names the search.
Action: run again later. The Actor never logs in, so it cannot get past this page.

#### Input rejected

Symptom: the run fails at once with `INVALID_INPUT`.
Likely reason: no place, no search word or category, a non-Marketplace link, or more than 50 searches.
Check: the message in the run log, for example "Add a search word (query) or a category".
Action: fix the field named in the message. Invalid runs cost nothing.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### FAQ

#### Do I need a Facebook account or cookies?

No. The Actor reads Marketplace as a logged-out visitor. Do not give it your cookies or password.

#### Why is my run empty, and do I pay for it?

Facebook found nothing, or your filters removed everything. You pay only the search fee ($0.008 on Free). `RUN_SUMMARY` shows how many listings were read before filters.

#### Does it return every listing in the city?

No. It returns what Facebook shows a logged-out visitor for your search, up to `maxItems`. Use several search words or categories to cover more.

#### How do I get only new listings every day?

Turn on `onlyNew`, give the monitor a `monitorName` and run it on an Apify schedule. Listings you already have are skipped free.

#### Can I get seller names or phone numbers?

No. Seller data is never saved.

#### Which countries work?

Any city where Facebook Marketplace works. Prices come in the local currency, with `priceUsd` when Facebook shows it.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### Related Actors

- [Craigslist Scraper](https://apify.com/cliqtomedia/craigslist-scraper) — the same kind of local listings and prices from Craigslist.
- [OLX Listings Scraper](https://apify.com/cliqtomedia/olx-listings-scraper) — classified listings from OLX in Poland, Ukraine, Romania and more.
- [eBay Sold Listings Scraper](https://apify.com/cliqtomedia/ebay-sold-listings) — sold prices on eBay, to check what an item really sells for.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

### Support

For a bug, question or feature request, open the Actor's **Issues** tab on Apify. Include the run ID, your input (without private data) and the status from `RUN_SUMMARY`. Never send tokens, cookies or passwords.

> **👉 [Try it now: open the input form](https://console.apify.com/actors/zoHkKY005UgTz8EL9/input)**

# Changelog

This Actor's version history is a separate document: https://apify.com/cliqtomedia/facebook-marketplace/changelog.md

# Actor input Schema

## `city` (type: `string`):

City to search, as text: "Pattaya", "Chiang Mai", "New York", "London, GB". Add a country code when a name exists in several countries. A Marketplace city slug ("nyc") or numeric location id also works.

## `query` (type: `string`):

What to look for, as you would type it in Marketplace search, e.g. "motorbike", "iphone 15", "sofa". Leave empty to browse a whole category.

## `category` (type: `string`):

Marketplace category. With search words it narrows the search; without them the whole category of the city is listed.

## `priceMin` (type: `integer`):

Lowest price in the local currency of the city (baht in Pattaya, dollars in New York).

## `priceMax` (type: `integer`):

Highest price in the local currency of the city.

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

Listings to save per search (each city × search word is one search). You pay one small search fee per search plus each saved listing; a search that stops early costs less.

## `onlyNew` (type: `boolean`):

Save only listings this search has not returned before. Run it on a schedule to get each new listing once. Reposts of an old listing under a new id are skipped too.

## `trackChanges` (type: `boolean`):

Compare with the previous run of the same search: each row gets changeType new, priceDown or priceUp with previousPrice and priceDropPercent; listings that disappeared and are confirmed sold or deleted come as removed. Unchanged listings are left out unless you turn on the next option; each one left out is charged as a cheap listing check.

## `includeUnchanged` (type: `boolean`):

With price tracking, also save listings that did not change (changeType stillActive).

## `monitorName` (type: `string`):

Optional name to keep this monitor's memory apart from other runs of the same search (letters, digits, "-", "\_").

## `dedupeReposts` (type: `boolean`):

Treat a listing with the same title, price and city as one already seen as a repost: marked isRepost, and skipped in only-new mode.

## `maxRemovedChecks` (type: `integer`):

How many disappeared listings to open per search to confirm they were sold or deleted. Each check is charged as a listing page check; removed rows themselves are free. 0 turns the check off.

## `includeDetails` (type: `boolean`):

Open each listing page for condition, full description, all photos, exact position, delivery and vehicle data (make, model, mileage). Charged as a detailed listing.

## `radiusKm` (type: `integer`):

Keep only listings within this distance of the city centre. Reads each listing page for its position, so rows are detailed listings; pages outside the radius are charged as listing page checks.

## `condition` (type: `array`):

Only listings in these conditions.

## `delivery` (type: `string`):

Only listings with this delivery method.

## `daysSinceListed` (type: `string`):

Only listings posted recently.

## `maxAgeHours` (type: `integer`):

Keep only listings posted at most this many hours ago, by the posting time Facebook shows. Finer than "Listed within"; listings without a posting time are kept.

## `availability` (type: `string`):

Sold asks Facebook for listings already marked sold, for example to see what sold and at what price.

## `strictQuery` (type: `boolean`):

Facebook also returns loosely related listings. Turn this on to keep only listings whose title contains every word of the search query.

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

Order of the first page. To go past one page the Actor also reads other orders and price bands, so the dataset is not strictly sorted.

## `cities` (type: `array`):

Extra cities, searched with the same words and filters. Up to 50 searches per run (cities × search words).

## `queries` (type: `array`):

Extra search words; each is searched in every city.

## `startUrls` (type: `array`):

Paste Marketplace links from your browser: a search (facebook.com/marketplace/bangkok/search/?query=honda), a category page, or a single listing (facebook.com/marketplace/item/…). Filters in the link are kept.

## `locationId` (type: `string`):

Marketplace location id or slug from a Marketplace link, if you prefer it to a city name.

## `outputFormat` (type: `string`):

Flat rows suit spreadsheets; nested rows group price, location, media, monitoring and market fields.

## `deliveryConnector` (type: `string`):

Your Slack, Notion or other MCP connector. After the run the Actor posts a short summary there. Connect services once in Apify Console → MCP connectors.

## `deliveryTarget` (type: `string`):

Where to post the summary: a Notion page link (each run is added on top of that page) or a Slack channel ID. Leave empty to let the connector decide.

## Actor input object example

```json
{
  "city": "pattaya",
  "query": "motorbike",
  "maxItems": 10,
  "onlyNew": false,
  "trackChanges": false,
  "includeUnchanged": false,
  "dedupeReposts": true,
  "maxRemovedChecks": 20,
  "includeDetails": false,
  "availability": "available",
  "strictQuery": false,
  "sortBy": "best_match",
  "outputFormat": "flat"
}
```

# Actor output Schema

## `listings` (type: `string`):

Listings as a table.

## `listingsWithDetails` (type: `string`):

Condition, description, photos and vehicle data (with Include details).

## `changes` (type: `string`):

Monitoring rows (with Track price drops).

## `marketSummary` (type: `string`):

Count, min, median, quartiles and max price per search.

## `runSummary` (type: `string`):

Status, reason, per-search counts and charged listings.

# 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 = {
    "city": "pattaya",
    "query": "motorbike",
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("cliqtomedia/facebook-marketplace").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 = {
    "city": "pattaya",
    "query": "motorbike",
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("cliqtomedia/facebook-marketplace").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 '{
  "city": "pattaya",
  "query": "motorbike",
  "maxItems": 10
}' |
apify call cliqtomedia/facebook-marketplace --silent --output-dataset

```

## MCP server setup

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

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/zoHkKY005UgTz8EL9/builds/ZXOJeb2FkXlZIQck8/openapi.json
