# Facebook Marketplace Scraper & API: Vehicles, Rentals, No Login (`hyperbach/facebook-marketplace-scraper`) Actor

Facebook Marketplace scraper and API for listings data without login or account: search by words and place, or give links. Per listing the title, price, city, date, photo and seller; with details the description, condition, coordinates, all photos, vehicle and rental facts, seller rating.

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

## Pricing

from $3.89 / 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 & API: Vehicles, Rentals, No Login

**Facebook Marketplace listings as data, logged out.** Give Marketplace links as you copy them (a search, a category at a city, a city's feed, a listing) or search words with cities, and get **one row per listing**: the id and link, the title, the **price with its ISO currency**, the old price, the city, **the date it was listed**, sold and pending flags, the delivery types, the photo and the **seller's name and id**. Ask for details and each row also carries the **description, condition, map coordinates** (and the distance from the searched place), **every photo and the video**, the vehicle facts (make, model, mileage, transmission), the rental unit's rooms, shipping and the **seller's rating and join date**. A link that gives no listing gets a free row that says why. No login, no cookies, no browser, proxies handled for you.

### Why this Facebook Marketplace scraper

- **A repeat is never charged twice.** One listing is one charged row a run, however many of your links or searches show it; a later one gets a free `duplicate` row that names the input that first delivered it. On the same Prague jobs the most-used Marketplace Actor charged 40 rows for 39 distinct listings and 50 for 43 (our stage-1 runs).
- **Every listing dated.** `created_at` comes from Facebook's own listing time, on 3,696 of 3,696 search cards our study walked, so `daysSinceListed`, the newest-first sort and `onlyNew` on a schedule work on real dates, never on a guess from the id.
- **The price as a number with its currency.** `price` is the amount, `currency` the ISO code (`CZK`, `USD`, `GBP`, `EUR`), `price_text` Facebook's own text, and the struck-through old price beside it. A rental's monthly text stays in `price_text`.
- **Filters before the charge.** Price bounds, days since listed, the sort, the condition, sold listings, the delivery method, for vehicles (with search words such as `car`) the year, mileage and transmission, and for rentals the bedrooms and bathrooms go to Facebook's own search. Your include and exclude words and the strict city filter drop a listing before it is charged or counted against your caps.
- **Details only when you ask.** The list card already carries the title, price, place, date, photo and (on 84-98 % of cards in our study) the seller's name. Details read each listing's own page and its photo viewer: the description, condition, map coordinates, attributes, every photo, the video, the vehicle and rental facts, shipping and the seller's rating.
- **Plain HTTP, no browser, no account.** Facebook's own logged-out Marketplace queries through residential connections; a refused connection moves the read to a fresh one at once. On the Apify platform 200 listings took 17 seconds (700 a minute, the first at 5 seconds), and 50 listings with details 32 seconds.

### Who it's for

- **Resellers and deal hunters** — new listings under a price at the cities they buy in, newest first, read on a schedule with `onlyNew` so each run brings only listings no earlier run delivered (add `daysSinceListed` to keep them recent: under a cap, older listings the memory never saw fill the room).
- **Car dealers and vehicle market analysts** — vehicles by year, mileage and transmission at each city (a search such as `car` or `truck` with the vehicle filters), with the make, model, trim, mileage and the seller type from each listing's page.
- **Property and rental researchers** — the rentals and homes of a city with their price, rooms, area, coordinates (with details) and listing date, compared week by week.

### Quick start

**One search at Prague, the first 50**

```json
{
  "startUrls": [
    "https://www.facebook.com/marketplace/prague/search/?query=apartment"
  ],
  "maxItems": 50
}
```

**Search words at two cities, newest first, under a price**

```json
{
  "searchQueries": [
    "bike"
  ],
  "locations": [
    "nyc",
    "austin"
  ],
  "maxPrice": 300,
  "sortBy": "creation_time_descend",
  "maxResultsPerQuery": 40
}
```

**One listing with its details**

```json
{
  "startUrls": [
    "https://www.facebook.com/marketplace/item/702911604955231/"
  ],
  "searchDetails": true
}
```

### Output

One row per listing (and one free summary row per link or search):

| field | meaning |
|---|---|
| `record_type` | `listing` (one listing; charged when `status` is `ok`) or `target` (one free row per link or search: what it delivered and its verdict). |
| `status` | `ok` on a charged listing and on a target that delivered. Free: `duplicate`, `not_found`, `private`, `invalid_input`, `failed`, `not_read` (the FAQ says which is which). |
| `input` | The link or search as you gave it, that this row answers. |
| `search_query` | The search words of the search that listed this row (from `searchQueries` or a link's `?query=`). |
| `search_place` | The city of the search or feed that listed this row, as Facebook's link names it (`prague`, `nyc`). |
| `search_category` | The category of the feed that listed this row (`vehicles`, `home-improvements`), when the input named one. |
| `search_rank` | The listing's place in its input's list, 1 = first. |
| `id` | Facebook's listing id. |
| `url` | The listing's page: `https://www.facebook.com/marketplace/item/<id>/`. |
| `title` | The listing's title as the seller wrote it. |
| `price` | The price as a number in `currency` (199 for CZK199; 0 for a free item). |
| `price_text` | Facebook's own price text (`CZK199`, `$1,250`, `Free`, a rental's `$1,500 / Month`). |
| `currency` | The price's ISO currency code (`CZK`, `USD`, `GBP`, `EUR`). |
| `strikethrough_price` | The struck-through old price, when the seller lowered the price. |
| `strikethrough_price_text` | Facebook's text of the old price. |
| `city` | The listing's city. |
| `state` | The listing's state or region. |
| `country` | The two-letter country code (from the listing's page, else the searched place's). |
| `city_page_id` | Facebook's page id of the listing's city. |
| `city_page_name` | The name of the listing's city page. |
| `location_text` | The place line the listing's page shows (`Praha`, `Austin, TX`). |
| `latitude` | The listing's latitude (details; Facebook places it near, not at, the seller's address). The search card carries none. |
| `longitude` | The listing's longitude (details). |
| `distance_km` | Kilometres from the searched city's point to the listing's coordinates (details); empty on a listing read by its own link. |
| `created_at` | When the listing was put up (UTC), from Facebook's own listing time. |
| `is_live` | Facebook shows the listing as live. |
| `is_pending` | The seller marked the listing pending. |
| `is_sold` | The seller marked the listing sold. |
| `listing_status` | The status the listing's page shows (details). |
| `delivery_types` | How the item changes hands: `IN_PERSON`, `SHIPPING_OFFSITE`, `DOOR_PICKUP` and others, as Facebook names them. |
| `is_shipping_offered` | The seller ships the item (details). |
| `shipping_price` | The shipping price as a number, when the page gives one in US form (details). |
| `shipping_price_text` | Facebook's shipping price text (details). |
| `category_id` | Facebook's Marketplace category id. |
| `category` | The category's name (`Tools`, `Property rentals`); empty on a vehicle, whose page names none. |
| `category_slug` | The word of the category's link (`tools`, `propertyrentals`) (details). |
| `listing_type` | Facebook's kind of listing: `FOR_SALE_ITEM`, a vehicle or a home or rental type (details). |
| `condition` | The condition the seller chose (`New`, `Used - like new`, `Used - good`, `Used - fair`) (details). |
| `attributes` | Every attribute the listing's page shows, as name and value pairs (details). |
| `subtitles` | The card's sub-lines (a vehicle's mileage, a rental's rooms), as Facebook shows them. |
| `description` | The seller's description (details). |
| `photo_url` | The listing's first photo (a signed link: see `media_urls_expire_at`). |
| `photos` | Every photo of the listing, in order (details; signed links). |
| `has_video` | The listing carries a video. |
| `video_url` | The first video's link (details; signed). |
| `video_url_hd` | The first video's HD link (details; signed). |
| `media_urls_expire_at` | When the signed photo and video links stop working (UTC), about 4 days after the read. |
| `vehicle_make` | A vehicle's make (details). |
| `vehicle_model` | A vehicle's model (details). |
| `vehicle_trim` | A vehicle's trim (details). |
| `vehicle_mileage` | A vehicle's mileage, in `vehicle_mileage_unit` (details). |
| `vehicle_mileage_unit` | The mileage's unit (miles or kilometres) (details). |
| `vehicle_transmission` | A vehicle's transmission (details). |
| `vehicle_fuel_type` | A vehicle's fuel type (details). |
| `vehicle_exterior_color` | A vehicle's exterior colour (details). |
| `vehicle_interior_color` | A vehicle's interior colour (details). |
| `vehicle_seller_type` | Who sells the vehicle, as Facebook states it (a private seller or a dealership) (details). |
| `vehicle_condition` | A vehicle's condition as the seller states it (excellent, very good, good, fair) (details). |
| `vehicle_vin` | The vehicle identification number, when the seller gives it (details). |
| `vehicle_title_status` | The vehicle's title status as the seller states it (clean, rebuilt …) (details). |
| `vehicle_owners` | How many owners the vehicle has had, as Facebook states it (ONE, TWO, …) (details). |
| `vehicle_paid_off` | Whether the vehicle is paid off, as the seller states it (details). |
| `vehicle_specifications` | A vehicle's other specifications with their units, by name (details). |
| `unit_details` | A home's or rental's unit lines as the page shows them (rooms, area, type, pets, parking) (details). |
| `bedrooms` | A home's or rental's bedrooms, from its unit lines (details). |
| `bathrooms` | A home's or rental's bathrooms, from its unit lines (details). |
| `area` | A home's or rental's area, as its unit line gives it (details). |
| `seller_name` | The seller's name as the listing shows it to a logged-out visitor. |
| `seller_id` | Facebook's id of the seller. |
| `seller_profile_url` | The seller's Marketplace profile link, built from the id; it opens for a logged-in visitor only and is not read. |
| `seller_joined_at` | When the seller joined Facebook (UTC) (details). |
| `seller_rating` | The seller's average rating out of 5, as the item page serves it (details). |
| `seller_rating_count` | How many ratings the seller has (details). |
| `seller_ratings_private` | The seller marks the ratings private on the profile; the item page still serves the figures (details). |
| `seller_verified` | Facebook shows a verified badge on the seller (details). |
| `business_seller` | Facebook labels the seller a business (details). |
| `related_ids` | The ids of the similar listings the page shows (details). |
| `details_status` | `served` (the listing's page was read), `refused` (Facebook refused it on every connection tried; never charged as details), `missing` or `not_asked`. |
| `analysis_listing_kind` | The model's kind of listing (`tagListings`): `for_sale`, `for_rent`, `wanted`, `service`, `swap` or `other`. |
| `analysis_category` | The model's category of the listing (`tagListings`): `vehicles`, `property`, `phones_electronics`, `home_appliances`, `furniture_home`, `baby_kids`, `sports_outdoors`, `clothing_accessories`, `tools_garden` or `other`. |
| `analysis_seller_kind` | The model's guess of the seller from the listing's words: `private`, `business` or `unclear` (`tagListings`). Weak: on our test 3 of 20 answers were wrong at 0.91-0.97 confidence; a hint, never a fact. |
| `analysis_price_kind` | The model's kind of price: `real`, `placeholder` (a token figure such as 1 or 123), `free` or `unstated` (`tagListings`). |
| `analysis_confidence` | The model's confidence (0-1) in each of its tags, by tag name (`tagListings`). |
| `verdict` | On a target row: `COMPLETE` (read to Facebook's own end), `DATE_LIMIT` (the end of the `daysSinceListed` window), `CAPPED` (your cap or charge limit came first) or `PARTIAL` (stopped early, a filtered walk past its read budget of 100 listings per row delivered among them: `note` says why). |
| `rows_delivered` | On a target row: the listing rows it delivered. |
| `note` | Why a row has the status or the verdict it has; on a `duplicate`, the input that first delivered the listing. |
| `scraped_at` | When this row was read (UTC). |

Example record:

```json
{
  "record_type": null,
  "status": null,
  "input": null,
  "search_query": null,
  "search_place": null,
  "search_category": null,
  "search_rank": null,
  "id": null,
  "url": null,
  "title": null,
  "price": null,
  "price_text": null,
  "currency": null,
  "strikethrough_price": null,
  "strikethrough_price_text": null,
  "city": null,
  "state": null,
  "country": null,
  "city_page_id": null,
  "city_page_name": null,
  "location_text": null,
  "latitude": null,
  "longitude": null,
  "distance_km": null,
  "created_at": null,
  "is_live": null,
  "is_pending": null,
  "is_sold": null,
  "listing_status": null,
  "delivery_types": null,
  "is_shipping_offered": null,
  "shipping_price": null,
  "shipping_price_text": null,
  "category_id": null,
  "category": null,
  "category_slug": null,
  "listing_type": null,
  "condition": null,
  "attributes": null,
  "subtitles": null,
  "description": null,
  "photo_url": null,
  "photos": null,
  "has_video": null,
  "video_url": null,
  "video_url_hd": null,
  "media_urls_expire_at": null,
  "vehicle_make": null,
  "vehicle_model": null,
  "vehicle_trim": null,
  "vehicle_mileage": null,
  "vehicle_mileage_unit": null,
  "vehicle_transmission": null,
  "vehicle_fuel_type": null,
  "vehicle_exterior_color": null,
  "vehicle_interior_color": null,
  "vehicle_seller_type": null,
  "vehicle_condition": null,
  "vehicle_vin": null,
  "vehicle_title_status": null,
  "vehicle_owners": null,
  "vehicle_paid_off": null,
  "vehicle_specifications": null,
  "unit_details": null,
  "bedrooms": null,
  "bathrooms": null,
  "area": null,
  "seller_name": null,
  "seller_id": null,
  "seller_profile_url": null,
  "seller_joined_at": null,
  "seller_rating": null,
  "seller_rating_count": null,
  "seller_ratings_private": null,
  "seller_verified": null,
  "business_seller": null,
  "related_ids": null,
  "details_status": null,
  "analysis_listing_kind": null,
  "analysis_category": null,
  "analysis_seller_kind": null,
  "analysis_price_kind": null,
  "analysis_confidence": null,
  "verdict": null,
  "rows_delivered": null,
  "note": null,
  "scraped_at": null
}
```

### Pricing

**Pay per listing delivered**, plus one run start; no platform usage and no proxy traffic is billed to you. The price falls with your Apify plan.

| event | unit | Free | Starter | Scale | Business |
|---|---|---|---|---|---|
| Listing (`listing`) | per 1,000 | $6.20 | $5.00 | $3.89 | $3.89 |
| Listing details (`listing_details`) | per 1,000 | $6.20 | $5.00 | $3.80 | $2.60 |
| Listing tags (`listing_tags`) | per 1,000 | $1.00 | $0.85 | $0.70 | $0.50 |
| Run start (`start`) | per run | $0.0017 | $0.0017 | $0.0017 | $0.0017 |

A listing is **$6.20 per 1,000** on the Free plan ($0.0062 a listing) and $5.00 on Starter, with everything its card carries: the title, the price and its currency, the city, the date, the photo and the seller's name and id (coordinates come with details). Details (Read each listing's item page, off by default) add the listing's own page and its photo viewer at $6.20 per 1,000 on the Free plan and $5.00 on Starter, only on a row whose page came in. Tags by a model (Tag each listing with a model, off by default) add $1.00 per 1,000 on the Free plan, only on a row the model tagged. Each run that delivers a charged row also pays the **run start, $0.0017 once**; a run that delivers none pays nothing at all. So one listing costs $0.0079 on the Free plan and $0.0067 on Starter; a search's first 100 (the default cap) $0.6217 and $0.5017; the same 100 with details $1.2417 and $1.0017; 1,000 listings $6.2017 and $5.0017. Free: a repeat (a listing two of your links or searches show is charged once), a listing a filter or `onlyNew` leaves out, a link that gives no listing, each link's and search's own row, a details page Facebook refused, and a target left unread at `maxItems`, your charge limit or the time limit. A run that stops early (a timeout, an abort) is charged for the rows it delivered. `maxItems` counts the charged listings. Before the first request the log names the most the run can cost at your plan's prices: per link or search Max results per search (100 unless you set it, at most 10,000), a listing link one row, under `maxItems`, with the add-ons you switched on and the run start, or your charge limit when that is lower. A search's list can end sooner: on our runs Facebook listed 409 listings for "apartment" at Prague, 1,313 for "sofa" at Austin and 2,184 for "bike" at Prague, each to its own end. Enterprise plans have their own rates — the Actor's Pricing tab shows the price for your plan.

### Usage patterns

- **Links, searches and cities** — `startUrls` takes Marketplace links one a line, as you copy them: a search (`…/marketplace/nyc/search/?query=bike&maxPrice=300`), a category at a city (`…/marketplace/prague/home-improvements/`), a city's feed (`…/marketplace/london/`) or a listing (`…/marketplace/item/<id>/`); the filters in a link's query are read. `searchQueries` × `locations` searches each word at each city; `category` alone browses one category at each city. A city is the word Facebook's own link uses (`nyc`, `austin`, `london`, `prague`) or its city page id; with search words, a point as `latitude,longitude` searches around it; a free place name or a postal code is not read yet and gives a free `invalid_input` row. Facebook takes no radius from a logged-out visitor, so a city's results include nearby towns: `strictLocation` keeps the city itself only.
- **What a row is** — `record_type` = `listing`: one listing; `status` `ok` is the charged row, `duplicate` a free row for a listing an earlier input of the run already delivered. `record_type` = `target`: one free row per link or search with `rows_delivered`, the `verdict` and its `note`. Every listing row carries the input that gave it (`input`, `search_query`, `search_place`, `search_category`) and its place in that input's list (`search_rank`).
- **Caps, verdicts and the picture links** — `maxResultsPerQuery` (default 100) stops each link or search; `maxItems` (0 = no limit) stops the run after that many charged listings. A target's verdict: `COMPLETE` (read to Facebook's own end), `DATE_LIMIT` (the end of a `daysSinceListed` window), `CAPPED` (your cap or charge limit came first) or `PARTIAL` (stopped early: `note` says why). With include or exclude words or `strictLocation`, a walk reads at most 100 listings for each listing it delivers, then ends `PARTIAL` with a note, so a filter that keeps almost nothing cannot read a city to its end at your cost. Facebook lists 11-15 listings on a US search's first page and 24-29 on the pages after, 24 a page in Europe. The photo and video links are signed by Facebook and stop working at `media_urls_expire_at` (about 4 days): download the images you keep.
- **Tags by a model (optional)** — `tagListings` adds five columns from a language model: `analysis_listing_kind`, `analysis_category`, `analysis_seller_kind`, `analysis_price_kind` and `analysis_confidence`. `analysis_seller_kind` (`private`, `business` or `unclear`) is the weakest: on our 20-listing test 3 of its answers were wrong at a confidence of 0.91-0.97, and on a card with a title only the honest answer is often `unclear`. Read it as a hint, never as a fact about the seller.

