---
title: "Facebook Marketplace Search API"
method: GET
path: "/v1/facebook/marketplace-search"
tags: ["Facebook Marketplace"]
---

# Facebook Marketplace Search API

`GET /v1/facebook/marketplace-search`

## Request

- Base URL: `https://api.captapi.com`
- URL: `https://api.captapi.com/v1/facebook/marketplace-search`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Search Marketplace by keyword + city — filters, isLocal/shipsOutsideRadius, opaque cursor (2 credits).

Search Facebook Marketplace with a product keyword and a required search-origin city (searchLocation, or the location alias — no backend default city, no lat/lng required). Major US metros resolve to Facebook's numeric city-page id (verified hub scoping). Smaller US towns are geocoded and snapped to the nearest baked metro (Millington, NJ → New York) — an unknown vanity slug does not 404, it silently searches a default location (that is how a Millington guitar query returned Wisconsin vehicles). Non-US places and far unique single-word US towns still use a vanity slug. The origin is echoed as searchLocation on the envelope and inside filters — listings[].location is a different object (where the item is). Each result: title, price + priceAmount (minor units), categoryId, location{name,city,state,countryCode,latitude,longitude}, deliveryTypes, status (available|pending|sold) with isSold/isPending/isHidden, cover image, createdAt, mediaUrlsExpireAt from Meta CDN oe= (~4.4 days), plus isLocal and shipsOutsideRadius so nationwide shipped listings (SHIPPING / SHIPPING_ONSITE) are not mistaken for nearby pickups. Facebook can surface shipped inventory outside radiusMiles and can broaden the keyword (a Rawlings search may include other brands — that is Facebook, not our matcher; sortBy=creation_time is recency, not relevance). daysSinceListed is Facebook's calendar-day window (1 = since the start of yesterday, not a rolling 24 hours). Optional filters: minPrice, maxPrice, sortBy, daysSinceListed, condition, deliveryMethod, availability, radiusMiles, category. hasMore is true only when nextCursor is present (same rule as tiktok/trending-feed and truth-social/user-posts; nextCursor is always keyed, null when exhausted). Default list path is flat 2 credits (cover photo in image — photos[] only when the card has more than one). Pass details=true for description, condition, coordinates, full photo gallery, seller{} when Facebook exposes it, and distanceMiles — billed as 2 + 2 credits per enriched listing (listings the 90s deadline did not reach ship as search cards with truncatedReason=enrich_deadline and are not billed the extra 2). timings{path,fetchMs,parseMs,resolveMs,totalMs} is the catalogue template — no root fetchMs/totalMs twins. cached is always keyed (true on cache=true hit or labelled last-good; default cache=false so identical live calls each bill). A first call typically takes ~28s (up to ~50s when cold); read timings.fetchMs. Facebook's own empty search (no listings that match) is an empty 200 at 0 credits — timings.path=search_no_results — not a 56–70s 502. A login shell or parse miss with a 6h last-good page is labelled stale at 0 credits. A miss with no snapshot is 502 UPSTREAM_UNAVAILABLE or 504 UPSTREAM_TIMEOUT (0 credits) with timings.

Docs: https://captapi.com/apis/facebook-marketplace-search

## Query parameters

- `q` string, required
- `searchLocation` string, required
- `location` string
- `limit` integer
- `minPrice` number
- `maxPrice` number
- `sortBy` string
- `daysSinceListed` string
- `condition` string
- `deliveryMethod` string
- `availability` string
- `radiusMiles` integer
- `category` string
- `cursor` string
- `details` boolean
- `cache` boolean

## Response `200`

Success. The data object for this endpoint.

