# Facebook Marketplace Scraper – Listings, Prices & Sellers (`scrapingmonkey/facebook-marketplace-scraper`) Actor

Scrape Facebook Marketplace by keyword, location, category, or URL. Extract prices, descriptions, photos, seller data, vehicles, status, and changes.

- **URL**: https://apify.com/scrapingmonkey/facebook-marketplace-scraper.md
- **Developed by:** [ScrapingMonkey](https://apify.com/scrapingmonkey) (community)
- **Categories:** E-commerce, Lead generation, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 search 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/platform/actors/running/actors-in-store#pay-per-event

## 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 Marketplace Scraper - Search, Listing Details and Price Monitoring

Collect public Facebook Marketplace listings by keyword, location, category, or URL, enrich them with item details, and monitor price or availability changes in a clean Apify dataset.

- Search multiple products and Marketplace locations in one run
- Follow public cursor pagination instead of stopping at the first page
- Extract prices, descriptions, status flags, photos, public seller fields, attributes, and vehicle data when exposed
- Accept search, category, location, and individual item URLs
- Recheck listing availability and emit only new or changed records on scheduled runs
- Continue past individual unavailable or blocked targets and report them in `RUN_SUMMARY`
- Use Apify Residential Proxy automatically; no Facebook account, cookies, browser, or proxy setup is required
- Export results to JSON, CSV, Excel, XML, or access them through the Apify API

### What can you do with this Actor?

| Mode | Input | Output | Best for |
| --- | --- | --- | --- |
| `search` | Keywords and a Marketplace location | Paginated listing rows | Product research and lead discovery |
| `browse` | Search, category, or location URLs | Listings from the supplied pages | Reusing URLs prepared on Facebook Marketplace |
| `details` | Listing IDs or item URLs | Rich public listing details | Catalog enrichment and one-off lookups |
| `status` | Listing IDs or item URLs | Current public price and availability | Inventory and sold-status checks |
| `monitor` | Searches, item IDs, or URLs | Only new or changed rows | Scheduled price and availability monitoring |
| `auto` | Mixed Marketplace URLs and IDs | Automatically routed results | Batch processing heterogeneous inputs |

One run uses one selected mode. You can batch multiple keywords, URLs, or IDs inside that mode. Set `includeDetails` in search or browse mode to merge detail enrichment into each discovered listing row.

### Quick start

1. Open the Actor and click **Try for free**.
2. Keep `search` mode and enter one or more product keywords.
3. Set the Marketplace location and result limit.
4. Click **Start**.
5. Preview the single **Results** table or download it in your preferred format.

The default input searches for bicycles in New York and returns a small useful dataset without additional setup.

### Input examples

#### Search public listings

```json
{
  "mode": "search",
  "searchTerms": ["used bicycle", "mountain bike"],
  "location": "newyork",
  "maxItems": 50,
  "maxPages": 5,
  "includeDetails": false
}
```

`maxItems` applies to each search input. One dataset row represents one unique Marketplace listing.

#### Browse copied Marketplace URLs

```json
{
  "mode": "browse",
  "startUrls": [
    {"url": "https://www.facebook.com/marketplace/newyork/vehicles/"},
    {"url": "https://www.facebook.com/marketplace/newyork/search?query=camera"}
  ],
  "maxItems": 100,
  "maxPages": 10
}
```

#### Extract listing details

```json
{
  "mode": "details",
  "listingIds": [
    "2239956220131017",
    "https://www.facebook.com/marketplace/item/967043349730698/"
  ],
  "includeMedia": true,
  "includeSeller": true,
  "includeVehicleDetails": true
}
```

#### Check listing status

```json
{
  "mode": "status",
  "listingIds": ["2239956220131017", "967043349730698"]
}
```

#### Monitor new listings and changes

```json
{
  "mode": "monitor",
  "searchTerms": ["road bike"],
  "location": "newyork",
  "maxItems": 100,
  "monitorMode": "newAndChanged",
  "monitorKey": "nyc-road-bikes"
}
```

#### Auto-detect mixed URLs

```json
{
  "mode": "auto",
  "startUrls": [
    {"url": "https://www.facebook.com/marketplace/newyork/search?query=laptop"},
    {"url": "https://www.facebook.com/marketplace/item/2239956220131017/"}
  ],
  "maxItems": 25
}
```

#### Search with filters

```json
{
  "mode": "search",
  "searchTerms": ["camera"],
  "location": "newyork",
  "radiusKm": 40,
  "minPrice": 100,
  "maxPrice": 900,
  "sortBy": "price_ascend",
  "conditions": ["used_like_new", "used_good"],
  "deliveryMethods": ["local_pick_up"],
  "availability": "in_stock",
  "dateListed": "7",
  "exactMatch": false,
  "maxItems": 100
}
```

### Complete output example

Every emitted listing and status record has the same fixed set of **45 top-level fields**. Fields that do not apply to a listing are returned as `null` or an empty array; keys are not hidden in a separate “All fields” view. Objects such as `location`, `seller`, `attributes`, `vehicle`, and optional `raw` preserve source-controlled public subfields, so their internal keys can vary by listing category and Facebook's current response.

#### Complete listing/status row - 45 top-level fields

```json
{
  "recordType": "listing",
  "sourceMode": "search",
  "sourceTarget": "https://www.facebook.com/marketplace/newyork/search?query=bicycle",
  "sourceUrl": "https://www.facebook.com/marketplace/newyork/search?query=bicycle",
  "sourceEndpoints": [
    "https://www.facebook.com/marketplace/newyork/search?query=bicycle",
    "https://www.facebook.com/api/graphql/"
  ],
  "id": "2239956220131017",
  "url": "https://www.facebook.com/marketplace/item/2239956220131017/",
  "title": "Road bicycle",
  "description": "Public listing description.",
  "price": {
    "amount": "350.00",
    "currency": "USD",
    "formatted_amount": "$350"
  },
  "priceAmount": 350.0,
  "priceCurrency": "USD",
  "priceText": "$350",
  "strikethroughPrice": null,
  "location": {
    "latitude": 40.7128,
    "longitude": -74.006,
    "reverse_geocode": {
      "city": "New York",
      "state": "New York"
    }
  },
  "locationText": "New York, New York",
  "latitude": 40.7128,
  "longitude": -74.006,
  "createdAtUnix": 1786406400,
  "createdAt": "2026-08-11T00:00:00+00:00",
  "categoryId": "807311116002614",
  "categoryName": "Bicycles",
  "condition": "used_good",
  "inventoryCount": 1,
  "deliveryTypes": ["IN_PERSON"],
  "isLive": true,
  "isPending": false,
  "isSold": false,
  "isHidden": false,
  "availability": "live",
  "primaryPhotoUrl": "https://scontent.example/public-primary.jpg",
  "photoUrls": [
    "https://scontent.example/public-primary.jpg",
    "https://scontent.example/public-secondary.jpg"
  ],
  "videoUrls": [],
  "seller": {
    "id": "100012345678901",
    "name": "Public seller name"
  },
  "sellerName": "Public seller name",
  "sellerId": "100012345678901",
  "attributes": [
    {
      "attribute_name": "Condition",
      "value": "Used - good"
    }
  ],
  "vehicle": null,
  "shipping": {
    "offered": false,
    "profile": null,
    "deliveryData": null,
    "formattedPrice": null,
    "estimatedWindow": null
  },
  "detailWarning": null,
  "monitorStatus": null,
  "changedFields": null,
  "previousCapturedAt": null,
  "capturedAt": "2026-08-13T10:15:30.000000+00:00",
  "raw": null
}
```

In `status` mode, `recordType` is `listingStatus`. When monitoring is enabled, `monitorStatus` is `new` or `changed`, `changedFields` lists changed top-level keys, and `previousCapturedAt` contains the prior observation time. `raw` is `null` unless `includeRaw` is enabled. Unavailable inputs and request failures do not create error rows and are not charged; their categories appear in `RUN_SUMMARY`.

### What data can you extract?

| Category | Fields |
| --- | --- |
| Record and provenance | `recordType`, `sourceMode`, `sourceTarget`, `sourceUrl`, `sourceEndpoints`, `capturedAt` |
| Identity and content | `id`, `url`, `title`, `description` |
| Price | `price`, `priceAmount`, `priceCurrency`, `priceText`, `strikethroughPrice` |
| Location and time | `location`, `locationText`, `latitude`, `longitude`, `createdAtUnix`, `createdAt` |
| Classification | `categoryId`, `categoryName`, `condition`, `attributes`, `vehicle` |
| Inventory and delivery | `inventoryCount`, `deliveryTypes`, `shipping`, `isLive`, `isPending`, `isSold`, `isHidden`, `availability` |
| Media | `primaryPhotoUrl`, `photoUrls`, `videoUrls` |
| Public seller subset | `seller`, `sellerName`, `sellerId` |
| Enrichment and monitoring | `detailWarning`, `monitorStatus`, `changedFields`, `previousCapturedAt` |
| Optional source data | `raw` |

### Input parameters

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `mode` | string | Yes | `search` | `search`, `browse`, `details`, `status`, `monitor`, or `auto` |
| `searchTerms` | string\[] | In search/monitor mode | `['bicycle']` when no URL is supplied | Product keywords; each becomes a separate search input |
| `startUrls` | request\[] | In browse/auto mode | - | Marketplace search, category, location, or item URLs |
| `listingIds` | string\[] | In details/status mode | - | Numeric listing IDs or item URLs |
| `location` | string | No | `newyork` | Marketplace location slug used to build searches |
| `radiusKm` | integer | No | `65` | Search radius from 1 to 500 km |
| `minPrice` | number | No | - | Minimum displayed price |
| `maxPrice` | number | No | - | Maximum displayed price |
| `sortBy` | string | No | `best_match` | `best_match`, `creation_time_descend`, `price_ascend`, `price_descend`, or `distance_ascend` |
| `conditions` | string\[] | No | `[]` | Marketplace condition values such as `new`, `used_like_new`, `used_good`, or `used_fair` |
| `deliveryMethods` | string\[] | No | `[]` | Delivery method values accepted by Marketplace |
| `categoryIds` | string\[] | No | `[]` | Marketplace category IDs |
| `availability` | string | No | `all` | `all`, `in_stock`, or `out_of_stock` |
| `dateListed` | string | No | `all` | `all`, `1`, `7`, or `30` days |
| `exactMatch` | boolean | No | `false` | Request exact keyword matching |
| `maxItems` | integer | No | `20` | Maximum listings per input, from 1 to 10,000 |
| `maxPages` | integer | No | `20` | Maximum cursor pages per input, from 1 to 500 |
| `includeDetails` | boolean | No | `false` | Fetch a detail page for every discovered listing |
| `includeMedia` | boolean | No | `true` | Populate public photo and video URL arrays |
| `includeSeller` | boolean | No | `true` | Include the public seller subset when exposed |
| `includeVehicleDetails` | boolean | No | `true` | Include the public vehicle object when exposed |
| `monitorMode` | string | No | `off` | `off`, `onlyNew`, or `newAndChanged` |
| `monitorKey` | string | No | `default` | Namespace for persistent comparison state |
| `maxConcurrency` | integer | No | `3` | Concurrent inputs, from 1 to 10 |
| `includeRaw` | boolean | No | `false` | Include a sanitized source listing object |

### Use cases

#### Marketplace lead discovery

Run several location and product searches, export unique listings, and route promising results to a CRM or spreadsheet.

#### Price research

Collect comparable listings with normalized amount, currency, condition, and location fields, then calculate price ranges outside the Actor.

#### Inventory and availability monitoring

Schedule `monitor` or `status` mode and send new, changed, pending, or sold results to a webhook, Slack workflow, or database.

#### Vehicle catalog collection

Use category URLs with detail enrichment to retain category-specific attributes and the public `vehicle` object when Facebook exposes it.

### Performance and cost

The Actor uses pay-per-event billing when configured on Apify. Search rows, enriched detail rows, and explicit status checks use separate event names so they can be priced according to upstream work and buyer value. Consult the Actor's **Pricing** tab for the currently configured rates.

Search-only runs are the lightest. `includeDetails: true` adds one public item workflow per listing and substantially increases requests and transfer. Large media URLs are returned as text; binary media files are not downloaded. Runtime also depends on source latency, selected limits, retries, and Marketplace availability.

### API usage

Replace `YOUR_USERNAME` with the published Actor owner name.

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/YOUR_USERNAME~facebook-marketplace-public-scraper/runs?token=APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "search",
    "searchTerms": ["bicycle"],
    "location": "newyork",
    "maxItems": 20
  }'
