1. 2scraper
  2. Classifieds, property & travel
  3. Facebook Marketplace
Open source · MITRuns with no key, proxy or account

Facebook Marketplace Scraper

Marketplace listings by keyword, category, location and price, read logged out and paginated past the first 24.

  • Playwright
  • Selenium
  • Puppeteer
  • Scraping Browser API
  • JSON
  • CSV
facebook-marketplace-scraper
# Keyword search
$ python3 playwright_scraper.py --query bike --location nyc
✓ 3 sample rows · 33 columns in sample_output.json
0accounts, cookies or keys needed
150listings from one Chicago search in 35 s (Oct 2026)
~600listings per search per exit before Facebook's rate limit (Oct 2026)
3browser engines on one shared fetch loop
Available Facebook Marketplace scrapers

What the Facebook Marketplace scraper collects

Scrapes Facebook Marketplace search and category pages in any Marketplace location, without logging in: title, price, location, listing time, photo, sold or pending status, delivery options and, on vehicles, the mileage. With --details it also opens each listing for its description, condition, category, every photo and the currency code. Output is JSON or CSV with a .meta.json sidecar.

Keyword search

Input: A keyword and a Marketplace location slug

One row per listing with price, location, listing time, photo, status and delivery options, paginated past the 24 a logged-out page embeds.

Filtered search

Input: A keyword, location, price range, sort and listing age

The same rows, using Marketplace's own price, sort and days-since-listed filters.

Category browse

Input: A category slug and a location

Listings from a Marketplace category such as vehicles, where the subtitle carries the mileage.

Listing details

Input: A search, or listing URLs, with --details

Each listing's own page as well: description, condition, category, all photos, shipping and the ISO currency code.

Quick start

From zero to Facebook Marketplace data in 3 steps

  1. Install

    Clone the repository and install one browser engine. Python 3.9+.

    $ git clone https://github.com/2scraper/facebook-marketplace-scraper.git
    $ cd facebook-marketplace-scraper
    $ python3 -m venv .venv && source .venv/bin/activate
    $ pip install -r requirements-playwright.txt
    $ playwright install chromium
  2. Run a scraper

    Pick what you need and run it. Every flag is documented in the README.

    $ python3 playwright_scraper.py --query bike --location nyc
  3. Get structured data

    Rows land in JSON or CSV (--format), with a .meta.json sidecar recording status, pages fetched and why the run stopped.

Output

Facebook Marketplace data fields

33 columns per row in a predictable schema. The most useful ones:

FieldWhat it holds
listing_idMarketplace listing id
titleListing title
priceAsking price as a number (0.0 for a free item)
price_textPrice as displayed, e.g. "$1,100"
original_priceStruck-out earlier price, when shown
currencyISO code; left empty for a bare "$" unless --details reads it
cityListing city
stateListing state or region
listed_atWhen it was listed (UTC)
is_soldMarked sold
is_pendingMarked pending
subtitleOn vehicles, the mileage ("73K miles")
delivery_types_jsonDelivery options such as IN_PERSON or DOOR_PICKUP
descriptionSeller's description (--details)
conditionItem condition (--details)
photo_urls_jsonEvery photo URL (--details)
[
  {
    "sku": "facebook-listing-1655081135947682",
    "source": "facebook.com",
    "category": "listing",
    "title": "Kugoo Pink Kids Bike with Training Wheels",
    "brand": null,
    "price": 50.0,
    "currency": "USD",
    "price_source": "item_page",
    "product_url": "https://www.facebook.com/marketplace/item/1655081135947682/",
    "image_url": "https://scontent.fakx4-2.fna.fbcdn.net/v/t39.84726-6/829909982_1767649754356695_3015029…",
    "scraped_at": "2026-10-06T09:36:02Z",
    "listing_id": "1655081135947682",
    "price_text": "$50",
    "original_price": null,
    "city": "New York",
    "state": "NY",
    "location_text": "New York, NY",
    "listed_at": "2026-10-02T20:30:44Z",
    "is_sold": false,
    "is_pending": false,
    "status": "AVAILABLE",
    "category_id": "1658310421102081",
    "subtitle": null,
    "delivery_types_json": "[\"IN_PERSON\"]",
    "description": "Vibrant pink Kugoo kids bicycle has a white front basket and matching training wheels. …",
    "category_name": "Bicycles",
    "category_slug": "bicycles",
    "condition": "Used - like new",
    "attributes_json": "[{\"name\": \"Condition\", \"value\": \"Used - like new\"}]",
    "photo_urls_json": "[\"https://scontent.fakx4-2.fna.fbcdn.net/v/t39.84726-6/829909982_1767649754356695_30150…",
    "shipping_offered": false,
    "search_url": "https://www.facebook.com/marketplace/nyc/search/?query=bike",
    "position": 1
  },
  {
    "sku": "facebook-listing-4565211807048416",
    "source": "facebook.com",
    "category": "listing",
    "title": "Trek FX 2 Hybrid Bike Gen 4",
    "brand": null,
    "price": 620.0,
    "currency": "USD",
    "price_source": "item_page",
    "product_url": "https://www.facebook.com/marketplace/item/4565211807048416/",
    "image_url": "https://scontent.fakx4-2.fna.fbcdn.net/v/t39.84726-6/832321968_1406461511614506_4553649…",
    "scraped_at": "2026-10-06T09:36:02Z",
    "listing_id": "4565211807048416",
    "price_text": "$620",
    "original_price": null,
    "city": "North Bergen",
    "state": "NJ",
    "location_text": "North Bergen, NJ",
    "listed_at": "2026-10-04T01:45:36Z",
    "is_sold": false,
    "is_pending": false,
    "status": "AVAILABLE",
    "category_id": "1658310421102081",
    "subtitle": null,
    "delivery_types_json": "[\"IN_PERSON\"]",
    "description": "Excellent matte black Trek FX 2 hybrid bike. This aluminum frame bicycle has disc brake…",
    "category_name": "Bicycles",
    "category_slug": "bicycles",
    "condition": "Used - like new",
    "attributes_json": "[{\"name\": \"Condition\", \"value\": \"Used - like new\"}]",
    "photo_urls_json": "[\"https://scontent.fakx4-2.fna.fbcdn.net/v/t39.84726-6/832321968_1406461511614506_45536…",
    "shipping_offered": false,
    "search_url": "https://www.facebook.com/marketplace/nyc/search/?query=bike",
    "position": 2
  }
]