- object
  - `success` unknown, required
  - `data` object, required
    - `query` string: The search query you sent.
    - `searchLocation` string: Search-origin city you sent (or the location alias). Always echoed here and inside filters — not a silent default. Distinct from listings[].location.
    - `filters` object
      - `searchLocation` string: Search-origin city you sent (or the location alias). Always echoed here and inside filters — not a silent default. Distinct from listings[].location.
    - `totalReturned` integer: Number of items returned in this response.
    - `hasMore` boolean: True only when nextCursor is present. Same catalogue rule as tiktok/trending-feed and truth-social/user-posts (those two may set hasMore true with a null cursor only when truncatedReason=single_page_only).
    - `nextCursor` unknown
    - `listings` object[]
      - `platform` string: Platform identifier for this response (matches the endpoint's platform).
      - `id` string: Id of this listings item.
      - `title` string: Title of this listings item.
      - `url` string: Canonical URL of the item.
      - `price` integer: Price of the item.
      - `priceFormatted` string: Formatted price string.
      - `priceAmount` integer: Price in minor units (cents) for exact arithmetic — prefer over float price.
      - `currency` string: Currency code.
      - `categoryId` string: Category id when the platform exposes one.
      - `cityPageId` string: City page id. Example: "106224666074625".
      - `status` string: Listing availability: "available" | "pending" | "sold". Prefer this over isPublished.
      - `isSold` boolean: Convenience bool for status === sold.
      - `isPending` boolean: Convenience bool for status === pending.
      - `isHidden` boolean: Is hidden. Example: false.
      - `isPublished` boolean: Whether Facebook still publishes the listing page (their is_live). Not a livestream. Omitted when status is sold/pending — prefer status.
      - `seller` object: Seller card when Facebook exposes marketplace_listing_seller on the enriched/item path.
        - `id` string: Id of this listings item.
        - `name` string
        - `url` string: Canonical URL of the item.
      - `deliveryTypes` string[]: Facebook delivery enums (e.g. IN_PERSON, SHIPPING_ONSITE).
      - `image` string: Cover photo URL. Signed Meta CDN — check mediaUrlsExpireAt (~4.4 days from oe=).
      - `createdAt` string: Creation date (ISO 8601).
      - `location` object: Removed from the envelope root (collided with listings[].location). Read searchLocation. Each listing.location is {name,city,state,countryCode,latitude,longitude}.
        - `name` string
        - `city` string
        - `state` string
        - `countryCode` string
        - `latitude` unknown
        - `longitude` unknown
      - `mediaUrlsExpireAt` string: Earliest Meta CDN oe= expiry across image + photos. Same helper as instagram/details. Null when the URL has no parseable stamp. Archive these bytes before this instant.
      - `isLocal` boolean: true when the listing's city/state matches the search origin (or distanceMiles ≤ radiusMiles when coords exist).
      - `strikethroughPrice` unknown
      - `strikethroughPriceFormatted` unknown
      - `strikethroughPriceAmount` unknown
    - `cached` boolean: Always keyed. true on a cache=true hit or labelled last-good. Default cache=false — identical live calls each bill 2 credits.

## Other responses

- `400`: Bad request: wrong platform URL, unknown endpoint, or an invalid parameter value. Not billed.
- `401`: Missing, invalid or revoked API key. Not billed.
- `402`: Not enough credits for this request. Not billed.
- `404`: The resource does not exist or is not public. Not billed.
- `422`: A required parameter is missing or has the wrong type. Not billed.
- `429`: Rate limit reached. Wait for Retry-After seconds. Not billed.
- `502`: The platform could not be reached or returned nothing usable. Retryable, not billed. 503 and 504 use the same envelope.

## Changes

- **2026-10-19** `c9b9ac5ff1bd`: 1 breaking, 5 warning, 5 info
  - the `data/nextCursor` response's property type changed from `string` to no type for status `200`
  - removed the optional property `data/filters/daysSinceListed` from the response with the `200` status
  - removed the optional property `data/filters/maxPrice` from the response with the `200` status
  - removed the optional property `data/filters/minPrice` from the response with the `200` status
  - …7 more

[Operation history](https://skmtc.dev/captapi/apis/captapi-api/changes/v1/facebook/marketplace-search/get.md)

---

[API](https://skmtc.dev/captapi/apis/captapi-api.md) · [All operations](https://skmtc.dev/captapi/apis/captapi-api/llms.txt) · [OpenAPI document](https://skmtc.dev/captapi/apis/captapi-api/revisions/c9b9ac5ff1bd?raw)