```

The resulting dataset works with Apify API clients, schedules, webhooks, Google Sheets, Make, Zapier, n8n, Airbyte, and data warehouses.

### Best for / not for

**Best for:** public Marketplace search, public listing enrichment, price research, availability checks, scheduled discovery, and category-specific catalog collection.

**Not for:** Facebook login automation, private seller information, messaging, checkout, buyer/seller account activity, or private Marketplace content.

### Limits and good to know

- One mode is selected per run, but each mode accepts batches of inputs.
- `maxItems` and `maxPages` apply per search or browse input before cross-input deduplication.
- Facebook controls public availability, localization, filters, and the fields present on each listing.
- Detail pages do not always expose every search-card image or seller field to anonymous visitors.
- Every successful row contains all 45 top-level keys; missing values use `null` or empty arrays.
- Retries use fresh residential sessions. One failed target does not cancel successful targets.
- Failed, blocked, duplicate, and unavailable inputs do not create a paid error row.
- The Actor uses Apify Residential Proxy automatically and does not expose proxy configuration in the input.

### Frequently asked questions

#### What input should I provide?

For discovery, provide `searchTerms` and a Marketplace location slug such as `newyork`. For exact lookups, provide numeric IDs or copied item URLs in `listingIds`.

#### How many results can I extract?

You can set up to 10,000 items and 500 cursor pages per input. Actual availability is controlled by Facebook, the selected location and filters, and public cursor depth.

#### Why are some fields empty?

Marketplace categories use different public schemas. Seller, vehicle, shipping, media, and coordinates may not be exposed for every listing. Missing scalar/object values are `null`; list values are usually empty arrays.

#### Can I process multiple searches or IDs?

Yes. Add multiple values to `searchTerms`, `startUrls`, or `listingIds`. Results are deduplicated by listing ID.

#### Can I schedule recurring runs?

Yes. Use Apify schedules with `monitor` mode and a stable `monitorKey`, then connect a webhook to receive new or changed rows.

#### Do I need a Facebook account, API key, or proxy?

No Facebook account or API key is required. Apify Residential Proxy is configured internally and used automatically.

### Responsible use

This Actor extracts publicly available Marketplace information. Users are responsible for complying with applicable laws, privacy regulations, contractual obligations, and Facebook's terms. Facebook and Marketplace are trademarks of Meta Platforms, Inc.; this Actor is not affiliated with or endorsed by Meta.

### Support

If you encounter a problem, create an issue in the Actor's **Issues** tab. Include the run ID, mode, and a non-sensitive reproducible keyword, URL, or listing ID. Do not include account cookies or credentials.

# Actor input Schema

## `mode` (type: `string`):

Choose discovery, detail, status, monitoring, or automatic URL routing.

## `searchTerms` (type: `array`):

One or more products or phrases to search for.

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

Location, category, search, or individual item URLs.

## `listingIds` (type: `array`):

Used by details and status modes.

## `location` (type: `string`):

The location segment from a Marketplace URL, for example newyork or london.

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

Maximum search distance around the selected Marketplace location, from 1 to 500 kilometers.

## `minPrice` (type: `number`):

Optional minimum listing price in the currency used by the selected Marketplace region.

## `maxPrice` (type: `number`):

Optional maximum listing price in the currency used by the selected Marketplace region.

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

Order listings by best match, newest first, price, or distance.

## `conditions` (type: `array`):

Marketplace condition values such as new, used\_like\_new, used\_good, or used\_fair.

## `deliveryMethods` (type: `array`):

Optional Marketplace delivery method values used to narrow search results.

## `categoryIds` (type: `array`):

Optional Facebook Marketplace category identifiers used to restrict discovery.

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

Return all listings or restrict results by the public availability state.

## `dateListed` (type: `string`):

Restrict search results to listings published within the selected recent period.

## `exactMatch` (type: `boolean`):

Prefer listings that match the supplied search phrase exactly when the public search surface supports it.

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

Maximum number of normalized listing rows saved for each search term, URL, or direct input.

## `maxPages` (type: `integer`):

Maximum number of public result pages requested for each discovery input.

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

Visit every discovered item for description, seller, media, and category-specific fields.

## `includeMedia` (type: `boolean`):

Keep public listing image and video URLs when Facebook exposes them.

## `includeSeller` (type: `boolean`):

Keep seller identity and profile fields only when they are publicly available without login.

## `includeVehicleDetails` (type: `boolean`):

Keep public vehicle attributes such as make, model, year, mileage, transmission, and body style when available.

## `monitorMode` (type: `string`):

Save every result, only newly discovered listings, or new and changed listings compared with previous runs.

## `monitorKey` (type: `string`):

Stable namespace used to keep independent monitoring histories separate.

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

Maximum number of Marketplace input jobs processed concurrently.

## `includeRaw` (type: `boolean`):

Include a sanitized public source object for advanced processing; this increases dataset size.

## Actor input object example

```json
{
  "mode": "search",
  "searchTerms": [
    "bicycle"
  ],
  "location": "newyork",
  "radiusKm": 65,
  "sortBy": "best_match",
  "availability": "all",
  "dateListed": "all",
  "exactMatch": false,
  "maxItems": 20,
  "maxPages": 20,
  "includeDetails": false,
  "includeMedia": true,
  "includeSeller": true,
  "includeVehicleDetails": true,
  "monitorMode": "off",
  "monitorKey": "default",
  "maxConcurrency": 3,
  "includeRaw": false
}
```

# Actor output Schema

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

Complete listings, details, status, media, seller, and monitoring fields.

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

Requests, transfer, failures, results, and charged events.

# 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("scrapingmonkey/facebook-marketplace-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("scrapingmonkey/facebook-marketplace-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 '{}' |
apify call scrapingmonkey/facebook-marketplace-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapingmonkey/facebook-marketplace-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/PZU0YTLceCe0BXRJl/builds/HKoZcjn854cF1AkXY/openapi.json