First 2 of 3 rows from a real run — sample_output.json. Long values shortened here.

Built for Facebook Marketplace

Handles what breaks naive Facebook Marketplace scrapers

Paginates past the logged-out 24

A logged-out search embeds 24 listings. The tool scrolls the way the page needs, keeps the pagination request the page itself sends, and replays it with each next cursor.

Rate limits end a run as partial, not empty

After about 25 next-page requests Facebook answers "Rate limit exceeded". The run stops that search with stop_reason rate_limited, keeps every row and exits 6.

No seller data, by design

Logged-out pages sometimes carry the seller's name. The tool never writes a seller field, and the test suite checks that a listing carrying one yields a row without it.

Currency is never guessed

£ becomes GBP and € becomes EUR, but a bare "$" is left empty unless --details reads the code from the listing page.

Everything built in

Scraping infrastructure included

The same tested core runs every 2scraper repository, so the hard parts work the same way on every site.

CAPTCHA handling

Detects the challenge a page really serves and, with a 2Captcha key, solves it only when it blocks the data — a capped number of solves per page.

Proxy rotation

Single proxy or a pool from a file, rotated on blocks with a fresh browser per exit. Credentials stay out of argv and logs.

Fingerprints

Optional complete device identity from the 2Captcha Fingerprint API — user agent, client hints, locale and timezone that agree with each other.

Scraping Browser API

Point --cdp-endpoint at a managed Chromium with its own exit country — no browser infrastructure to run yourself.

Honest run metadata

Every run writes a .meta.json sidecar and distinct exit codes: complete, blocked, empty and partial are never confused, and a failed run never overwrites good data.

Diff two runs

diff_runs.py compares two complete Facebook Marketplace snapshots by id — new, removed and changed rows for monitoring.

Use cases

What teams do with Facebook Marketplace data

Resale price research

See what used bikes, furniture or electronics actually ask for in a given city, filtered by price and listing age.

Deal alerts

Run a search on a schedule and use diff_runs.py to spot price drops and listings that went sold or pending.

Used-vehicle market tracking

Browse the vehicles category per city and collect prices with mileage from the subtitle.

Cross-city comparison

Run the same query in nyc, london, berlin or la and compare supply and asking prices.

Access & pricing

Free to run. Pay only for what the site requires.

Runs with no key, proxy or account

No account, cookies, key or proxy: the quick start runs with no .env at all, and the README's live runs were made logged out. Residential proxies (--proxy-file) let you read more than about 600 listings per search per exit and pick an exit country. The Scraper API mode needs a 2Captcha key and, measured Oct 2026, a Scraping Browser API profile, because the Scraper API's own pool got the login page. No captcha was met in any live run.

Optional 2Captcha services — captcha solving, the Scraping Browser API, residential proxies and fingerprints — work behind one key.

Good to know

  • About 600 listings per search per exit before Facebook's rate limit (measured 2026-10-06).
  • A price sort combined with --days-since-listed comes back empty; the tool warns first.
  • A bare "$" price has no currency code without --details.

2scraper vs. hosted scraper APIs

2scraperTypical hosted API
CodeOpen source, MIT — read and patch itClosed
CostFree; optional services billed only when usedSubscription or per request / per result
Runs onYour machine, server or CIThe vendor's infrastructure
OutputJSON/CSV files + run metadataAPI responses
When the site changesFix it yourself or open an issue / PRWait for the vendor
FAQ

Facebook Marketplace scraper FAQ

Do I need a Facebook account?

No. It reads what Marketplace shows any logged-out visitor and never logs in.

How many listings can I get per search?

About 600 per search from one address before Facebook's rate limit (measured 2026-10-06). Split the search by price or category, or rotate residential exits with --proxy-file.

Which locations work?

Any Marketplace location slug from facebook.com/marketplace/<location>/ (nyc, la, chicago, london and berlin were tested), or a numeric location id.

Does it collect seller information?

No. Sellers are private people, so no seller field is ever written, whether the page sends one or not.

What output do I get?

JSON or CSV plus a .meta.json sidecar with status, stop_reason and per-address results. Writes are atomic, and a run that finds nothing never overwrites your last good file.

Is this allowed?

Facebook's robots.txt disallows crawlers and Meta's terms forbid automated collection without permission. The tool reads only public logged-out pages; check your jurisdiction and purpose before running it.