Facebook Marketplace Scraper
Pricing
from $0.50 / 1,000 record scrapeds
Facebook Marketplace Scraper
Reliable Facebook Marketplace scraper. Works without login — extracts titles, prices, full descriptions, GPS, photos, and category attributes (vehicle make/year/mileage, property bedrooms). Built-in monitoring mode for incremental scraping. Multi-source SSR JSON parser handles FB shape changes.
Pricing
from $0.50 / 1,000 record scrapeds
Rating
0.0
(0)
Developer
kata Kuri
Actor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Reliable, no-login Facebook Marketplace scraper. Returns clean JSON with title, price, full description, photos, GPS coordinates, condition, category, and category-specific attributes (vehicle make/model/year/mileage, property bedrooms/bathrooms, etc.).
Works without cookies for 90%+ of public listings. Most other scrapers go silent the moment Facebook rotates its SSR shape — this one walks the inlined JSON and merges every sibling target node, so you don't lose half the fields when FB changes things.
Why this scraper
| This actor | Typical alternative | |
|---|---|---|
| Anonymous mode | ✓ default — no cookies needed | Often "required", silently fails |
| Login wall handling | Content-aware: serves through soft overlays | Hard-fails on /login redirect |
| Description, GPS, photos | Extracted from inlined SSR JSON anonymously | Often null without cookies |
| SSR shape changes | Multi-source merge from every sibling target node | Returns partial / null when FB rotates |
| Honest completeness flag | _completeness: "basic" | "full" | Marks partial data as full |
| Cross-run dedup | Built-in monitoring mode | Add-on / missing |
| Incremental "since X" | untilDate filter | Missing |
| Strict keyword match | strictMatch: true removes broad-match noise | Missing |
| Auto same-country proxy | Picks US / GB / DE / FR / etc. from city | Manual config |
| Pricing (full detail, 1K) | $1.51 (Starter+), $2.72 (Free) — pay-per-event | $2.60–$44 / 1K + subscriptions |
Quickstart
1. Search by keyword + city
{"searchQuery": "iphone 15","city": "newyork","maxResults": 50,"scrapeDetails": true,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
2. Browse a category
{"city": "losangeles","category": "furniture","maxResults": 100,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
3. Drop in raw Marketplace URLs
{"searchUrls": ["https://www.facebook.com/marketplace/sanfrancisco/cars?minPrice=10000&maxPrice=30000","https://www.facebook.com/marketplace/seattle/electronics"],"scrapeDetails": true,"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
4. Incremental "what's new since yesterday"
{"searchQuery": "macbook pro","city": "austin","scrapeDetails": true,"monitoringMode": true,"monitoringStoreName": "fb-macbook-austin","untilDate": "2026-04-25","proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Schedule this hourly; you'll only ever pay for net-new listings.
Inputs
Search
| Field | Type | Default | Description |
|---|---|---|---|
searchUrls | string[] | — | Paste any Marketplace URL: /marketplace/<city>/, /marketplace/<city>/<category>, /marketplace/<city>/search?query=.... Combinable with the search-builder fields. |
searchQuery | string | — | Keyword. Combined with city / category to build a URL. |
city | string | — | City slug. Use Facebook's slug (e.g. newyork, losangeles, london, paris, berlin). The actor ships shortcuts for the most common spellings. |
category | enum | — | vehicles, cars, phones, furniture, clothing, property-rentals, appliances, etc. (full list in input schema). |
sortBy | enum | best-match | newest, price-low, price-high, distance, best-match. |
condition | enum | — | new, used-like-new, used-good, used-fair. |
minPrice / maxPrice | int | — | Price filter (in the city's local currency). |
radiusKm | int | FB default | Search radius from city center, max 100 km. |
Scope and cost control
| Field | Type | Default | Description |
|---|---|---|---|
maxResults | int | unlimited | Hard cap on listings returned. The crawler stops as soon as this is hit. |
scrapeDetails | bool | true | Visit each listing's detail page for description, GPS, full photo set, condition, category attributes. Cheaper to leave off if you only need card data. |
maxConcurrency | int | 3 | Parallel browser tabs (1–10). Keep low (2–3) to stay under FB's bot-detection threshold. |
Filters
| Field | Type | Default | Description |
|---|---|---|---|
strictMatch | bool | false | When searchQuery is set, drop any listing whose title doesn't contain every word of the query (accent-insensitive). Filters out FB's broad-match noise — e.g. "iphone 15" no longer returns chargers and cases. |
untilDate | string | — | ISO date (2026-04-25 or 2026-04-25T00:00:00Z). Skip listings posted before this date. Only applied when detail-scraping captures publishedAt. |
Incremental scraping
| Field | Type | Default | Description |
|---|---|---|---|
monitoringMode | bool | false | Track listing IDs across runs in a named Key-Value store. Skip any IDs already pushed in earlier runs. Combine with a schedule for an incremental feed. |
monitoringStoreName | string | fb-marketplace-seen | Name of the KV store. Use different names to keep separate watchlists (fb-iphones-nyc, fb-cars-austin, …). |
Authentication (optional)
| Field | Type | Default | Description |
|---|---|---|---|
cookieState | string | — | Optional Facebook session cookies as JSON. Anonymous works for public card and detail data; supply cookies only if you need seller name/profile (FB hides those server-side anonymously). |
Infrastructure
| Field | Type | Default | Description |
|---|---|---|---|
proxyConfiguration | object | — | Standard Apify proxy config. Residential strongly recommended — datacenter IPs are blocked by Facebook. If you set a city and use residential without a countryCode, the actor auto-picks a same-country proxy for you (e.g. US for New York, GB for London, DE for Berlin). |
Output schema
Each row in the dataset:
{"listingId": "1279908470484354","title": "iPhone 12 Pro Max - Mint condition","price": 425,"currency": "USD","condition": "Used - Like New","category": "807311116002614","description": "Selling my iPhone 12 Pro Max, 256GB, mint condition. Battery health 89%. No scratches. Comes with original box and charger…","city": "Austin","location": "Austin, TX","latitude": 30.267153,"longitude": -97.743057,"images": ["https://scontent…/photo1.jpg","https://scontent…/photo2.jpg","..."],"sellerName": null,"sellerProfileUrl": null,"deliveryType": "IN_PERSON","listingUrl": "https://www.facebook.com/marketplace/item/1279908470484354/","publishedAt": "2026-04-30T23:00:11.000Z","scrapedAt": "2026-05-02T08:00:00.000Z","attributes": {"subtitles": ["256 GB", "Like new"]},"isSold": false,"isPending": false,"_completeness": "full"}
Vehicle listings additionally fill attributes.vehicleMake, vehicleModel, vehicleYear, mileage, mileageUnit, transmission, fuelType, exteriorColor, interiorColor, vehicleSellerType, vin.
Property listings additionally fill attributes.bedrooms, bathrooms, areaSize, areaUnit, propertyType, yearBuilt.
_completeness is "basic" when only card-level data was captured (search-only run, or detail page didn't return a usable SSR blob). "full" means detail-page enrichment landed.
sellerName and sellerProfileUrl are null in anonymous mode — Facebook hides seller PII server-side without login.
Pricing
Pay-per-event with automatic Apify-plan discounts. You pay only for what's scraped — no subscription, no minimums.
| Event | Free | Starter | Scale | Business |
|---|---|---|---|---|
| Record scraped (per 1,000) | $0.70 | $0.50 | $0.50 | $0.50 |
| Detail-enriched listing (per 1,000) — fires when full description, GPS, photos, and category attributes are extracted | $2.00 | $1.00 | $1.00 | $1.00 |
| Actor start (per run) | $0.02 | $0.01 | $0.009 | $0.008 |
Higher Apify plans (Starter / Scale / Business) automatically receive the discounted rates — nothing to configure.
What a typical run costs
| Mode | Free plan | Starter / Scale / Business |
|---|---|---|
Search-only (1,000 listings, scrapeDetails: false) | $0.72 | $0.51 |
| Full detail (1,000 listings, default) | $2.72 | $1.51 |
| Search-only (10,000 listings) | $7.02 | $5.01 |
| Full detail (10,000 listings) | $27.02 | $15.01 |
Plus standard Apify residential-proxy traffic, billed to your account separately.
Cost vs alternatives
| Scraper | Full-detail 1K listings | Subscription |
|---|---|---|
| This actor (Starter+) | $1.51 | none |
| apify/facebook-marketplace-scraper | $2.60 | none |
| memo23/facebook-marketplace-cheerio | usage-based | $25/mo |
| datavoyantlab/facebook-marketplace-scraper | $0.45–$4.00 | $28/mo |
| webdatalabs/deal-finder | $44.00 (deals only) | none |
How it stays reliable
Three defensive layers, in priority order:
- Inlined SSR JSON — Facebook ships every page with multiple
<script type="application/json">blobs containing the full GraphQL responses. The actor scans every script, walks the JSON tree (up to 20 levels deep), and merges sibling target nodes (targetcarries description,marketplace_listing_renderable_targetcarries condition, separate blob carries the photo array). Other scrapers grab the first match and miss half the data. - Live
/api/graphqlinterceptor — when the page actually fires GraphQL calls (logged-in sessions or client-side re-fetches), those payloads are parsed too. Same parser, same field set. - Open Graph meta tags —
og:title,og:description(truncated),og:imageare always populated even if FB rotates its SSR shape.
Plus:
- Per-context warm-up — visit
/marketplace/once before the real navigation, so FB's bot detector sees a "browser that browsed first" instead of a clean context jumping into a deep search URL. - Content-aware block detection — only fail on
/loginredirects when there's no marketplace data on the page; FB often serves the full data with a login overlay on top. - ID-matching guard — fields are only merged from items whose
idmatches the target listing, so the "Similar items" sidebar can't leak into your row.
Common scenarios
Build a price-tracking feed
{"searchQuery": "iphone 15","city": "newyork","scrapeDetails": false,"monitoringMode": true,"monitoringStoreName": "fb-iphone15-nyc-prices"}
Schedule hourly. Each run only pushes listings you haven't seen — perfect for a (timestamp, listingId, price) time series.
Monitor a niche category
{"city": "boston","category": "musical-instruments","monitoringMode": true,"monitoringStoreName": "fb-instruments-boston","untilDate": "2026-04-01","scrapeDetails": true}
You only get instruments posted in April or later, never re-fetched once seen.
Strict comparison shopping
{"searchQuery": "macbook pro 14","city": "sanfrancisco","strictMatch": true,"scrapeDetails": true}
strictMatch drops any listing whose title doesn't contain both "macbook" and "pro" — no chargers, no docks, no accessories.
Used-car research
{"city": "dallas","category": "cars","minPrice": 5000,"maxPrice": 25000,"condition": "used-good","sortBy": "newest","scrapeDetails": true,"maxResults": 200}
Returns full vehicle attributes (vehicleMake, vehicleModel, vehicleYear, mileage, transmission, fuelType) for each listing.
FAQ
Q: Why does anonymous mode work? Other scrapers say login is required.
Facebook serves Marketplace card and detail data anonymously to keep the page indexable by Google. The data is in inlined JSON blobs alongside the rendered HTML. Most scrapers only listen to live /api/graphql calls (which require login on detail pages) and miss the inlined version. This actor reads the inlined version directly.
Q: When do I need cookies?
Only if you need sellerName or sellerProfileUrl. Facebook hides those fields server-side from anonymous viewers regardless of how you scrape.
Q: How do I supply cookies?
Export your session as JSON (using the EditThisCookie browser extension, or Playwright's context.storageState()) and paste into cookieState. Format: { "cookies": [...] }.
Q: Why residential proxy and not datacenter? Facebook blocks datacenter IPs aggressively (CAPTCHA, login redirect, empty pages). Residential proxies look like normal home users and pass through.
Q: Why is price sometimes 0 even when the listing isn't free?
Some sellers leave the price field blank, and Facebook displays "$0" or "Free" placeholder text. The actor reflects what FB shows. Filter price > 0 if you want priced-only.
Q: What does _completeness mean?
"basic"— only card-level data (title, price, location, cover image, listing URL)."full"— detail-page enrichment landed (description, full photo array, GPS, category attributes).
Q: My run failed with "Blocked: login-required" — what now?
Rare since the content-aware block detection update. If it does happen, switch the proxy country (e.g. proxyConfiguration.countryCode: "GB") or rerun with maxConcurrency: 1. FB's bot detection occasionally flags specific IPs.
Q: Can I scrape sold listings?
Yes. Look at isSold and isPending in the output — both come through on detail pages.
Q: Does this work outside the US?
Yes — anywhere Facebook Marketplace is available. Use Facebook's city slug in city (e.g. london, paris, berlin, sydney, toronto, mexico) or paste the full Marketplace URL into searchUrls. The actor knows 60+ city → country mappings for auto-proxy selection; for unlisted cities, set proxyConfiguration.countryCode manually.
Q: How do I run incremental scrapes?
Set monitoringMode: true and pick a monitoringStoreName. The actor stores seen listing IDs in an Apify Key-Value store and skips them on subsequent runs. Combine with a schedule (Apify Schedules tab) to build a hands-off feed of net-new listings.
Issues / contact
Open an issue on this actor's page on Apify Store, or contact the maintainer through the Apify console.