### Input configuration

| field | type | default | what it does |
|---|---|---|---|
| `startUrls` | `array` | `[]` | One a line, as you copy it from Facebook: a search (`https://www.facebook.com/marketplace/nyc/search/?query=bike&maxPrice=300`), a category at a city (`…/marketplace/prague/home-improvements/`, `…/marketplace/austin/vehicles/?minYear=2016`), a city's page (`…/marketplace/london/`), a listing (`…/marketplace/item/1101734965941993/`) or a bare listing id (`1101734965941993`). Any facebook.com host (`m.`, `web.`), with or without `https://`, inside a redirect link (`l.facebook.com/l.php?u=…`) or an old `#!/` link. A link keeps the filters set on Facebook. A value with spaces, a share link, a seller's page, a link with no city or another site gets a free `invalid_input` row. |
| `searchQueries` | `array` | `[]` | Search Marketplace for these words, one search a line (`bike`, `iphone 15`), at every city of Cities: each search × each city is one search. Needs Cities. Each search reads to Facebook's own end or Max results per search. |
| `locations` | `array` | `[]` | The cities to search, one a line, as Facebook's own Marketplace link names them: the word after `/marketplace/` (`nyc`, `la`, `austin`, `london`, `berlin`, `prague`), the city page id (`108424279189115`) or a Marketplace link of the city. With search words, a point as `latitude,longitude` (`50.0755,14.4378`) searches around that point. Alone (no search words, no category), each city's own feed is read. Facebook does not read a place by a free name or a postal code when logged out: such a value gets a free `invalid_input` row that says so. A place Facebook does not publish gets a free `not_found` row. |
| `category` | `string` | `""` | Browse one category at every city of Cities, with no search words: the word of the category's link (`vehicles`, `propertyrentals`, `home-improvements`). With search words, put the category into the words, or give the category's link in Marketplace links. |
| `minPrice` | `integer` | `0` | Only listings at this price or above, in the city's own currency, whole units (0 = no bound). The filters below apply to Search words and Category, not to Marketplace links. |
| `maxPrice` | `integer` | `0` | Only listings at this price or below, in the city's own currency, whole units (0 = no bound). |
| `daysSinceListed` | ``/ `1` / `7` / `30` | `""` | Only listings listed in the last day, 7 days or 30 days. |
| `sortBy` |`` / `creation_time_descend` / `price_ascend` | `""` | Facebook's order of the list: its own best match, the newest first, or the lowest price first. |
| `itemCondition` | `array` | `[]` | Only listings in these conditions (empty = any). |
| `onlySold` | `boolean` | `false` | Off: the listings for sale. On: only the listings marked sold (Facebook's 'out of stock'). |
| `deliveryMethod` | ``/ `local_pick_up` / `shipping` | `""` | Only local pickup, or only listings that ship. Facebook ships in the US only: elsewhere 'Shipping' lists nothing. |
| `minYear` | `integer` | `0` | Vehicles made in this year or later (0 = no bound). The vehicle filters go with search words (`car`, `truck`, `motorcycle`): Facebook applies them to a search; its vehicles category page ignores them for a logged-out visitor. |
| `maxYear` | `integer` | `0` | Vehicles made in this year or earlier (0 = no bound). |
| `minMileage` | `integer` | `0` | Vehicles with at least this odometer reading, in the unit the city's listings show (0 = no bound). |
| `maxMileage` | `integer` | `0` | Vehicles with at most this odometer reading (0 = no bound). |
| `transmissionType` |`` / `manual` / `automatic` | `""` | Only vehicles with this transmission. |
| `minBedrooms` | `integer` | `0` | Rentals with at least this many bedrooms (category propertyrentals; 0 = no bound). |
| `minBathrooms` | `integer` | `0` | Rentals with at least this many bathrooms (category propertyrentals; 0 = no bound). |
| `searchDetails` | `boolean` | `false` | Off: the listing as the list shows it (id, link, title, price, city, primary photo, listing date, status, delivery, the seller's name and id). On: also the item page's fields (description, condition, coordinates, category, every photo and the video, vehicle fields, the shipping price, related listing ids); slower. |
| `tagListings` | `boolean` | `false` | Off: no tags. On: four labels a language model reads from the listing's words: what the post is (for sale, for rent, wanted, service, swap), what it is about (vehicles, property, electronics, furniture, …), who posts it (private, business or unclear; an unsure answer is unclear) and what the price means (real, a placeholder, free, none), with the model's confidence for each. Billed per tagged listing; a listing the model did not answer is not billed. |
| `includeKeywords` | `array` | `[]` | Keep only the listings whose title (and description, with item pages) holds at least one of these words, case aside. The others are dropped before any charge. |
| `excludeKeywords` | `array` | `[]` | Drop the listings whose title (and description, with item pages) holds any of these words, case aside (`broken`, `parts only`). Dropped listings are not charged. |
| `strictLocation` | `boolean` | `false` | Off: every listing Facebook shows for the city, nearby towns too (Facebook takes no radius logged out). On: only the listings in the city itself; the others are dropped before any charge. |
| `onlyNew` | `boolean` | `false` | Deliver only the results an earlier run with the same memory did not deliver (older ones it never delivered too: add daysSinceListed to keep a scheduled run to recent listings). For a scheduled task. |
| `stateStoreName` | `string` | `""` | The name of the memory `onlyNew` keeps (letters, digits, '.', '\_', '-'); empty = a name derived from the inputs. |
| `maxResultsPerQuery` | `integer` | `100` | Stop each link, search or city after this many listings (1 to 10,000). A listing another value of the run already delivered is skipped and not counted. |
| `maxItems` | `integer` | `0` | The most charged rows of the whole run; 0 = no cap beyond your charge limit. |
| `country` | \`\` / `us` / `gb` / `de` / `cz` | `""` | The country of the connection the Actor reads through. Empty: the cities' own country where the Actor knows it, else the US. Set it to your cities' country when they are outside the US. |

### Errors

**A run does not fail because of your input.** When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends **Succeeded**, charges nothing, and says what to change:

- the status message starts with `INPUT REJECTED`;
- the dataset holds one row, `{"error": true, "code": "…", "message": "…"}`, and no results;
- the key-value store record `ERROR` holds the same object.

From code, check `error` on the first row before reading results.

A link that is not a Marketplace page, a place Facebook does not publish or a listing that is gone is not an error: it gets one free row with its `status` and the reason in `note`, and the run goes on with the others. A run that ends **Failed** is a fault on our side, never your input; it charges nothing, and we are alerted.

### FAQ

**Which status is which?**

`ok`: a listing, charged. Free: `duplicate` (a listing this run already delivered; `note` names the input that gave it first), `not_found` (Facebook answers no listing for the id on two connections, or does not publish the place), `private` (Facebook shows it to logged-in visitors only), `invalid_input` (a group, a profile, another site, a place by free name or postal code, coordinates without search words), `failed` (Facebook refused every connection tried; read it again later), `not_read` (`maxItems`, your charge limit or the time limit came first).

**Why is the city empty on some rows, and what is `distance_km`?**

Facebook's search cards name the city, never the coordinates: `latitude`, `longitude` and `distance_km` come with details (the listing's own page): our runs had coordinates on 0 of 3,497 rows without details and on 51 of 51 with them. The country is the searched place's (read from its link, or from its listings' currency; empty when the currency names no one country, such as the euro). A listing read from its own link names no searched place, so its row has no `distance_km`. `distance_km` is the great-circle distance from the searched city's point to the listing's coordinates.

**Does it read the seller's profile, messages or phone number?**

No. The seller's name and id come from the listing as a logged-out visitor sees it; `seller_profile_url` is built from the id and opens only for a logged-in visitor. No profile, message, phone number or other listing of the seller is read.

**Does it need a Facebook account, cookies or an API key?**

No. Everything is read from Facebook's public, logged-out Marketplace: no login, no cookie, no token of yours. Residential connections are included in the price.

### Integration

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('hyperbach/facebook-marketplace-scraper').call({"startUrls": ["https://www.facebook.com/marketplace/prague/search/?query=apartment"], "maxItems": 50});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('hyperbach/facebook-marketplace-scraper').call(run_input={'startUrls': ['https://www.facebook.com/marketplace/prague/search/?query=apartment'], 'maxItems': 50})
items = client.dataset(run['defaultDatasetId']).list_items().items
```

#### CLI

```bash
apify call hyperbach/facebook-marketplace-scraper --input '{"startUrls": ["https://www.facebook.com/marketplace/prague/search/?query=apartment"], "maxItems": 50}'
```

#### REST

```bash
curl -X POST "https://api.apify.com/v2/acts/hyperbach~facebook-marketplace-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' -d '{"startUrls": ["https://www.facebook.com/marketplace/prague/search/?query=apartment"], "maxItems": 50}'
```

### Support

**Disagree with a charge?** Write to apify@hyperbach.com with the run ID. We will ask Apify to compensate you, and the charge comes back to your Apify account as platform credit.

### See also

- **[Meta Ad Library Scraper](https://apify.com/hyperbach/meta-ads-library-scraper)** — every ad a page runs on Facebook, Instagram, Messenger, WhatsApp and Threads, with the landing URL, media, run dates and EU reach.
- **[Threads Scraper](https://apify.com/hyperbach/threads-scraper)** — Threads profiles with the exact follower count, their posts and replies with view counts, and keyword and tag search, without a login.
- **[Instagram Reels Transcript Scraper](https://apify.com/hyperbach/instagram-reels-transcript-scraper)** — the spoken words of Instagram reels, by reel link or creator, with the exact posting time.
- **[Instagram Posts Scraper](https://apify.com/hyperbach/instagram-posts-scraper)** — the posts and reels of Instagram profiles, with the whole caption, the exact publish time, likes, comments and plays.
- **[Instagram Hashtag Scraper](https://apify.com/hyperbach/instagram-hashtag-scraper)** — Instagram's own ranked list of top reels for a hashtag or a search keyword.
- **[Facebook Pages Scraper](https://apify.com/hyperbach/facebook-pages-scraper)** — Facebook pages by URL, id, name or search words: the exact follower count, categories, address, phone, e-mail and websites, and the page transparency facts.

*This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.*

# Actor input Schema

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

One a line, as you copy it from Facebook: a search (`https://www.facebook.com/marketplace/nyc/search/?query=bike&maxPrice=300`), a category at a city (`…/marketplace/prague/home-improvements/`, `…/marketplace/austin/vehicles/?minYear=2016`), a city's page (`…/marketplace/london/`), a listing (`…/marketplace/item/1101734965941993/`) or a bare listing id (`1101734965941993`). Any facebook.com host (`m.`, `web.`), with or without `https://`, inside a redirect link (`l.facebook.com/l.php?u=…`) or an old `#!/` link. A link keeps the filters set on Facebook. A value with spaces, a share link, a seller's page, a link with no city or another site gets a free `invalid_input` row.

## `searchQueries` (type: `array`):

Search Marketplace for these words, one search a line (`bike`, `iphone 15`), at every city of Cities: each search × each city is one search. Needs Cities. Each search reads to Facebook's own end or Max results per search.

## `locations` (type: `array`):

The cities to search, one a line, as Facebook's own Marketplace link names them: the word after `/marketplace/` (`nyc`, `la`, `austin`, `london`, `berlin`, `prague`), the city page id (`108424279189115`) or a Marketplace link of the city. With search words, a point as `latitude,longitude` (`50.0755,14.4378`) searches around that point. Alone (no search words, no category), each city's own feed is read. Facebook does not read a place by a free name or a postal code when logged out: such a value gets a free `invalid_input` row that says so. A place Facebook does not publish gets a free `not_found` row.

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

Browse one category at every city of Cities, with no search words: the word of the category's link (`vehicles`, `propertyrentals`, `home-improvements`). With search words, put the category into the words, or give the category's link in Marketplace links.

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

Only listings at this price or above, in the city's own currency, whole units (0 = no bound). The filters below apply to Search words and Category, not to Marketplace links.

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

Only listings at this price or below, in the city's own currency, whole units (0 = no bound).

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

Only listings listed in the last day, 7 days or 30 days.

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

Facebook's order of the list: its own best match, the newest first, or the lowest price first.

## `itemCondition` (type: `array`):

Only listings in these conditions (empty = any).

## `onlySold` (type: `boolean`):

Off: the listings for sale. On: only the listings marked sold (Facebook's 'out of stock').

## `deliveryMethod` (type: `string`):

Only local pickup, or only listings that ship. Facebook ships in the US only: elsewhere 'Shipping' lists nothing.

## `minYear` (type: `integer`):

Vehicles made in this year or later (0 = no bound). The vehicle filters go with search words (`car`, `truck`, `motorcycle`): Facebook applies them to a search; its vehicles category page ignores them for a logged-out visitor.

## `maxYear` (type: `integer`):

Vehicles made in this year or earlier (0 = no bound).

## `minMileage` (type: `integer`):

Vehicles with at least this odometer reading, in the unit the city's listings show (0 = no bound).

## `maxMileage` (type: `integer`):

Vehicles with at most this odometer reading (0 = no bound).

## `transmissionType` (type: `string`):

Only vehicles with this transmission.

## `minBedrooms` (type: `integer`):

Rentals with at least this many bedrooms (category propertyrentals; 0 = no bound).

## `minBathrooms` (type: `integer`):

Rentals with at least this many bathrooms (category propertyrentals; 0 = no bound).

## `searchDetails` (type: `boolean`):

Off: the listing as the list shows it (id, link, title, price, city, primary photo, listing date, status, delivery, the seller's name and id). On: also the item page's fields (description, condition, coordinates, category, every photo and the video, vehicle fields, the shipping price, related listing ids); slower.

## `tagListings` (type: `boolean`):

Off: no tags. On: four labels a language model reads from the listing's words: what the post is (for sale, for rent, wanted, service, swap), what it is about (vehicles, property, electronics, furniture, …), who posts it (private, business or unclear; an unsure answer is unclear) and what the price means (real, a placeholder, free, none), with the model's confidence for each. Billed per tagged listing; a listing the model did not answer is not billed.

## `includeKeywords` (type: `array`):

Keep only the listings whose title (and description, with item pages) holds at least one of these words, case aside. The others are dropped before any charge.

## `excludeKeywords` (type: `array`):

Drop the listings whose title (and description, with item pages) holds any of these words, case aside (`broken`, `parts only`). Dropped listings are not charged.

## `strictLocation` (type: `boolean`):

Off: every listing Facebook shows for the city, nearby towns too (Facebook takes no radius logged out). On: only the listings in the city itself; the others are dropped before any charge.

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

Deliver only the results an earlier run with the same memory did not deliver (older ones it never delivered too: add daysSinceListed to keep a scheduled run to recent listings). For a scheduled task.

## `stateStoreName` (type: `string`):

The name of the memory `onlyNew` keeps (letters, digits, '.', '\_', '-'); empty = a name derived from the inputs.

## `maxResultsPerQuery` (type: `integer`):

Stop each link, search or city after this many listings (1 to 10,000). A listing another value of the run already delivered is skipped and not counted.

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

The most charged rows of the whole run; 0 = no cap beyond your charge limit.

## `country` (type: `string`):

The country of the connection the Actor reads through. Empty: the cities' own country where the Actor knows it, else the US. Set it to your cities' country when they are outside the US.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.facebook.com/marketplace/prague/search/?query=apartment",
    "https://www.facebook.com/marketplace/prague/home-improvements/"
  ],
  "searchQueries": [],
  "locations": [],
  "category": "",
  "minPrice": 0,
  "maxPrice": 0,
  "daysSinceListed": "",
  "sortBy": "",
  "itemCondition": [],
  "onlySold": false,
  "deliveryMethod": "",
  "minYear": 0,
  "maxYear": 0,
  "minMileage": 0,
  "maxMileage": 0,
  "transmissionType": "",
  "minBedrooms": 0,
  "minBathrooms": 0,
  "searchDetails": false,
  "tagListings": false,
  "includeKeywords": [],
  "excludeKeywords": [],
  "strictLocation": false,
  "onlyNew": false,
  "stateStoreName": "",
  "maxResultsPerQuery": 100,
  "maxItems": 50,
  "country": ""
}
```

# Actor output Schema

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

All scraped records in the default dataset. One row per listing (and one free summary row per link or search):

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

How the run went: listings and add-ons charged, free rows by status, each link's and search's walk (pages read, listings read and kept, the verdict), the source counters (requests by kind, refusals, exits and rotations, bytes), the first and last row's seconds and the memory watch.

# 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 = {
    "startUrls": [
        "https://www.facebook.com/marketplace/prague/search/?query=apartment",
        "https://www.facebook.com/marketplace/prague/home-improvements/"
    ],
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("hyperbach/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 = {
    "startUrls": [
        "https://www.facebook.com/marketplace/prague/search/?query=apartment",
        "https://www.facebook.com/marketplace/prague/home-improvements/",
    ],
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("hyperbach/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 '{
  "startUrls": [
    "https://www.facebook.com/marketplace/prague/search/?query=apartment",
    "https://www.facebook.com/marketplace/prague/home-improvements/"
  ],
  "maxItems": 50
}' |
apify call hyperbach/facebook-marketplace-scraper --silent --output-dataset

```

## MCP server setup

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