# Facebook Marketplace Scraper — Local Listings & Prices (`logical_vivacity/facebook-marketplace-scraper`) Actor

Search Facebook Marketplace and get local listings as a sortable table: title, price as a number, location, photo, link and whether it has sold. Filter by price, condition, radius and how recently it was listed. No login needed.

- **URL**: https://apify.com/logical\_vivacity/facebook-marketplace-scraper.md
- **Developed by:** [Logical Vivacity](https://apify.com/logical_vivacity) (community)
- **Categories:** E-commerce, Lead generation, Business
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 listing founds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 — Local Listings & Prices

**What's for sale near you, as a table you can sort — every Facebook Marketplace listing for a search term in a city, with the price as a number.**

Marketplace is the biggest local classifieds board in the world and the worst one to work from. It is an endless scroll, it forgets where you were, and there is no way to line two hundred listings up next to each other and see which one is mispriced. This Actor turns a search into rows: title, price, where the seller is, the photo, the link, and whether the item has already gone.

Type what you want and the city you want it in. Or paste a Marketplace search link you already have open.

**You pay per listing returned.** Searches that come back empty and searches that fail cost you nothing.

***

### Try it in 30 seconds

Put this in **Searches**, set **City** to `dallas`, hit Start:

```
iphone
```

About fifty live listings with real prices, from Dallas and the towns around it. That exact run was made today and came back full.

***

### Two ways in

**A search term** — `iphone 15`, `dining table`, `snowblower`, `2015 civic`. Set **City** once and every term runs there.

**A full Marketplace search link** — open the board you want in your browser, get the filters right, and copy the URL from the address bar:

```
https://www.facebook.com/marketplace/austin/search?query=mountain%20bike
```

Links carry their own city and their own filters, so **City** is ignored for those lines. Anything you set in the Actor that the link doesn't already say is added on top.

**Finding the city slug.** Open Marketplace, set your location, and look at the address bar: `facebook.com/marketplace/`**`dallas`**`/search`. That word is the slug — the city name lowercased with the spaces taken out. `nyc`, `la`, `chicago`, `sanantonio`, `fortworth`.

***

### What you get per listing

```jsonc
{
  "listingId": "1042073261987193",       // stable — diff on this between runs
  "title": "iphone 17 pro",
  "price": 850,                          // a number, ready to sort and compare
  "currency": "USD",
  "priceText": "$850",                   // exactly as the board shows it
  "location": "Dallas, TX",              // the seller's town, not yours
  "imageUrl": "https://scontent-….fbcdn.net/…jpg",
  "listingUrl": "https://www.facebook.com/marketplace/item/1042073261987193/",
  "isSold": false,                       // true once it's sold or pending
  "isFree": false,                       // free-to-collect listings
  "searchTerm": "iphone",                // which of your searches produced this
  "city": "dallas",
  "scrapedAt": "2026-09-17T19:33:17+00:00",
  "status": "ok"
}
```

Export as JSON, CSV, Excel, XML or HTML, or pull it straight from the API.

***

### Who uses this

**Resellers and flippers sourcing inventory.** Run your buy list — `airpods`, `dyson`, `peloton`, `lawn mower` — across the cities you can drive to, sort by price ascending, and the underpriced end of every board is at the top of one spreadsheet. The scroll is where the margin dies; this removes the scroll.

**Local-deal arbitrage.** The same item is worth different money forty miles away. Run one term across six city slugs in a single job and the spread is a column, not a hunch.

**Price research before you buy or list.** Twenty comparable listings with numeric prices gives you a median in seconds. Price your own listing against what is actually on the board today, not what sold last year.

**Dealerships and inventory monitors.** Schedule a run with **Listed in the last 24 hours** and **Sort by newest**, diff on `listingId`, and you have a feed of everything new in your category in your market — with `isSold` telling you what moved since the last run.

**Market researchers and analysts.** Same searches, same cities, on a schedule. The change in median price, in listing count and in how fast items flip to sold is a dataset nobody publishes.

***

### What makes it different

**Price is a number.** `price: 850`, not `"$850"`. You get both — the numeric field for maths and `priceText` for what the board actually printed — so sorting, medians and price bands work the moment the run finishes.

**Several searches, several cities, one table.** Every row is tagged with the `searchTerm` and `city` that produced it, so a fifteen-term, six-city job comes back as one dataset you can pivot rather than ninety exports to stitch together.

**Sold and free are flags, not guesswork.** `isSold` covers sold and pending. `isFree` catches free-to-collect items, which otherwise read as a price of zero and poison your averages.

**No account, no login, no cookies to paste.** this Actor reads the same public boards a shopper browsing without an account sees. There is nothing to configure and no session to keep alive.

**Filters are applied before you're billed.** A run with a £50–£400 band bills you for the listings in that band, not for the whole board.

**Honest about the ceiling.** The public board stops at roughly 50–60 listings per search. That's in the FAQ, not buried — and the way around it is there too.

***

### Settings that matter

| Setting | What it does |
|---|---|
| **Searches** | One per line — a search term, or a full Marketplace search link |
| **City** | The city slug your search terms run in. Ignored for link lines |
| **Maximum listings per search** | Default 50. One board runs out around 50–60 — see the FAQ |
| **Minimum / maximum price** | Whole units, no commas. Listings with no price are dropped when set |
| **Item condition** | New, like new, good, fair — sellers set this themselves and many skip it |
| **Listed in the last** | 24 hours, 7 days, 30 days, any time |
| **Search radius** | Passed to the board, which decides its own area — read the FAQ before relying on it |
| **Sort by** | Best match, newest, price low to high, price high to low |

### Automate it

```bash
curl -X POST "https://api.apify.com/v2/acts/YOUR_USERNAME~facebook-marketplace-scraper/runs?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{ "searches": ["iphone 15", "airpods pro", "https://www.facebook.com/marketplace/austin/search?query=mountain%20bike"],
        "city": "dallas",
        "maxResultsPerSearch": 50,
        "minPrice": 50,
        "maxPrice": 600,
        "condition": "used_good",
        "daysSinceListed": "7",
        "sortBy": "newest" }'
```

Works with Make, Zapier, n8n, Google Sheets and the Apify API, and as an MCP tool for AI agents. Schedule it hourly on a short term list and you have a deal alarm.

### Results you can trust

Every search reports what happened, so nothing fails silently:

| `status` | Meaning |
|---|---|
| `ok` | A listing was returned — charged |
| `no_results` | The board was read fine, but nothing matched — not charged |
| `error` | The search couldn't be read, or the line was unusable — retry it; not charged |

***

### FAQ

**How many listings can one search return?**
Around 50 to 60. The public board hands out its first screens freely and then stops, and no amount of scrolling gets past that without signing in — which this Actor does not do. Raising **Maximum listings per search** above that will not conjure more listings out of one board.

The fix is more searches, not a bigger number. Each of these is a fresh board with its own 50–60:

- **Split the price range.** `sofa` at $0–200, $200–500, $500+ is three runs of the same term and three different sets of listings.
- **Be more specific.** `iphone 15 pro`, `iphone 14`, `iphone se` beats `iphone` and gives you rows you actually want.
- **Add cities.** One term across eight city slugs is eight boards.
- **Flip the sort.** Price ascending and price descending on the same search reach opposite ends of the same board.

A twelve-term, four-city job is forty-eight boards — two thousand or so listings in one run.

**Why do some listings have no price?**
Because the seller didn't put one. Marketplace lets people list with no price, with "Free", or with a price that is really a placeholder, and this Actor reports what's there rather than inventing a number: `price` is absent, `priceText` shows whatever the board printed, and `isFree` is `true` for free-to-collect items. Set a **Minimum price** of 1 and priceless listings drop out of the run — and you are not charged for them.

**Does the search radius actually work?**
Partly, and we'd rather say so. The public board serves the metro area around a city slug and treats a tight radius as a suggestion, so a 5-mile search on a big city will still return listings from towns 40 miles out. Your choice is passed through, but the reliable way to control distance is to filter on the `location` field after the run, or to search a smaller city slug.

**Do I need a Facebook account, a login or cookies?**
No. This Actor reads public search boards, the same ones a visitor with no account sees. Nothing to paste, nothing to keep alive, nothing of yours at risk.

**Does it return the seller's name, profile or phone number?**
No. Public search boards don't carry them, and this Actor doesn't go looking. What you get is the item: title, price, location, photo and link.

**Is `location` where the seller is or where I searched?**
Where the seller is — the town the board shows on the listing. `city` is the slug you searched. On a big-metro run they routinely differ, and that difference is exactly what tells you how far you'd have to drive.

**How do I track price drops or what's sold?**
Schedule the same searches and diff on `listingId`. A changed `price` is a price cut, `isSold` flipping to `true` means it went, and a row that stops appearing has been taken down.

**How fresh is it?**
Read live at the moment of your run. `scrapedAt` records exactly when, to the second.

**What about cars, real estate or rentals?**
Vehicle and property searches return as ordinary listings with title, price, location and link. The category-specific fields — mileage, bedrooms, transmission — are not in this version.

**Why is this slower than other scrapers?**
Because these boards only exist once the page has been rendered and scrolled. This Actor does that properly rather than returning the empty shell the quick approach gets. Budget roughly a minute per search.

***

### Terms of Use

This Actor collects publicly available listing information from Facebook Marketplace search results — the same listings a visitor browsing without an account can see. It does not sign in, does not use anyone's credentials, and does not collect seller names, profiles or contact details.

This Actor is an independent tool. It is not affiliated with, endorsed by, sponsored by or connected to Facebook, Meta Platforms, or any of their products or services, and all trademarks belong to their owners.

You are responsible for how you use the results, and for doing so lawfully and in line with the terms and regulations that apply to you — including Facebook's own terms of service, marketing and consumer-protection rules, and any data-protection law in your jurisdiction. If your plans involve republishing listing content, contacting sellers or building a competing product, check those terms before you start. Listing content belongs to the people who posted it.

Listings are returned as the source published them and may be inaccurate, stale or already gone by the time you read them — verify before you send money or drive anywhere. This Actor is provided "as is", without warranty of accuracy, completeness or fitness for a particular purpose.

***

*Missing a field, a filter or a category you need?* Open an issue on the Actor's Issues tab.

# Actor input Schema

## `searches` (type: `array`):

One per line. Either a plain search term like "iphone 15" or "dining table" — which uses the City below — or a full Marketplace search link copied from your browser's address bar, which already carries its own city and filters.

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

The city your search terms run in — "dallas", "chicago", "nyc", "sanantonio". To find the exact slug, open Facebook Marketplace, set your location, and read the word between /marketplace/ and /search in the address bar: facebook.com/marketplace/**dallas**/search. It is the city name lowercased with the spaces removed. Ignored for lines that are already full search links.

## `maxResultsPerSearch` (type: `integer`):

How many listings to return for each search. A single public search board runs out at roughly 50–60 listings — see the README — so to go deeper, split one search into several narrower ones (price bands, more specific terms, nearby cities) rather than raising this number.

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

Optional. Whole units of the local currency, no commas. Listings with no price at all are dropped when you set a price band.

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

Optional. Whole units of the local currency, no commas.

## `condition` (type: `string`):

Keep only listings the seller marked with this condition. Sellers set it themselves and many leave it off, so a tight condition will thin out the results.

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

Only listings posted within this window. Set 1 day for a scheduled run that watches for anything new.

## `radiusMiles` (type: `string`):

How far around the city to look. Passed through to the search board, which decides the area it serves — on the public board this is treated as a hint rather than a hard limit, so expect listings from the wider metro. Filter on the location field afterwards if you need it tighter.

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

Which listings come back first. This is what decides the contents of your run when the cap is smaller than the number of matches — newest for a watch list, price low to high for deal hunting.

## Actor input object example

```json
{
  "searches": [
    "iphone",
    "https://www.facebook.com/marketplace/austin/search?query=mountain%20bike"
  ],
  "city": "dallas",
  "maxResultsPerSearch": 50,
  "condition": "any",
  "daysSinceListed": "all",
  "sortBy": "best_match"
}
```

# Actor output Schema

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

Every listing matching your search, sortable by price.

## `overview` (type: `string`):

The same rows as a spreadsheet-style table, with the most useful columns first.

# 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 = {
    "searches": [
        "iphone",
        "https://www.facebook.com/marketplace/austin/search?query=mountain%20bike"
    ],
    "city": "dallas"
};

// Run the Actor and wait for it to finish
const run = await client.actor("logical_vivacity/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 = {
    "searches": [
        "iphone",
        "https://www.facebook.com/marketplace/austin/search?query=mountain%20bike",
    ],
    "city": "dallas",
}

# Run the Actor and wait for it to finish
run = client.actor("logical_vivacity/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 '{
  "searches": [
    "iphone",
    "https://www.facebook.com/marketplace/austin/search?query=mountain%20bike"
  ],
  "city": "dallas"
}' |
apify call logical_vivacity/facebook-marketplace-scraper --silent --output-dataset

```

## MCP server setup

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