# Changelog of Facebook Marketplace Scraper — Search Results Export (`devilscrapes/facebook-marketplace-scraper`) Actor

- **URL**: https://apify.com/devilscrapes/facebook-marketplace-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/devilscrapes/facebook-marketplace-scraper.md

## Changelog

### 0.1.0 — 2026-09-19

Initial implementation. Exports public Facebook Marketplace search
results (title, price, seller, city/state, delivery types) for one or
more search queries and a buy-location, via `curl-cffi` + a Relay
persisted-query GraphQL call — no login, no browser automation.

- `curl_cffi.requests.AsyncSession` (`impersonate="chrome131"`) bootstrap
  `GET` against `facebook.com/marketplace/category/search/`, extracting
  the `CometMarketplaceSearchContentContainerQuery` preloader's own
  `queryID`/`variables` blob verbatim from the page's `data-sjs` JSON.
- `doc_id` self-heal: on a hard `errors[]` response, re-derives the
  current persisted-query id from the search page's own `rsrc.php` JS
  bundles, caches it in a named key-value store, and retries once.
- NDJSON response parsing (one `json.loads` per line, `Content-Type`
  header ignored) with a binary ok/error classification and a genuinely
  empty page (`edges: []`, no `errors` key) treated as a real,
  successful zero-result answer — never an error, never a signal to
  stop early.
- Run-wide `listing_id` dedupe across every query in one run — a
  listing that turns up under two different search terms is pushed and
  charged once.
- Pay-per-event billing: `actor-start` ($0.20, once per run, gated
  behind the first real delivery) + `listing-scraped` ($0.005, once per
  unique row pushed) — a run that delivers nothing is billed nothing.
- Per-query fault isolation — one query's bootstrap/search failure never
  aborts the rest of the batch.
- Default `proxy_configuration` is no Apify Proxy at all — live recon
  (2026-09-19) cleared the public search endpoint with no proxy from
  this machine; customers may opt in to Residential.
