All posts

Export Facebook Marketplace Listings to CSV (Step by Step)

November 8, 2026

You want Marketplace listings in a spreadsheet: to compare prices, to track a market, or to hand a client a list. Marketplace has no export button. Here are two routes, one manual and one scripted, and a column plan so the sheet is useful later.

Route 1: by hand, for under 30 listings

  1. Open Marketplace, set your location and radius, and search.
  2. Apply filters: price range, condition, date listed.
  3. Open each listing and copy title, price, location, listed date and URL into a sheet.

It is slow but fine for a one-time check. Keep the URL in every row so you can come back. Note the date you collected each row too, since prices drop and listings sell within days.

Route 2: a script, for hundreds of listings

Meta has no public API for reading listings Meta for Developers, so a script needs a source that returns listing search results as JSON. The script below calls a search, finds the list of listings in the response, flattens every field into columns with pandas, and writes a CSV that opens cleanly in Excel.

import os, requests, pandas as pd

KEY = os.environ["SCRAPEIO_API_KEY"]
H = {"x-api-key": KEY}
BASE = "https://scrapeio.com/v1/facebook/marketplace/search"
params = {"query": "standing desk", "lat": "40.7128", "lng": "-74.0060",
          "radius_km": "30", "condition": "used_good"}

def first_list(obj):
    if isinstance(obj, list):
        return obj
    if isinstance(obj, dict):
        for v in obj.values():
            found = first_list(v)
            if found and isinstance(found[0], dict):
                return found
    return []

rows, cursor = [], None
for page in range(5):                      # 5 pages = 5 credits
    if cursor:
        params["cursor"] = cursor
    data = requests.get(BASE, params=params, headers=H, timeout=60).json().get("data") or {}
    rows += first_list(data)
    cursor = data.get("cursor") if isinstance(data, dict) else None
    if not cursor:
        break

df = pd.json_normalize(rows)               # nested fields become dotted columns
df = df.drop_duplicates()
df.to_csv("listings.csv", index=False, encoding="utf-8-sig")
print(df.shape, list(df.columns)[:15])

Two details matter. json_normalize turns nested objects like a location into columns such as location.city, so you don't have to know the shape ahead of time. And utf-8-sig adds the byte-order mark Excel needs to show accents and currency symbols correctly. The cursor key can differ by source; if paging stops early, print data.keys() and use the key you see.

A column plan

After the first export, keep only what you need and rename columns to plain names:

ColumnKeep because
listing_idDeduplicate across runs
titleGroup similar items
price, currencyThe point of most exports
city, distanceLocal price differences
conditionNew and used are separate markets
listed_atHow fresh, how long unsold
urlGo back to the source
collected_atPrices change; date every snapshot

Leave out seller names unless your use needs them. For price research it never does.

Cleaning steps before you analyze

  • Convert price to a number. Remove currency symbols and commas.
  • Drop prices of 0 or 1. Those are placeholders.
  • Drop duplicates by listing id; reposted items get new ids, so also check title plus price plus city.
  • Split by condition before taking medians.

Quick analysis in the spreadsheet

Once the CSV is clean, a few formulas answer most questions. Assuming prices are in column C and condition in column E:

  • Median price: =MEDIAN(C2:C500)
  • Median for one condition: =MEDIAN(FILTER(C2:C500, E2:E500="used_good")) in Google Sheets or Excel 365
  • Middle 50% range: =QUARTILE(C2:C500,1) and =QUARTILE(C2:C500,3)
  • Count by city: a pivot table with city in rows and count of listing id in values

Sort by price and read the cheapest ten listings by hand. They are either the best deals or the obvious scams, and you want to know which before you trust the median.

Google Sheets instead of Excel

Import the CSV with File > Import. To refresh on a schedule, run the script daily and append to the same file with a collected_at column, or push rows to a sheet with the Google Sheets API.

Cost

Each search page is one call. Five pages for each of 10 searches is 50 calls, about $0.09 at $1.88 per 1,000. A daily refresh of that set is about 1,500 calls a month, or under $3.

How to do it with ScrapeIO

The script uses the Facebook Marketplace search API. Get the lat and lng for any city from the Marketplace location search API, and add details for a single row with the Marketplace item API. Calls that fail or return nothing are not charged.

Sources

Checked on 8 November 2026 from each vendor's own pages. Prices and limits change; follow the links before you decide.

100 free credits, no card. Credits never expire.

Get API key