π Facebook Marketplace Scraper With Listings
Pricing
$19.99/month + usage
π Facebook Marketplace Scraper With Listings
Facebook Marketplace Scraper extracts listings from Facebook Marketplace. Capture titles, prices, photos, descriptions, locations, sellers, and timestamps. Ideal for product research, price tracking, local market insights, and workflows needing structured Marketplace data.
Pricing
$19.99/month + usage
Rating
5.0
(1)
Developer
API Empire
Maintained by CommunityActor stats
3
Bookmarked
36
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
Facebook Marketplace Scraper β Extract Listings, Prices & Sellers
Facebook Marketplace Listings Scraper extracts Marketplace listings, price data, and seller & location details directly from Facebook's own search and listing-detail endpoints β no browser automation on your end, no login, no HTML parsing. Give it search URLs, a keyword and location, or direct listing links, and every response comes back as typed, normalized JSON: prices, conditions, categories, seller names, coordinates and β optionally β AI-generated scam-risk and deal-score signals. After reading this you'll know exactly which fields the Actor returns, how its server-side filters work, and how to wire it into a monitoring pipeline or an AI agent.
What is Facebook Marketplace Listings Scraper?
Facebook Marketplace Listings Scraper is an Apify Actor that reads Facebook Marketplace's public search and listing-detail GraphQL surface directly over HTTP and returns one structured row per listing. It requires no Facebook account, login, or session cookies β the Actor's request session carries no cookies, and every request is routed through Apify's residential proxy by default, because Marketplace hard-blocks datacenter IPs. Each output row folds together three layers: the listing itself (title, price, condition, category), the seller and location context (name, id, city, coordinates, distance from your search center), and β only if you switch it on β AI-derived insight signals (scam-risk, deal score, quality score).
- π Scrape listings from search URLs, a
search+locationpair, or direct item URLs - π Capture seller and location signals β name, id, city, state, coordinates, distance
- π€ Optionally enrich each listing with AI (off by default, deep mode only)
- π€ Export as JSON or CSV straight from the Apify dataset
- π No proxy management β residential proxy is the built-in default
What data does Facebook Marketplace Listings Scraper collect?
Every row combines listing details, seller/location context, run-level price analytics, and β when enabled β AI-derived insight fields into one unified record.
| Data Type | Key Fields | JSON Field Names |
|---|---|---|
| Listing details | title, price, condition, category, description | title, priceFormatted, priceAmount, condition, categoryId, categoryBreadcrumb, description |
| Seller & location | seller name/id, city/state/postal code, distance from search center | sellerName, sellerId, city, state, postalCode, distanceKm, locationText |
| Price analytics | strikethrough price, discount %, run-level percentile & price band | priceAmount, strikethroughAmount, discountPercent, pricePercentile, priceBucket |
| AI-enriched insights (optional) | brand/model/size, scam-risk signal, quality & deal score | aiBrand, aiModel, aiSize, aiScamRisk, aiQualityScore, aiDealScore, aiSummary |
Why not build this yourself?
Meta does not publish a public Marketplace API for browsing or searching consumer listings β as observed on a top-ranked competing Actor's Apify Store listing on 2026-07-26, "there is no public Facebook Marketplace API." Reaching the data yourself means either driving a full browser against Marketplace's web app or reverse-engineering its internal GraphQL surface, and Facebook rotates the pieces a DIY script depends on: every GraphQL POST needs a per-page-load lsd token (plus a derived fb_dtsg/jazoest pair), and the doc_id for both the search and item-detail queries lives inside a minified, hash-named JavaScript bundle that has to be located and re-parsed on every run. On top of that, Marketplace hard-blocks datacenter IP ranges, so a script needs a residential proxy pool before it can load a single page. This Actor already does that discovery work β bootstrap-page token extraction, JS-bundle scanning for the current doc_id, and a residential proxy by default β on every run, so you get structured rows instead of maintaining a scraper against a platform with no stable public contract.
Why do developers and teams scrape Facebook Marketplace?
For resellers, flippers and pricing analysts
Local resale margins depend on knowing what things actually sell for, not list for. Pull a category or keyword across a radiusKm around a city center, sort the run by priceBucket and pricePercentile, and flag anything sitting well under the run's median for that condition β discountPercent already isolates items marked down from a strikethrough price. Filtering by daysSinceListed on a schedule turns this into a same-day alert for freshly posted, underpriced inventory before other buyers see it.
For AI engineers and agent builders
Every row is typed JSON with stable field names, so it drops into a RAG index or an agent tool call without an HTML-parsing step. A shopping or deal-finding agent can call the Actor with a search/location pair and a price band, then reason directly over priceFormatted, condition, aiScamRisk and aiDealScore (when AI enrichment is on) to rank or filter candidates before ever showing them to a user.
For researchers and market analysts
Because the Actor returns only publicly visible listing pages, it supports category- or region-level studies of second-hand market structure β price distributions by condition, category mix via categoryBreadcrumb, or listing velocity via daysListed β without touching anything behind a login wall. Run the same search on a schedule and compare pricePercentile distributions across weeks to track a category's price trend.
For developers building data products
count, daysSinceListed and the price/condition/delivery filters make it straightforward to build a scheduled Apify run per market segment and treat the dataset as a feed β combined with an Apify webhook, a new run's output can push straight into a deal-alert app, a price-tracking dashboard, or a lead-generation pipeline without you writing or maintaining the extraction layer.
How to scrape Facebook Marketplace (step by step)
- Open Facebook Marketplace Listings Scraper on its Apify Store page and click Try for free / Start.
- Provide input β no field is required, but the Actor needs at least one of
startUrls, or asearch+locationpair, to know what to browse. - Set the scope β
minPrice,maxPrice,condition,deliveryMethod,daysSinceListed,categoryIdandradiusKmnarrow results server-side;deepScrapecontrols whether listing detail pages are fetched;aiEnhancementoptionally turns on AI enrichment. - Click Start and watch the run log for progress (
Scanning search query=...,Fetching PDP details for N listing(s)...). - Open the Dataset tab and export the results as JSON, CSV, Excel, or pull them via the Apify API.
What to do when Facebook changes its structure
The Actor re-derives Facebook's session tokens (lsd, fb_dtsg, jazoest) and both GraphQL doc_id values from the live bootstrap page and its JavaScript bundles on every run, instead of hardcoding them β so many of Facebook's routine front-end changes don't require an Actor update. It is maintained, and the output schema stays stable, so your integration keeps working without changes on your end.
β¬οΈ Input
All 18 parameters are optional β the schema has no required fields, but the Actor needs at least one discovery input (startUrls, or search + location) to produce results.
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
startUrls | No | array | Facebook Marketplace search URLs and/or direct listing (item) URLs. Search URLs are paginated; item URLs (β¦/marketplace/item/<id>/) are fetched as detail-only. | ["https://www.facebook.com/marketplace/108479165840750/search/?query=iphone"] |
search | No | string | Keyword to search for. Combined with location to build a search URL internally. | "iphone 13" |
location | No | string | Marketplace location id or city slug used with search. | "108479165840750" or "seattle" |
deepScrape | No | boolean | ON: fetch each listing's detail page for description, seller, condition, category breadcrumb, extra photos. OFF: search-snippet fields only. Default true. | true |
count | No | integer, min 0 | Cap on listings collected per run across all search URLs. 0 = unlimited. Default 50. | 50 |
minPrice | No | integer, min 0 | Only listings at or above this price (whole currency units), applied server-side. | 100 |
maxPrice | No | integer, min 0 | Only listings at or below this price (whole currency units). | 500 |
daysSinceListed | No | integer, min 0 | Only listings posted within this many days. Facebook's own filter UI commonly exposes 1, 7 and 30. | 7 |
condition | No | enum, default "any" | any / new / used (any) / used_like_new / used_good / used_fair. | "used_good" |
deliveryMethod | No | enum, default "all" | all / shipping / local. | "local" |
categoryId | No | string | Restrict to a Marketplace category by numeric id. | "807311116002614" |
latitude | No | string | Override the search center latitude (used with longitude + radiusKm); also the origin for the computed distanceKm. | "40.7128" |
longitude | No | string | Override the search center longitude. | "-74.0060" |
radiusKm | No | integer, min 1 | Search radius in km around the search center. | 40 |
aiEnhancement | No | boolean, default false | OFF by default. When ON in deep mode with an API key, each listing is analyzed for brand/model/size, scam-risk, quality score, and deal score. Does nothing without a key. | false |
aiModel | No | enum, default "claude-haiku-4-5" | LLM to use for enrichment. Provider is auto-detected from the name (claude-*βAnthropic, gpt-*/o1/o3βOpenAI, gemini-*βGoogle, grok-*βxAI, deepseek-*βDeepSeek, sonar*βPerplexity, mistral-*βMistral). 22 models available. | "claude-haiku-4-5" |
aiApiKey | No | string (secret) | API key for the selected provider. Falls back to ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY/GOOGLE_API_KEY, XAI_API_KEY, DEEPSEEK_API_KEY, PERPLEXITY_API_KEY, or MISTRAL_API_KEY if left blank. | "sk-..." |
proxyConfiguration | No | object | Proxy settings. Marketplace hard-blocks datacenter IPs, so the Actor defaults to Apify residential proxy. A supplied config is honored instead. | {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} |
β οΈ The proxyConfiguration schema field prefills to {"useApifyProxy": false}, but that is only the input form's default β it is not what the Actor actually runs with. Unless you explicitly set useApifyProxy: true in your own proxyConfiguration, the Actor silently switches to Apify's residential proxy group anyway, because Marketplace rejects most datacenter IPs outright. The field only takes effect (including selecting a non-residential group) once you turn it on yourself.
Example JSON input
{"startUrls": ["https://www.facebook.com/marketplace/108479165840750/search/?query=iphone"],"search": "","location": "","deepScrape": true,"count": 50,"minPrice": 100,"maxPrice": 500,"daysSinceListed": 7,"condition": "used_good","deliveryMethod": "local","categoryId": "","latitude": "","longitude": "","radiusKm": 40,"aiEnhancement": false,"aiModel": "claude-haiku-4-5","aiApiKey": "","proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }}
Common pitfall: setting search without location (or the reverse) does nothing β the Actor cannot build a search URL from either alone, logs a warning, and the run collects zero listings unless startUrls is also supplied.
β¬οΈ Output
Every run writes one JSON row per listing to the Apify dataset, and every pushed row is billed once through the row_result charged event β the Actor never writes a separate, uncharged diagnostic or error row, so the dataset's row count is exactly what you're billed for. Rows share one fixed 53-key schema across all three scrape modes (search, deep, pdp): fields that only come from a listing's detail page are null β never omitted β when deepScrape is off, so the dataset's column set never changes between modes. The default dataset view surfaces 21 of those columns for readability (scrapeMode, id, title, searchQuery, priceFormatted, priceAmount, currency, discountPercent, pricePercentile, priceBucket, condition, sellerName, city, distanceKm, daysListed, listingUrl, primaryImageUrl, detailFetched, aiScamRisk, aiDealScore, scrapedAt); switch the dataset view to see or export the full record. Results can be downloaded as JSON, CSV, Excel, or XML from the Dataset tab, or pulled through the Apify API.
Note: the output field aiModel (the product model the AI extracted from the listing text, e.g. "iPhone 13") is unrelated to the input parameter of the same name (aiModel, which LLM to run) β don't confuse the two when mapping fields downstream.
Scraped listing
{"scrapeMode": "deep","id": "1234567890123456","title": "iPhone 13 128GB","searchQuery": "iphone","listingUrl": "https://www.facebook.com/marketplace/item/1234567890123456/","facebookUrl": "https://www.facebook.com/marketplace/108479165840750/search/?query=iphone","priceFormatted": "$450","priceAmount": 450,"currency": "USD","strikethroughPriceFormatted": "$550","strikethroughAmount": 550,"discountPercent": 18,"priceBucket": "250_500","pricePercentile": 62,"comparablePrice": null,"comparablePriceType": null,"minListingPrice": null,"maxListingPrice": null,"locationText": "New York, New York","city": "New York","state": "New York","postalCode": null,"latitude": 40.71,"longitude": -74.0,"distanceKm": 3.2,"listedAt": "2026-06-28T12:00:00.000Z","daysListed": 4,"sellerName": "Jane D.","sellerId": "100000000000000","condition": "Used - good","listingAttributes": [{ "name": "condition", "value": "used_good", "label": "Used - good" }],"categoryId": "807311116002614","categoryBreadcrumb": "Electronics > Cell Phones","description": "Great condition, includes charger and original box.","sellerBlurb": null,"primaryImageUrl": "https://scontent.xx.fbcdn.net/v/photo1.jpg","imageAltText": "May be an image of phone","imageUrls": ["https://scontent.xx.fbcdn.net/v/photo1.jpg","https://scontent.xx.fbcdn.net/v/photo2.jpg"],"listingPhotos": [{ "uri": "https://scontent.xx.fbcdn.net/v/photo1.jpg", "width": 720, "height": 720, "accessibilityCaption": "May be an image of phone" }],"listingVideo": [],"isSold": false,"isPending": false,"isLive": true,"isHidden": false,"detailFetched": true,"scrapedAt": "2026-07-02T10:00:00.000Z","aiBrand": "Apple","aiModel": "iPhone 13","aiSize": "128GB","aiScamRisk": "low","aiQualityScore": 82,"aiDealScore": 71,"aiSummary": "Well-described used iPhone 13 priced below the run's median for its condition."}
categoryBreadcrumb and sellerBlurb are parsed best-effort from Facebook's own display sections, which are not a fixed schema β both can be null even in deep mode if Facebook's markup for that listing doesn't match a known pattern. aiBrand through aiSummary stay null unless aiEnhancement is true, deepScrape is true, and a resolvable API key is present.
How does Facebook Marketplace Listings Scraper compare to other Facebook Marketplace scrapers?
| Feature | Facebook Marketplace Listings Scraper | Generic alternative |
|---|---|---|
| Documented fields per row | 53 typed JSON keys | 14β26 fields, as documented on the three top-ranked competing Apify Store listings (observed 2026-07-26) |
| Schema across scrape modes | One fixed 53-key schema; unfetched detail fields are null, never dropped | Field set changes by mode β e.g. priceNumericβpriceAmount, thumbnailUrlβprimaryImageUrl between fast/deep output, as shown on a top-ranked competitor's listing (observed 2026-07-26) |
| AI-derived insight fields | Optional scam-risk, quality-score and deal-score signals, across 7 LLM providers | Not documented on the three top-ranked competing listings (observed 2026-07-26) |
| Discovery input | Search URLs, keyword + location, or direct listing URLs, all via startUrls | Varies by Actor; one top-ranked competitor's keyword search is a client-side title filter over a location feed rather than a server-side search (observed 2026-07-26) |
| Proxy requirement | Residential proxy on by default; no setup needed | Proxy country/config is a manual input field on the compared listings (observed 2026-07-26) |
If you're building an AI agent or RAG pipeline, the output-format row is the decision-maker β parsing HTML inside an agent loop is a reliability failure mode, not a feature. A fixed, typed schema across modes means your downstream code doesn't need mode-specific branching either.
How many results can you scrape with Facebook Marketplace Listings Scraper?
There is no hard cap coded into the Actor itself. count (default 50, 0 = unlimited) sets how many listings a run collects across all supplied search URLs combined; direct listing URLs passed in startUrls are always processed in addition to that cap, since each is a single detail fetch rather than a paginated search. Internally, search results are pulled in pages of 24 listings via a cursor, and pagination keeps requesting the next page until Facebook's own response reports no next page, the cursor comes back empty, or your count is reached β whichever happens first. Facebook's own search feed is therefore the real ceiling: once it stops returning a next page, there's nothing further for that query to collect. No benchmark run time or throughput figure is published for this Actor.
Integrate Facebook Marketplace Listings Scraper and automate your workflow
Facebook Marketplace Listings Scraper works with any language or tool that can send an HTTP request.
REST API integration
from apify_client import ApifyClientclient = ApifyClient("<APIFY_API_TOKEN>")run = client.actor("facebook-marketplace-listings-scraper").call(run_input={"search": "iphone 13","location": "108479165840750","minPrice": 100,"maxPrice": 500,"deepScrape": True,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["title"], item["priceFormatted"], item["sellerName"])
Works in Python, Node.js, Go, Ruby, cURL.
Automation platforms (n8n, Make, LangChain)
Facebook Marketplace Listings Scraper is a regular Apify Actor, so it runs on Apify's native platform integrations: the Apify node in n8n and the Apify module in Make can start a run with a chosen input and pull the resulting dataset items straight into a workflow, no custom HTTP call required. For agent frameworks, Apify's LangChain integration (ApifyDatasetLoader / ApifyActorsTool) can trigger a run or load a finished dataset directly as a step in an agent chain.
Is it legal to scrape Facebook Marketplace listings?
Scraping Facebook Marketplace's public listing pages is generally lawful; the more relevant constraints here are Facebook's Terms of Service and database/copyright rights over the compiled listing data, not privacy law. Facebook Marketplace Listings Scraper returns only publicly available listing data β Marketplace serves search and listing pages to any visitor without requiring login, and the Actor never authenticates or reads anything behind a login wall. Because rows are product/listing records rather than personal profiles, this sits under terms-of-service and database-rights considerations. One field is a partial exception: sellerName is the seller's own public display name, so apply the same care to bulk or commercial use of that specific field that you would to any other public personal identifier. Consult legal counsel for commercial use cases involving bulk personal data.
β Frequently asked questions
Does Facebook Marketplace Listings Scraper work without a Facebook account?
Yes. The Actor holds no cookies and never logs in β it reads Facebook Marketplace's public search and listing-detail GraphQL endpoints directly. No Facebook account, session, or credentials are required as input.
How often is the scraped data updated?
Every run fetches live from Facebook at the moment it runs β there is no caching layer. Re-run the Actor (manually or on an Apify schedule) to get current prices, availability and listing status.
What happens if a listing is sold, removed, or already gone by the time the Actor fetches it?
The row is still returned with whatever the search result or detail page reported. isSold, isPending, isLive and isHidden reflect Facebook's own status flags at scrape time, and detailFetched is false if a listing's detail page couldn't be merged in deep mode β the base search-snippet fields are still saved rather than dropping the row entirely.
Can I scrape private or login-gated Marketplace content?
No. Only content Facebook serves on its public search and listing pages is returned. Anything gated behind a Facebook login β messages, saved searches, a seller's full profile β is out of scope and not accessed by this Actor.
Can I combine search URLs with a search keyword and location in the same run?
Yes. If you provide both startUrls and a search + location pair, the Actor builds a search URL from search/location and adds it to your startUrls list β all of them are scraped together in the same run, and listings are deduplicated by id across every URL.
Does Facebook Marketplace Listings Scraper work for AI agent workflows and LLM pipelines?
Yes. It's callable as an HTTP endpoint through the Apify API by any agent framework, and every response is typed JSON with stable field names β no HTML, no parsing step before passing it to an LLM or tool call.
How does Facebook Marketplace Listings Scraper handle Facebook's anti-bot system?
It routes every request through Apify's residential proxy by default (Facebook blocks most datacenter IP ranges outright), re-derives Facebook's per-page-load session tokens (lsd, fb_dtsg, jazoest) and both GraphQL doc_id values from the live page on every run rather than hardcoding them, retries failed pagination requests on a fresh proxy session, and retries detail-page fetches up to 3 times.
How does Facebook Marketplace Listings Scraper compare to other Facebook Marketplace scrapers?
As observed on the Apify Store on 2026-07-26, the three top-ranked competing Actors document 14β26 fields per listing and no built-in AI enrichment; this Actor documents 53 fields per row and optional AI-derived scam-risk, quality and deal scores across 7 LLM providers. See the comparison table above for the full breakdown.
Does Facebook Marketplace Listings Scraper return data in a format LLMs can use directly?
Yes. Every row is typed, normalized JSON with stable field names β pass it directly into an LLM's context window, index it into a vector store, or route it through an agent tool without a parsing step.
Can I use Facebook Marketplace Listings Scraper without managing proxies?
Yes. Unless you supply your own proxyConfiguration with useApifyProxy: true, the Actor automatically runs on Apify's residential proxy group β no proxy setup, country selection, or pool management required on your end.
What happens when Facebook changes its Marketplace structure or blocks the scraper?
The scraper is maintained, and the output schema stays stable β field names and types don't change on your end. Because session tokens and GraphQL doc_id values are re-extracted from the live page on every run rather than hardcoded, the Actor already absorbs many of Facebook's routine front-end changes without needing an update.
π¬ Your feedback
Found a bug, an empty field that should be populated, or a Marketplace surface this Actor doesn't cover yet? We want to know β use the Issues tab on the Actor's Apify Store page to report it. Feedback there is what keeps this Actor's field coverage and token/doc_id extraction current as Facebook's Marketplace front end evolves.