API Reference · v1
SoldComps API
Real sold listings — price, condition, date, seller — from a single request.
No scraping setup, no stale cache, no OAuth dance.
eBay endpoints: /v1/scrape for one page at a time, async Max Mode for server-side pagination.
Plus Mercari and Poshmark sold listings, and TCGPlayer products and recent sales.
eBay active listings (sold=false) and a single-item lookup (/v1/item) are also available.
Machine-readable spec: openapi.json
New to eBay sold data? See how we compare →
Quickstart
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
"https://api.sold-comps.com/v1/scrape?keyword=iphone+15+pro&count=60"Authentication
Every endpoint on this page requires a bearer token, with two exceptions: the RapidAPI channel (below) and the Max Mode CSV download, which uses a signed token in the URL. Send your API key in this header:
Authorization: Bearer sc_YOUR_KEY_HEREAPI keys start with sc_.
Get one from the dashboard.
The free plan includes 100 requests/month, no credit card required.
The /rapidapi/scrape-ebay endpoint authenticates through the RapidAPI marketplace headers instead — see the RapidAPI section.
Optional
Authenticated requests
Optionally send your own eBay session cookies in the X-eBay-Cookies header on /v1/scrape, /v1/scrape/category, /v1/scrape/max, /api/bulk-search, and /rapidapi/scrape-ebay.
Every endpoint works without it.
How to get your cookies
- Sign in to eBay in your browser, on the same site you plan to query. A cookie from ebay.com does not work for an ebay.co.uk request.
- Open developer tools (
F12, orCmd + Option + Ion Mac) and go to the Network tab. - Reload the page and click the first document request in the list.
- Under Request Headers, copy the entire value of the
cookieheader. - Send that string as the
X-eBay-Cookiesheader. No encoding needed.
Example
curl -H "Authorization: Bearer sc_YOUR_KEY" \
-H "X-eBay-Cookies: nonsession=BAQ...; ebaysid=p2...; dp1=bu1p/QEBf..." \
"https://api.sold-comps.com/v1/scrape?keyword=iphone"Cookies you send are used only to run your requests, and are ignored for active-listing searches (sold=false).
If eBay blocks 10 requests in a row that use the same cookies, requests with those cookies return 400 with code: "cookies_expired" for 24 hours after the last block.
A request with new cookies, or without the header, works at once.
Pacing matters
Space cookie requests at least 2-3 seconds apart. Faster requests from one session trigger eBay's bot detection and get the session blocked.
Rate limits
Two limits apply per account (one shared budget across all its API keys).
Both return 429; the body's code field tells you which one was hit.
Per-minute rate limit (code: "rate_limited") — 60 requests/minute on standard plans (free, starter, growth, scale), 120 on mid-tier custom plans (100k–500k), and 240 on high-volume custom plans (1M, 2M, 4M).
A purchasable rate-limit add-on raises any key to 500 requests/minute.
Monthly quota (code: "quota_exceeded") — resets at your billing cycle anchor (not calendar UTC).
On the free plan the monthly cycle starts from your signup date, or from the end of your last paid period.
Purchased credits are used automatically when the quota runs out, so the 429 only fires when both are exhausted.
See current plan limits at /dashboard/subscription.
A rate_limited or quota_exceeded 429 carries a Retry-After header (seconds), with two exceptions: credit-only mode with no credits left, and a 429 from the API key check (its body has no code).
Rate-limit responses set X-RateLimit-* headers and quota responses set X-Usage-* headers.
The same numbers are available without spending a request from GET /usage.
X-RateLimit-Reset is a Unix epoch timestamp in seconds.
Handling 429s
if response.status == 429:
if body.code == "quota_exceeded":
stop retrying, alert ops, wait until body.reset_at
(no reset_at in credit-only mode: buy credits)
else:
wait body.retry_after seconds (a few seconds if absent), then retryOptional
Credits (pay-as-you-go)
Buy one-time API request credits at $3 per 1,000 requests — no subscription required. Credits never expire and work on any plan, including free. Purchase from the dashboard from 1,000 to 1,000,000 requests per purchase, in increments of 100.
Automatic overflow. Requests debit your subscription quota first, then your credits — no code change needed.
Credit-only mode.
To pay exclusively from credits, pass the X-Credit-Source header:
curl -H "Authorization: Bearer sc_YOUR_KEY" \
-H "X-Credit-Source: credits" \
"https://api.sold-comps.com/v1/scrape?keyword=iphone"Subscription-only mode.
To never touch purchased credits, pass X-Credit-Source: subscription-only.
Requests return 429 quota_exceeded as soon as the monthly cap is hit.
Refunds on failure. If a request fails (any non-200 response), the credit is refunded automatically.
A response paid with a credit has X-Credit-Source: credits and X-Credit-Balance: <n> headers, and does not have the X-Usage-* headers.
Errors
| Status | Meaning | What to do |
|---|---|---|
| 400 | Invalid params | Check the error body — for example a missing keyword, an out-of-range number, or an X-eBay-Cookies header with no name=value pairs. |
| 400 (code: cookies_expired) | Your eBay cookies are locked | eBay blocked 10 requests in a row that used these cookies. Send new cookies or omit the X-eBay-Cookies header. Not charged. |
| 400 (code: page_limit) | Page above 100 on /v1/scrape/category | eBay does not return results past page 100 on ebay.com, ebay.co.uk, ebay.de, ebay.fr, ebay.it and ebay.es. Use count=240 to reach more items in 100 pages. Not charged. |
| 401 | Missing or invalid API key | Verify the Authorization header. Keys start with sc_. |
| 429 (code: rate_limited) | Per-minute rate limit | Back off for the duration in Retry-After (seconds), then retry. The limit for each plan is in Rate limits above. |
| 429 (code: quota_exceeded) | Monthly quota exhausted | Stop retrying — Retry-After can be days long. Upgrade or wait until reset_at. In credit-only mode (X-Credit-Source: credits) with no credits left there is no Retry-After and no reset_at: buy credits or remove the header. |
| 429 (no code) | Too many API key checks | There is no Retry-After header. Wait a few seconds, then retry. |
| 503 (code: upstream_blocked) | Marketplace fetch failed | Usually transient — retry after a few seconds. Do not retry past page 100 on /v1/scrape, and do not retry many times with the same X-eBay-Cookies (10 blocks in a row lock them). Not charged on direct plans. |
| 503 (code: at_capacity) | Temporarily at capacity | Retry shortly. Not charged on direct plans. |
| 503 (code: service_unavailable) | Temporary internal failure | Your API key is not rejected. Retry after a few seconds. |
| 500 | Server error | Unexpected internal error. Retry with exponential backoff. |
Pagination
Each /v1/scrape request returns one page of sold listings (up to 240 items).
Increment the page parameter until hasNextPage is false.
Stop at page 100.
On ebay.com, ebay.co.uk, ebay.de, ebay.fr, ebay.it and ebay.es, eBay blocks most requests past page 100, and page 100 can still return hasNextPage: true on /v1/scrape.
Do not retry a 503 upstream_blocked past page 100.
Use count=240 to reach up to 24,000 items in 100 pages.
Past the last page.
A page past the last one returns 200 with an empty items array, hasNextPage: false, code: "past_last_page" and lastPage (also sent as the X-Past-Last-Page header).
It still counts as 1 request.
For larger jobs (50+ pages), use Max Mode — the server paginates for you.
totalItems is the count of items on the current page, not a grand total.
It can be lower than the count you requested — count is a page size (60, 120 or 240; other values round up), and items eBay renders without a parseable price or sold date are dropped.
totalResults is eBay's own reported total for your search (e.g. "14,000+").
It's a string because eBay's counts are approximate on broad searches, and null when unavailable.
# Increment page until hasNextPage is false
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
"https://api.sold-comps.com/v1/scrape?keyword=iphone+15+pro&page=1"
# then page=2, page=3, ... while hasNextPage == true/v1/scrapeSearch sold listings
Query parameters
Note: the buyingFormat query parameter (below) filters which listings are returned by format.
It shares a name with the buyingFormat field on each item in the response, which instead classifies how that listing was actually listed.
The two use different enums and serve different purposes.
keywordstringrequired- Passed directly to eBay's search bar. Supports eBay's minus-sign syntax to exclude terms — e.g. "iphone 15 pro -case -screen -lot" drops listings containing case, screen, or lot from results.
pageintegeroptionaldefault:1- Page number of eBay results to fetch. Increment until hasNextPage is false.
countinteger (60, 120, 240)optionaldefault:240- Items per page: 60, 120 or 240, for sold and active listings (sold=false). Other values are rounded up to the next size, so a request can return more items than count. Each page is one full eBay results page — the last page may contain fewer items.
ebaySiteenumoptionaldefault:ebay.com- eBay domain to scrape.
ebay.comebay.co.ukebay.deebay.frebay.itebay.esebay.caebay.com.au categoryIdstringoptionaldefault:0- eBay category ID (_sacat). Browse all 17,000+ IDs at sold-comps.com/ebay-categories. Use "0" for all categories.
sortOrderenumoptionaldefault:endedRecently- Sort order for results.
endedRecentlytimeNewlyListedpricePlusPostageLowestpricePlusPostageHighestdistanceNearest minPricenumberoptional- Minimum price filter, in listing currency.
maxPricenumberoptional- Maximum price filter, in listing currency.
itemLocationenumoptionaldefault:default- Item location filter.
defaultdomesticworldwide itemConditionenumoptionaldefault:any- Item condition filter applied as a request filter on eBay.
anynewused conditionIdnumberoptional- eBay numeric condition ID filter. Common IDs: 3 (New), 4 (Used), 1000 (Brand New), 1500 (Open box), 2750 (Like New), 3000 (Used), 7000 (For parts). Valid IDs vary by eBay category. When set, overrides itemCondition. When omitted, itemCondition applies (its default, any, is no condition filter).
buyingFormatenumoptionaldefault:all- Filter by listing format (request filter — distinct from the per-item buyingFormat response field, which classifies how a listing was actually listed and uses a different enum). "auction" = auction-only, "buyItNow" = fixed-price / Buy It Now, "acceptsOffers" = listings with Best Offer enabled. Default "all" (no format filter).
allauctionbuyItNowacceptsOffers sellerTypeenumoptional- Filter results by seller type. Only effective on EU sites (ebay.de, .fr, .it, .es). On non-EU sites the filter is silently ignored.
privatebusiness includeCompleteListingbooleanoptionaldefault:true- Include eBay completed-listing metadata (LH_Complete=1). This is what enables accurate bestOfferAccepted detection — without it, eBay does not render the "Best offer accepted" signal and bestOfferAccepted is false for nearly all items. Does not change which listings are returned: results stay sold-only (LH_Sold=1 takes precedence). Set to false only to match pre-July-2026 behavior.
soldbooleanoptionaldefault:true- When true (default), returns completed/sold listings. When false, returns ACTIVE (currently-listed) results instead. Active responses swap the sold-only fields (soldPrice, soldCurrency, endedAt, bestOfferAccepted) for active-only ones: listingType="active", the asking price in currentPrice/currentPriceMax/currentCurrency, plus watcherCount, unitsSold, acceptsOffers, and timeLeft.
soldAfterstring (YYYY-MM-DD)optional- Inclusive lower bound on endedAt. Applied after the page is scraped — sold-only, silently ignored when sold=false. See scrapedCount in the response for how to tell whether more pages will help.
soldBeforestring (YYYY-MM-DD)optional- Inclusive upper bound on endedAt. Applied after the page is scraped — sold-only, silently ignored when sold=false.
aspectFilterstring (JSON)optional- JSON object of eBay item-aspect facet filters — your HTTP client handles URL encoding automatically. Keys and values are the human-readable facet names exactly as shown in eBay's sidebar refinements (e.g. {"Brand":"Apple","Storage Capacity":"256 GB"}). Multi-select values use pipe as separator: {"Network":"Unlocked|AT&T"}. Facet names are dynamic per eBay category and vary by site language. Unrecognized facets are silently ignored by eBay. A value that is not a JSON object is ignored: the search runs with no aspect filter and no error is returned.
exactMatchbooleanoptionaldefault:true- When true (default), strips eBay's loosened-match results ("Results matching fewer words") so only items closely matching your keyword are returned. Set to false to include all results eBay returns — useful when you want maximum volume over keyword precision.
hydrateBoabooleanoptionaldefault:false- When true, items sold via Best Offer have their soldPrice updated to the actual accepted offer amount using eBay's Price Guide. Primarily useful for trading card categories where Best Offer is common. Each Best Offer item on the page is looked up, which adds response time; an item that is not in the Price Guide is a miss. eBay has Price Guide data only for items listed on ebay.com, ebay.co.uk and ebay.de. On an ebay.co.uk or ebay.de search, items listed on that site get the accepted amount in the listing currency; on every site, items listed on ebay.com get it in USD. When the hydrated price is in a different currency than the listing, boaAcceptedPrice and boaAcceptedCurrency are returned instead of overwriting soldPrice. Sold-only; ignored when sold=false. Costs 1 extra request against your quota, but only when hydration actually finds at least one match — a miss (or a keyword with no Best Offer items) costs nothing extra.
Date range filtering is post-processing.
Each request still scrapes one full page from eBay (up to count items), then filters by endedAt using soldAfter/soldBefore.
A page may return fewer items than count after filtering, and hasNextPage still reflects eBay's pagination, not the filtered set — a next page may exist but return 0 items after filtering.
To pull every sold item in a date range, paginate until hasNextPage is false, or until scrapedCount is lower than the page size (you've reached the end of eBay's results).
Best Offer price hydration costs 1 extra request.
With hydrateBoa=true, a successful hydration (at least one item's accepted offer price resolved) debits 1 additional request from your quota — at most 1 extra per request, regardless of how many items were hydrated.
If no Best Offer items are found, or all hydration attempts miss, no extra request is charged.
Primarily useful for trading card categories.
Aspect filters narrow by eBay sidebar facets.
Pass aspectFilter as a JSON object whose keys and values match the facet names in eBay's sidebar refinements.
Your HTTP client handles the URL encoding automatically.
aspectFilter={"Brand":"Apple","Storage Capacity":"256 GB"}For trading cards, filter by grade and card manufacturer:
aspectFilter={"Professional Grader":"PSA","Grade":"10","Manufacturer":"Topps"}Multi-select values use pipe: {"Grade":"9|10"}.
Facet names are dynamic per category and vary by site language.
Unrecognized facets are silently ignored by eBay.
Response fields (each item)
itemIdstring- eBay listing item ID.
urlstring- Canonical listing URL with ?nordt=true to bypass eBay's catalog redirect.
thumbnailUrlstring | null- Listing thumbnail (500px) from i.ebayimg.com. null when the listing has no product image.
fullResThumbnailUrlstring | null- Full-resolution version of thumbnailUrl (~1600px), derived by replacing the size suffix (s-l500, s-l140, etc.) with s-l1600. null when thumbnailUrl is null.
epidstring | null- eBay catalog product ID. Stable across sellers for the same variant. null when the listing has no catalog match.
titlestring | null- Listing title.
conditionstring | null- eBay's own localized condition label (e.g. "Pre-Owned", "Gebraucht"), when it resolves to a known value. null when the listing shows no condition, or when the label eBay displayed does not match a known value (rare — the field is dropped rather than surfaced verbatim).
conditionIdnumber | null- eBay numeric condition ID (best-effort lookup from the localized label). Common: 1000 New, 3000 Used, 7000 For parts.
sellerType"private" | "business" | null- EU sites only (ebay.de, .fr, .it, .es). null on all non-EU sites. May also be null on EU sites served via eBay's newer card layout, pending mapping.
buyingFormat"auction" | "buyItNow" | "auctionWithBIN" | null- How the item was listed. "auction" = competitive bidding, "buyItNow" = fixed price (includes Best Offer listings), "auctionWithBIN" = auction that also had a Buy It Now option. null when the listing type could not be determined. Distinct from the buyingFormat query parameter, which filters results by listing format (different enum, different concern).
bidCountnumber | null- Number of bids received. Present for auction listings, null for fixed-price (Buy It Now) listings.
categoryIdstring | null- Deprecated. The categoryId filter of your request, not the category of the item. null when the request has no categoryId.
listingType"sold" | "active"- Whether this is a completed sale ("sold", the default) or a currently-listed item ("active", returned when sold=false).
shippingPricestring | null- Shipping cost as a decimal string. null when shipping is free, pickup or not known — read shippingType to tell which.
shippingType"free" | "paid" | "pickup" | "unknown" | null- Shipping category.
totalPricestring | null- Listing price (soldPrice or currentPrice) plus shippingPrice. Equal to the listing price when shipping is free or not known. null when there is no price or when the two currencies differ.
sellerUsernamestring | null- eBay seller username.
sellerPositivePercentnumber | null- Seller positive feedback percentage.
sellerFeedbackScorenumber | null- Seller total feedback count.
itemLocationstring | null- Seller's location as shown on the eBay search results card. null when the card shows no location, so null does not prove that a listing is domestic. Localized per site language (e.g., "United States" on ebay.com, "Großbritannien" on ebay.de).
scrapedAtstring- ISO 8601 timestamp of when SoldComps fetched the listing.
Sold-listing fields (sold=true)
endedAtstring | null- Date the sale completed, as YYYY-MM-DD (date only — eBay never exposes a time of day). For active listings use timeLeft instead.
soldPricestring | null- The listing price at time of sale, as a decimal string. On Best Offer sales (bestOfferAccepted=true), this is normally the asking price (an upper bound), not the realized price — unless hydrateBoa=true, in which case soldPrice is updated to the actual accepted offer amount when a match is found and its currency matches soldCurrency. For active listings the asking price is in currentPrice.
soldCurrencystring | null- ISO 4217 currency of soldPrice. Active listings use currentCurrency.
bestOfferAcceptedboolean- true when the seller accepted a best offer rather than the listing selling at the listed price. With hydrateBoa=true, the accepted amount is returned in boaAcceptedPrice, and soldPrice is updated to it when the currencies match. Requires includeCompleteListing=true (the default). For active listings, whether the listing accepts offers is in acceptsOffers.
boaHydratedbooleanoptional- Only present with hydrateBoa=true, on items where bestOfferAccepted is true (omitted on all other items). true when the accepted offer was found in eBay's Price Guide; false when the lookup found no match — soldPrice then still holds the listing price.
boaAcceptedPricestring | nulloptional- The actual accepted Best Offer amount from eBay's Price Guide. Set whenever boaHydrated is true; null when boaHydrated is false. When boaAcceptedCurrency matches soldCurrency, soldPrice (and totalPrice) are also replaced with this amount; when the currencies differ, soldPrice keeps the listing price in the site currency.
boaAcceptedCurrencystring | nulloptional- ISO 4217 currency of boaAcceptedPrice. Set whenever boaHydrated is true; null when boaHydrated is false.
boaOriginalPricestring | nulloptional- The listing (asking) price before hydration — useful for computing the Best Offer discount. Set whenever boaHydrated is true; null when boaHydrated is false.
Active-listing fields (sold=false)
currentPricestring | null- Current asking price — the from/low bound of a multi-variant range. The active-mode counterpart to soldPrice.
currentPriceMaxstring | null- The to/high bound when a listing spans a price range (e.g. "$899.99 to $1099.99"). null for single-price listings; currentPrice is always the low bound.
currentCurrencystring | null- ISO 4217 currency code for currentPrice/currentPriceMax (e.g. "USD", "GBP"). The active-mode counterpart to soldCurrency.
watcherCountnumber | null- Number of eBay users watching this listing — a live demand signal. When eBay shows an approximate count ("N+"), this is N as a floor (at least N). null when none shown.
unitsSoldnumber | null- Units already sold on this currently-listed multi-quantity listing — a live sales-velocity signal. When eBay shows an approximate count ("N+" / "Más de N"), this is N as a floor. null when none shown.
acceptsOffersboolean- true when the listing accepts Best Offers ("or Best Offer"). The active-mode analogue of bestOfferAccepted.
timeLeftstring | null- Auction time remaining as a raw, localized, relative string exactly as eBay renders it, including the locale suffix ("6d 4h left", "Noch 5 Std 47 Min", "1g 6h rimasti"). A snapshot at scrape time — not an absolute end timestamp. null for fixed-price / Buy It Now listings.
Example active response (sold=false)
With sold=false, items drop the sold-only fields and return the asking price plus live signals instead.
The default (sold) response is shown at the top of this endpoint.
{
"keyword": "iphone 15 pro",
"page": 1,
"totalItems": 60,
"totalResults": "14,000+",
"hasNextPage": true,
"autoSelectedCategory": { "id": "9355", "name": "Cell Phones & Smartphones" },
"items": [
{
"itemId": "256987654321",
"url": "https://www.ebay.com/itm/256987654321?nordt=true",
"thumbnailUrl": "https://i.ebayimg.com/images/g/9QwAAeSwABCqGLiR/s-l500.webp",
"fullResThumbnailUrl": "https://i.ebayimg.com/images/g/9QwAAeSwABCqGLiR/s-l1600.webp",
"epid": "20049285656",
"title": "Apple iPhone 15 Pro 256GB Natural Titanium - Unlocked",
"condition": "Pre-Owned",
"conditionId": 3000,
"sellerType": null,
"buyingFormat": "buyItNow",
"bidCount": null,
"categoryId": null,
"listingType": "active",
"shippingPrice": null,
"shippingCurrency": null,
"shippingType": "free",
"totalPrice": "849.99",
"sellerUsername": "top-deals-store",
"sellerPositivePercent": 99.8,
"sellerFeedbackScore": 14200,
"itemLocation": "United States",
"scrapedAt": "2026-03-14T21:00:00.000Z",
"currentPrice": "849.99",
"currentPriceMax": null,
"currentCurrency": "USD",
"watcherCount": 31,
"unitsSold": 12,
"acceptsOffers": true,
"timeLeft": null
}
]
}Request
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
"https://api.sold-comps.com/v1/scrape\
?keyword=iphone+15+pro\
&ebaySite=ebay.com\
&page=1\
&count=60\
&sortOrder=endedRecently"Response
{
"keyword": "iphone 15 pro",
"page": 1,
"totalItems": 60,
"totalResults": "14,000+",
"hasNextPage": true,
"autoSelectedCategory": { "id": "9355", "name": "Cell Phones & Smartphones" },
"items": [
{
"itemId": "256123456789",
"url": "https://www.ebay.com/itm/256123456789?nordt=true",
"thumbnailUrl": "https://i.ebayimg.com/images/g/3nkAAeSwCitqGLiR/s-l500.webp",
"fullResThumbnailUrl": "https://i.ebayimg.com/images/g/3nkAAeSwCitqGLiR/s-l1600.webp",
"epid": "20049285656",
"title": "Apple iPhone 15 Pro 256GB Natural Titanium - Unlocked",
"condition": "Pre-Owned",
"conditionId": 3000,
"sellerType": null,
"buyingFormat": "buyItNow",
"bestOfferAccepted": false,
"bidCount": null,
"categoryId": null,
"listingType": "sold",
"endedAt": "2026-03-10",
"soldPrice": "899.99",
"soldCurrency": "USD",
"shippingPrice": null,
"shippingCurrency": null,
"shippingType": "free",
"totalPrice": "899.99",
"sellerUsername": "top-deals-store",
"sellerPositivePercent": 99.8,
"sellerFeedbackScore": 14200,
"itemLocation": "United States",
"scrapedAt": "2026-03-14T21:00:00.000Z"
}
]
}/v1/scrape/categoryBrowse category sold listings
categoryId (eBay _sacat) and optionally filter by price, condition, or seller type.
Same filters and response shape as /v1/scrape.
Useful for catalogue-based sellers who want every recent sale in a category without specifying a search term.
Browse all 17,000+ category IDs at /ebay-categories.
EU sites (ebay.de, .fr, .it, .es) include sellerType on each item and support the sellerType filter.
eBay does not return results past page 100 on ebay.com, ebay.co.uk, ebay.de, ebay.fr, ebay.it and ebay.es: on these sites page 100 has hasNextPage: false, and a higher page returns 400 with code: "page_limit" and is not counted.
Use count=240 to reach up to 24,000 items in 100 pages.Query parameters
categoryIdstringrequired- eBay category ID (_sacat). Must not be "0". Browse all 17,000+ IDs at sold-comps.com/ebay-categories.
pageintegeroptionaldefault:1- Page number of eBay results to fetch. Increment until hasNextPage is false.
countintegeroptionaldefault:240- Items per page: 60, 120 or 240. Other values are rounded up to the next size, so a request can return more items than count. The last page may contain fewer items.
ebaySiteenumoptionaldefault:ebay.com- eBay domain to scrape.
ebay.comebay.co.ukebay.deebay.frebay.itebay.esebay.caebay.com.au sortOrderenumoptionaldefault:endedRecently- Sort order for results.
endedRecentlytimeNewlyListedpricePlusPostageLowestpricePlusPostageHighestdistanceNearest minPricenumberoptional- Minimum price filter, in listing currency.
maxPricenumberoptional- Maximum price filter, in listing currency.
itemLocationenumoptionaldefault:default- Item location filter.
defaultdomesticworldwide itemConditionenumoptionaldefault:any- Item condition filter.
anynewused conditionIdnumberoptional- eBay numeric condition ID filter. Common IDs: 3 (New), 4 (Used), 1000 (Brand New), 1500 (Open box), 2750 (Like New), 3000 (Used), 7000 (For parts). Valid IDs vary by eBay category. When set, overrides itemCondition.
buyingFormatenumoptionaldefault:all- Filter by listing format (request filter — distinct from the per-item buyingFormat response field, which classifies how a listing was actually listed and uses a different enum). "auction" = auction-only, "buyItNow" = fixed-price / Buy It Now, "acceptsOffers" = listings with Best Offer enabled. Default "all" (no format filter).
allauctionbuyItNowacceptsOffers sellerTypeenumoptional- Filter results by seller type. Only effective on EU sites (ebay.de, .fr, .it, .es). On non-EU sites the filter is silently ignored.
privatebusiness includeCompleteListingbooleanoptionaldefault:true- Include eBay completed-listing metadata (LH_Complete=1) so bestOfferAccepted is detected accurately. Does not change which listings are returned (results stay sold-only). Set to false only to match pre-July-2026 behavior.
soldAfterstring (YYYY-MM-DD)optional- Inclusive lower bound on endedAt. Applied after the page is scraped. Category scrape is always sold, so this always applies when set.
soldBeforestring (YYYY-MM-DD)optional- Inclusive upper bound on endedAt. Applied after the page is scraped.
aspectFilterstring (JSON)optional- JSON object of eBay item-aspect facet filters. Keys and values are the human-readable facet names exactly as shown in eBay's sidebar refinements. Multi-select values use pipe as separator: {"Network":"Unlocked|AT&T"}. Invalid or unrecognized facets are silently ignored by eBay.
exactMatchbooleanoptionaldefault:true- When true (default), strips eBay's loosened-match results ("Results matching fewer words") so only items closely matching your keyword are returned. Set to false to include all results eBay returns.
hydrateBoabooleanoptionaldefault:false- Same as hydrateBoa on /v1/scrape: Best Offer sales get the accepted offer amount from eBay's Price Guide. Costs 1 extra request, only when at least one item is matched.
Response fields (each item)
itemIdstring- eBay listing item ID.
urlstring- Canonical listing URL with ?nordt=true to bypass eBay's catalog redirect.
thumbnailUrlstring | null- Listing thumbnail (500px) from i.ebayimg.com. null when the listing has no product image.
fullResThumbnailUrlstring | null- Full-resolution version of thumbnailUrl (~1600px), derived by replacing the size suffix (s-l500, s-l140, etc.) with s-l1600. null when thumbnailUrl is null.
epidstring | null- eBay catalog product ID. Stable across sellers for the same variant. null when the listing has no catalog match.
titlestring | null- Listing title.
conditionstring | null- eBay's own localized condition label (e.g. "Pre-Owned", "Gebraucht"), when it resolves to a known value. null when the listing shows no condition, or when the label eBay displayed does not match a known value (rare — the field is dropped rather than surfaced verbatim).
conditionIdnumber | null- eBay numeric condition ID (best-effort lookup from the localized label). Common: 1000 New, 3000 Used, 7000 For parts.
sellerType"private" | "business" | null- EU sites only (ebay.de, .fr, .it, .es). null on all non-EU sites. May also be null on EU sites served via eBay's newer card layout, pending mapping.
buyingFormat"auction" | "buyItNow" | "auctionWithBIN" | null- How the item was listed. "auction" = competitive bidding, "buyItNow" = fixed price (includes Best Offer listings), "auctionWithBIN" = auction that also had a Buy It Now option. null when the listing type could not be determined. Distinct from the buyingFormat query parameter, which filters results by listing format (different enum, different concern).
bidCountnumber | null- Number of bids received. Present for auction listings, null for fixed-price (Buy It Now) listings.
categoryIdstring | null- Deprecated. The categoryId filter of your request, not the category of the item. null when the request has no categoryId.
listingType"sold" | "active"- Whether this is a completed sale ("sold", the default) or a currently-listed item ("active", returned when sold=false).
shippingPricestring | null- Shipping cost as a decimal string. null when shipping is free, pickup or not known — read shippingType to tell which.
shippingType"free" | "paid" | "pickup" | "unknown" | null- Shipping category.
totalPricestring | null- Listing price (soldPrice or currentPrice) plus shippingPrice. Equal to the listing price when shipping is free or not known. null when there is no price or when the two currencies differ.
sellerUsernamestring | null- eBay seller username.
sellerPositivePercentnumber | null- Seller positive feedback percentage.
sellerFeedbackScorenumber | null- Seller total feedback count.
itemLocationstring | null- Seller's location as shown on the eBay search results card. null when the card shows no location, so null does not prove that a listing is domestic. Localized per site language (e.g., "United States" on ebay.com, "Großbritannien" on ebay.de).
scrapedAtstring- ISO 8601 timestamp of when SoldComps fetched the listing.
Sold-listing fields (sold=true)
endedAtstring | null- Date the sale completed, as YYYY-MM-DD (date only — eBay never exposes a time of day). For active listings use timeLeft instead.
soldPricestring | null- The listing price at time of sale, as a decimal string. On Best Offer sales (bestOfferAccepted=true), this is normally the asking price (an upper bound), not the realized price — unless hydrateBoa=true, in which case soldPrice is updated to the actual accepted offer amount when a match is found and its currency matches soldCurrency. For active listings the asking price is in currentPrice.
soldCurrencystring | null- ISO 4217 currency of soldPrice. Active listings use currentCurrency.
bestOfferAcceptedboolean- true when the seller accepted a best offer rather than the listing selling at the listed price. With hydrateBoa=true, the accepted amount is returned in boaAcceptedPrice, and soldPrice is updated to it when the currencies match. Requires includeCompleteListing=true (the default). For active listings, whether the listing accepts offers is in acceptsOffers.
boaHydratedbooleanoptional- Only present with hydrateBoa=true, on items where bestOfferAccepted is true (omitted on all other items). true when the accepted offer was found in eBay's Price Guide; false when the lookup found no match — soldPrice then still holds the listing price.
boaAcceptedPricestring | nulloptional- The actual accepted Best Offer amount from eBay's Price Guide. Set whenever boaHydrated is true; null when boaHydrated is false. When boaAcceptedCurrency matches soldCurrency, soldPrice (and totalPrice) are also replaced with this amount; when the currencies differ, soldPrice keeps the listing price in the site currency.
boaAcceptedCurrencystring | nulloptional- ISO 4217 currency of boaAcceptedPrice. Set whenever boaHydrated is true; null when boaHydrated is false.
boaOriginalPricestring | nulloptional- The listing (asking) price before hydration — useful for computing the Best Offer discount. Set whenever boaHydrated is true; null when boaHydrated is false.
Request
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
"https://api.sold-comps.com/v1/scrape/category\
?categoryId=27386\
&ebaySite=ebay.de\
&page=1\
&count=60\
&sortOrder=endedRecently"Response
{
"categoryId": "27386",
"page": 1,
"totalItems": 60,
"totalResults": "89",
"hasNextPage": true,
"autoSelectedCategory": null,
"items": [
{
"itemId": "334987654321",
"url": "https://www.ebay.de/itm/334987654321?nordt=true",
"thumbnailUrl": "https://i.ebayimg.com/images/g/xyzAAeSwCitqGLiR/s-l500.webp",
"fullResThumbnailUrl": "https://i.ebayimg.com/images/g/xyzAAeSwCitqGLiR/s-l1600.webp",
"epid": null,
"title": "Bosch PSB 18 LI-2 Ergonomic Akkuschrauber",
"condition": "Gebraucht",
"conditionId": 3000,
"sellerType": "private",
"buyingFormat": "auction",
"bestOfferAccepted": false,
"bidCount": 7,
"categoryId": "27386",
"listingType": "sold",
"endedAt": "2026-06-14",
"soldPrice": "45.00",
"soldCurrency": "EUR",
"shippingPrice": "5.90",
"shippingCurrency": "EUR",
"shippingType": "paid",
"totalPrice": "50.90",
"sellerUsername": "werkzeug_verkauf",
"sellerPositivePercent": 98.7,
"sellerFeedbackScore": 312,
"itemLocation": "Deutschland",
"scrapedAt": "2026-06-15T08:00:00.000Z"
}
]
}/api/bulk-searchBulk keyword search (SSE)
error events with code quota_exceeded.
If no keyword fits, the response is a 429 JSON body, not a stream.
This endpoint always searches sold listings and returns page 1 of each keyword — there is no sold or page parameter.Request body (JSON)
keywordsstring[]required- Array of 1–20 search keywords. Each keyword runs as a separate eBay search and consumes 1 quota request on success. Duplicates are removed, preserving order.
countintegeroptionaldefault:240- Items per keyword: 60, 120 or 240 (other values round up). Same as the count param on /v1/scrape.
ebaySitestringoptionaldefault:ebay.com- eBay regional site. Applied to every keyword.
ebay.comebay.co.ukebay.deebay.frebay.itebay.esebay.caebay.com.au sortOrderstringoptionaldefault:endedRecently- Sort order. Applied to every keyword.
endedRecentlytimeNewlyListedpricePlusPostageLowestpricePlusPostageHighestdistanceNearest itemConditionstringoptionaldefault:any- Condition filter. Applied to every keyword.
anynewused conditionIdintegeroptional- Numeric eBay condition ID (e.g. 1000 = New, 3000 = Used). Overrides itemCondition when both set. Applied to every keyword.
buyingFormatstringoptionaldefault:all- Buying format filter. Applied to every keyword.
allauctionbuyItNowacceptsOffers minPricenumberoptional- Minimum price filter. Applied to every keyword.
maxPricenumberoptional- Maximum price filter. Applied to every keyword.
soldAfterstringoptional- Inclusive lower bound on endedAt (YYYY-MM-DD). Post-parse filter, applied to every keyword.
soldBeforestringoptional- Inclusive upper bound on endedAt (YYYY-MM-DD). Post-parse filter, applied to every keyword.
aspectFilterobjectoptional- eBay item-aspect facet filters as a JSON object. Same format as /v1/scrape. Applied to every keyword.
includeCompleteListingbooleanoptionaldefault:true- Include eBay completed-listing metadata (LH_Complete=1) for accurate bestOfferAccepted detection. Applied to every keyword.
exactMatchbooleanoptionaldefault:true- When true, only exact-match items are returned — eBay's loosened-match results are stripped. Applied to every keyword.
hydrateBoabooleanoptionaldefault:false- Same as hydrateBoa on /v1/scrape: Best Offer sales get the accepted offer amount from eBay's Price Guide. Costs 1 extra request for each keyword where at least one item is matched.
SSE event types:
progress— keyword started scrapingresult— keyword completed withtotalItems,totalResults,hasNextPage,autoSelectedCategory, optionalscrapedCount, anditemsarray (same item shape as/v1/scrape)error— keyword failed (quota not charged). Status is"failed"complete— all keywords done, includestotal,succeeded, andfailedcounts. Stream closes
Response fields (each item)
itemIdstring- eBay listing item ID.
urlstring- Canonical listing URL with ?nordt=true to bypass eBay's catalog redirect.
thumbnailUrlstring | null- Listing thumbnail (500px) from i.ebayimg.com. null when the listing has no product image.
fullResThumbnailUrlstring | null- Full-resolution version of thumbnailUrl (~1600px), derived by replacing the size suffix (s-l500, s-l140, etc.) with s-l1600. null when thumbnailUrl is null.
epidstring | null- eBay catalog product ID. Stable across sellers for the same variant. null when the listing has no catalog match.
titlestring | null- Listing title.
conditionstring | null- eBay's own localized condition label (e.g. "Pre-Owned", "Gebraucht"), when it resolves to a known value. null when the listing shows no condition, or when the label eBay displayed does not match a known value (rare — the field is dropped rather than surfaced verbatim).
conditionIdnumber | null- eBay numeric condition ID (best-effort lookup from the localized label). Common: 1000 New, 3000 Used, 7000 For parts.
sellerType"private" | "business" | null- EU sites only (ebay.de, .fr, .it, .es). null on all non-EU sites. May also be null on EU sites served via eBay's newer card layout, pending mapping.
buyingFormat"auction" | "buyItNow" | "auctionWithBIN" | null- How the item was listed. "auction" = competitive bidding, "buyItNow" = fixed price (includes Best Offer listings), "auctionWithBIN" = auction that also had a Buy It Now option. null when the listing type could not be determined. Distinct from the buyingFormat query parameter, which filters results by listing format (different enum, different concern).
bidCountnumber | null- Number of bids received. Present for auction listings, null for fixed-price (Buy It Now) listings.
categoryIdstring | null- Deprecated. The categoryId filter of your request, not the category of the item. null when the request has no categoryId.
listingType"sold" | "active"- Whether this is a completed sale ("sold", the default) or a currently-listed item ("active", returned when sold=false).
shippingPricestring | null- Shipping cost as a decimal string. null when shipping is free, pickup or not known — read shippingType to tell which.
shippingType"free" | "paid" | "pickup" | "unknown" | null- Shipping category.
totalPricestring | null- Listing price (soldPrice or currentPrice) plus shippingPrice. Equal to the listing price when shipping is free or not known. null when there is no price or when the two currencies differ.
sellerUsernamestring | null- eBay seller username.
sellerPositivePercentnumber | null- Seller positive feedback percentage.
sellerFeedbackScorenumber | null- Seller total feedback count.
itemLocationstring | null- Seller's location as shown on the eBay search results card. null when the card shows no location, so null does not prove that a listing is domestic. Localized per site language (e.g., "United States" on ebay.com, "Großbritannien" on ebay.de).
scrapedAtstring- ISO 8601 timestamp of when SoldComps fetched the listing.
Sold-listing fields (sold=true)
endedAtstring | null- Date the sale completed, as YYYY-MM-DD (date only — eBay never exposes a time of day). For active listings use timeLeft instead.
soldPricestring | null- The listing price at time of sale, as a decimal string. On Best Offer sales (bestOfferAccepted=true), this is normally the asking price (an upper bound), not the realized price — unless hydrateBoa=true, in which case soldPrice is updated to the actual accepted offer amount when a match is found and its currency matches soldCurrency. For active listings the asking price is in currentPrice.
soldCurrencystring | null- ISO 4217 currency of soldPrice. Active listings use currentCurrency.
bestOfferAcceptedboolean- true when the seller accepted a best offer rather than the listing selling at the listed price. With hydrateBoa=true, the accepted amount is returned in boaAcceptedPrice, and soldPrice is updated to it when the currencies match. Requires includeCompleteListing=true (the default). For active listings, whether the listing accepts offers is in acceptsOffers.
boaHydratedbooleanoptional- Only present with hydrateBoa=true, on items where bestOfferAccepted is true (omitted on all other items). true when the accepted offer was found in eBay's Price Guide; false when the lookup found no match — soldPrice then still holds the listing price.
boaAcceptedPricestring | nulloptional- The actual accepted Best Offer amount from eBay's Price Guide. Set whenever boaHydrated is true; null when boaHydrated is false. When boaAcceptedCurrency matches soldCurrency, soldPrice (and totalPrice) are also replaced with this amount; when the currencies differ, soldPrice keeps the listing price in the site currency.
boaAcceptedCurrencystring | nulloptional- ISO 4217 currency of boaAcceptedPrice. Set whenever boaHydrated is true; null when boaHydrated is false.
boaOriginalPricestring | nulloptional- The listing (asking) price before hydration — useful for computing the Best Offer discount. Set whenever boaHydrated is true; null when boaHydrated is false.
Request
curl -X POST "https://api.sold-comps.com/api/bulk-search" \
-H "Authorization: Bearer sc_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{"keywords":["iphone 15 pro","macbook air m2","airpods pro"]}'Response
event: progress
data: {"keyword":"iphone 15 pro","status":"processing"}
event: progress
data: {"keyword":"macbook air m2","status":"processing"}
event: progress
data: {"keyword":"airpods pro","status":"processing"}
event: result
data: {"keyword":"iphone 15 pro","status":"completed","totalItems":142,"totalResults":"14,000+","hasNextPage":true,"autoSelectedCategory":null,"items":[{"itemId":"123456789","title":"Apple iPhone 15 Pro 256GB","soldPrice":"899.99","soldCurrency":"USD","condition":"Pre-Owned","endedAt":"2026-08-15"}]}
event: result
data: {"keyword":"macbook air m2","status":"completed","totalItems":98,"totalResults":"5,200+","hasNextPage":true,"autoSelectedCategory":null,"items":[...]}
event: result
data: {"keyword":"airpods pro","status":"completed","totalItems":120,"totalResults":"9,800+","hasNextPage":true,"autoSelectedCategory":null,"items":[...]}
event: complete
data: {"total":3,"succeeded":3,"failed":0}Async sweeps
Max Mode
Max Mode auto-paginates server-side.
Submit once, then poll for progress, get the result by email, or stream a signed CSV.
Unlike /v1/scrape, a Max Mode submission is not 1 request — each successfully scraped page debits 1 request from your monthly quota (or from your purchased credits).
A 50-page sweep can cost up to 50 requests, or up to 100 with hydrateBoa=true (1 extra for each page where a Best Offer price is found).
Failed pages don't debit.
maxPages caps blast radius (max 100).
Max Mode searches sold listings only, at 240 items per page.
sold, count, page, soldAfter and soldBefore in the body are ignored, with no error.
Submit, poll and cancel calls count against the same per-minute limit as your search requests.
One job per user can be active at a time.
A second submit while one is running returns 409 with the existing jobId.
/v1/scrape/maxSubmit
jobId you can poll, cancel, or wait for the worker to deliver via email / signed download URL.
Pass Idempotency-Key to dedupe re-submits over a 24h window.Request body
keywordstringrequired- eBay search term.
maxPagesinteger (1–100)optionaldefault:50- Upper bound on how many pages the worker will fetch. Each successful page debits 1 request (2 when hydrateBoa finds a match on that page).
resultTypeenumoptionaldefault:inline- How to deliver the result: inline (poll the results endpoint), email (CSV attached or signed link), download (signed CSV stream URL).
inlineemaildownload emailTostringoptional- Recipient address when resultType=email. Falls back to the account email on file.
daysToScrapeinteger (1–365)optionaldefault:90- History window in days. Currently has no effect on the scrape — the value is accepted and stored with the job, but is not yet applied to the fetch.
ebaySiteenumoptionaldefault:ebay.com- eBay domain to scrape.
ebay.comebay.co.ukebay.deebay.frebay.itebay.esebay.caebay.com.au categoryIdstringoptionaldefault:0- eBay category ID (_sacat).
sortOrderenumoptionaldefault:endedRecently- Sort order.
endedRecentlytimeNewlyListedpricePlusPostageLowestpricePlusPostageHighestdistanceNearest minPricenumberoptional- Minimum price filter.
maxPricenumberoptional- Maximum price filter.
itemLocationenumoptionaldefault:default- Item location filter.
defaultdomesticworldwide itemConditionenumoptionaldefault:any- Item condition filter.
anynewused conditionIdnumberoptional- eBay numeric condition ID filter. Common IDs: 3 (New), 4 (Used), 1000 (Brand New), 1500 (Open box), 2750 (Like New), 3000 (Used), 7000 (For parts). Valid IDs vary by eBay category. When set, overrides itemCondition.
buyingFormatenumoptionaldefault:all- Filter by listing format (request filter — distinct from the per-item buyingFormat response field, which classifies how a listing was actually listed and uses a different enum). "auction" = auction-only, "buyItNow" = fixed-price / Buy It Now, "acceptsOffers" = listings with Best Offer enabled. Default "all" (no format filter).
allauctionbuyItNowacceptsOffers sellerTypeenumoptional- EU sites only.
privatebusiness includeCompleteListingbooleanoptionaldefault:true- Include eBay completed-listing metadata (LH_Complete=1) so bestOfferAccepted is detected accurately. Does not change which listings are returned. Set to false only to match pre-July-2026 behavior.
aspectFilterobjectoptional- eBay item-aspect facet filters. Keys and values are the human-readable facet names exactly as shown in eBay's sidebar refinements. Multi-select values use pipe as separator: {"Network":"Unlocked|AT&T"}. Invalid or unrecognized facets are silently ignored by eBay.
exactMatchbooleanoptionaldefault:true- When true (default), strips eBay's loosened-match results ("Results matching fewer words") so only items closely matching your keyword are returned. Set to false to include all results eBay returns.
hydrateBoabooleanoptionaldefault:false- Same as hydrateBoa on /v1/scrape: Best Offer sales get the accepted offer amount from eBay's Price Guide. Costs 1 extra request for each page where at least one item is matched, so a 50-page job can cost up to 100 requests.
Request
curl -X POST https://api.sold-comps.com/v1/scrape/max \
-H "Authorization: Bearer sc_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: rtx-4090-march-sweep" \
-d '{
"keyword": "rtx 4090",
"maxPages": 50,
"resultType": "email",
"emailTo": "[email protected]",
"ebaySite": "ebay.com",
"daysToScrape": 90
}'Response
{
"jobId": "8c2f1a3e-3b54-4f6b-9c2a-1d6e2b9a0d31",
"status": "queued",
"resultsUrl": "/v1/scrape/max/results/8c2f1a3e-3b54-4f6b-9c2a-1d6e2b9a0d31",
"estimatedSeconds": 150
}/v1/scrape/max/results/:jobIdPoll
410 Gone, and then 404 once the daily cleanup has deleted the job.Terminal statuses: done, failed, cancelled, quota_exhausted, upstream_unhealthy.
terminationReason: natural_end (no more pages), maxPages_reached, quota_exhausted, upstream_unhealthy (5 consecutive page failures), cancelled, or terminal_error (page 1 failed).
Running response
{
"jobId": "8c2f1a3e-3b54-4f6b-9c2a-1d6e2b9a0d31",
"status": "running",
"keyword": "rtx 4090",
"ebaySite": "ebay.com",
"createdAt": "2026-06-13T20:01:14.000Z",
"startedAt": "2026-06-13T20:01:14.000Z",
"progress": {
"currentPage": 13,
"pagesAttempted": 12,
"pagesSucceeded": 12,
"pagesFailed": 0,
"failedPages": [],
"itemsCollected": 2880,
"consecutiveFailures": 0
}
}Request
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
https://api.sold-comps.com/v1/scrape/max/results/8c2f1a3e-3b54-4f6b-9c2a-1d6e2b9a0d31Response
{
"jobId": "8c2f1a3e-3b54-4f6b-9c2a-1d6e2b9a0d31",
"status": "done",
"keyword": "rtx 4090",
"ebaySite": "ebay.com",
"autoSelectedCategory": null,
"createdAt": "2026-06-13T20:01:13.000Z",
"startedAt": "2026-06-13T20:01:14.000Z",
"completedAt": "2026-06-13T20:04:09.000Z",
"expiresAt": "2026-07-13T20:04:09.000Z",
"summary": {
"pagesAttempted": 42,
"pagesSucceeded": 42,
"pagesFailed": 0,
"failedPages": [],
"totalItems": 9870,
"partial": false,
"terminationReason": "natural_end"
},
"error": null,
"delivery": {
"method": "email",
"status": "delivered",
"lastError": null
}
}/v1/scrape/max/:jobIdCancel
409.
Pages already scraped are not refunded.Returns 200 with status: "cancelled" at once.
The job itself stays running until the worker reaches its next page check, and a new submit returns 409 until then.
A cancelled job keeps the pages it collected: inline jobs return them as items, download jobs get a downloadUrl, and email jobs are emailed the partial CSV.
Request
curl -X DELETE \
-H "Authorization: Bearer sc_YOUR_KEY_HERE" \
https://api.sold-comps.com/v1/scrape/max/8c2f1a3e-3b54-4f6b-9c2a-1d6e2b9a0d31/v1/scrape/max/:jobId/download.csvDownload CSV
?token= query parameter, not a Bearer header — the URL is safe to share in email.
A token is valid for 24 hours.
Each poll of a download job returns a new link, until the job expires at 30 days.The download URL is returned at the top level of the poll response as downloadUrl (when resultType=download) or attached directly to completion emails.
Its value is a path (/v1/scrape/max/...): put https://api.sold-comps.com in front of it.
Do not append your API key — the signed token is the auth.
One row per listing, with these columns: item_id, page_no, keyword, ebay_site, title, condition, condition_id, seller_type, sold_price, sold_currency, shipping_price, shipping_currency, total_price, seller_username, ended_at, url, thumbnail_url, epid.
The CSV does not have every field of the per-item response: for the others (for example buyingFormat, bidCount, shippingType, itemLocation and the boa* fields) use resultType=inline.
Request
# downloadUrl is at the top level of the poll response when
# resultType=download. It is a path: put the API host in front of it.
# The token is in the URL — do NOT add a Bearer header.
curl -o results.csv \
"https://api.sold-comps.com/v1/scrape/max/8c2f1a3e.../download.csv?token=eyJhb..."/rapidapi/scrape-ebayRapidAPI - Scrape eBay
/v1/scrape, but callable only through the SoldComps RapidAPI listing.
Auth is via RapidAPI's marketplace headers — X-RapidAPI-Key + X-RapidAPI-Host — not Bearer tokens.
Quotas and billing run through your RapidAPI subscription.
hydrateBoa=true has no extra charge on this channel.Query parameters
keywordstringrequired- Passed directly to eBay's search bar. Supports eBay's minus-sign syntax to exclude terms — e.g. "iphone 15 pro -case -screen -lot" drops listings containing case, screen, or lot from results.
pageintegeroptionaldefault:1- Page number of eBay results to fetch. Increment until hasNextPage is false.
countinteger (60, 120, 240)optionaldefault:240- Items per page: 60, 120 or 240, for sold and active listings (sold=false). Other values are rounded up to the next size, so a request can return more items than count. Each page is one full eBay results page — the last page may contain fewer items.
ebaySiteenumoptionaldefault:ebay.com- eBay domain to scrape.
ebay.comebay.co.ukebay.deebay.frebay.itebay.esebay.caebay.com.au categoryIdstringoptionaldefault:0- eBay category ID (_sacat). Browse all 17,000+ IDs at sold-comps.com/ebay-categories. Use "0" for all categories.
sortOrderenumoptionaldefault:endedRecently- Sort order for results.
endedRecentlytimeNewlyListedpricePlusPostageLowestpricePlusPostageHighestdistanceNearest minPricenumberoptional- Minimum price filter, in listing currency.
maxPricenumberoptional- Maximum price filter, in listing currency.
itemLocationenumoptionaldefault:default- Item location filter.
defaultdomesticworldwide itemConditionenumoptionaldefault:any- Item condition filter applied as a request filter on eBay.
anynewused conditionIdnumberoptional- eBay numeric condition ID filter. Common IDs: 3 (New), 4 (Used), 1000 (Brand New), 1500 (Open box), 2750 (Like New), 3000 (Used), 7000 (For parts). Valid IDs vary by eBay category. When set, overrides itemCondition. When omitted, itemCondition applies (its default, any, is no condition filter).
buyingFormatenumoptionaldefault:all- Filter by listing format (request filter — distinct from the per-item buyingFormat response field, which classifies how a listing was actually listed and uses a different enum). "auction" = auction-only, "buyItNow" = fixed-price / Buy It Now, "acceptsOffers" = listings with Best Offer enabled. Default "all" (no format filter).
allauctionbuyItNowacceptsOffers sellerTypeenumoptional- Filter results by seller type. Only effective on EU sites (ebay.de, .fr, .it, .es). On non-EU sites the filter is silently ignored.
privatebusiness includeCompleteListingbooleanoptionaldefault:true- Include eBay completed-listing metadata (LH_Complete=1). This is what enables accurate bestOfferAccepted detection — without it, eBay does not render the "Best offer accepted" signal and bestOfferAccepted is false for nearly all items. Does not change which listings are returned: results stay sold-only (LH_Sold=1 takes precedence). Set to false only to match pre-July-2026 behavior.
soldbooleanoptionaldefault:true- When true (default), returns completed/sold listings. When false, returns ACTIVE (currently-listed) results instead. Active responses swap the sold-only fields (soldPrice, soldCurrency, endedAt, bestOfferAccepted) for active-only ones: listingType="active", the asking price in currentPrice/currentPriceMax/currentCurrency, plus watcherCount, unitsSold, acceptsOffers, and timeLeft.
soldAfterstring (YYYY-MM-DD)optional- Inclusive lower bound on endedAt. Applied after the page is scraped — sold-only, silently ignored when sold=false. See scrapedCount in the response for how to tell whether more pages will help.
soldBeforestring (YYYY-MM-DD)optional- Inclusive upper bound on endedAt. Applied after the page is scraped — sold-only, silently ignored when sold=false.
aspectFilterstring (JSON)optional- JSON object of eBay item-aspect facet filters — your HTTP client handles URL encoding automatically. Keys and values are the human-readable facet names exactly as shown in eBay's sidebar refinements (e.g. {"Brand":"Apple","Storage Capacity":"256 GB"}). Multi-select values use pipe as separator: {"Network":"Unlocked|AT&T"}. Facet names are dynamic per eBay category and vary by site language. Unrecognized facets are silently ignored by eBay. A value that is not a JSON object is ignored: the search runs with no aspect filter and no error is returned.
exactMatchbooleanoptionaldefault:true- When true (default), strips eBay's loosened-match results ("Results matching fewer words") so only items closely matching your keyword are returned. Set to false to include all results eBay returns — useful when you want maximum volume over keyword precision.
hydrateBoabooleanoptionaldefault:false- When true, items sold via Best Offer have their soldPrice updated to the actual accepted offer amount using eBay's Price Guide. Primarily useful for trading card categories where Best Offer is common. Each Best Offer item on the page is looked up, which adds response time; an item that is not in the Price Guide is a miss. eBay has Price Guide data only for items listed on ebay.com, ebay.co.uk and ebay.de. On an ebay.co.uk or ebay.de search, items listed on that site get the accepted amount in the listing currency; on every site, items listed on ebay.com get it in USD. When the hydrated price is in a different currency than the listing, boaAcceptedPrice and boaAcceptedCurrency are returned instead of overwriting soldPrice. Sold-only; ignored when sold=false. Costs 1 extra request against your quota, but only when hydration actually finds at least one match — a miss (or a keyword with no Best Offer items) costs nothing extra.
Response fields (each item)
itemIdstring- eBay listing item ID.
urlstring- Canonical listing URL with ?nordt=true to bypass eBay's catalog redirect.
thumbnailUrlstring | null- Listing thumbnail (500px) from i.ebayimg.com. null when the listing has no product image.
fullResThumbnailUrlstring | null- Full-resolution version of thumbnailUrl (~1600px), derived by replacing the size suffix (s-l500, s-l140, etc.) with s-l1600. null when thumbnailUrl is null.
epidstring | null- eBay catalog product ID. Stable across sellers for the same variant. null when the listing has no catalog match.
titlestring | null- Listing title.
conditionstring | null- eBay's own localized condition label (e.g. "Pre-Owned", "Gebraucht"), when it resolves to a known value. null when the listing shows no condition, or when the label eBay displayed does not match a known value (rare — the field is dropped rather than surfaced verbatim).
conditionIdnumber | null- eBay numeric condition ID (best-effort lookup from the localized label). Common: 1000 New, 3000 Used, 7000 For parts.
sellerType"private" | "business" | null- EU sites only (ebay.de, .fr, .it, .es). null on all non-EU sites. May also be null on EU sites served via eBay's newer card layout, pending mapping.
buyingFormat"auction" | "buyItNow" | "auctionWithBIN" | null- How the item was listed. "auction" = competitive bidding, "buyItNow" = fixed price (includes Best Offer listings), "auctionWithBIN" = auction that also had a Buy It Now option. null when the listing type could not be determined. Distinct from the buyingFormat query parameter, which filters results by listing format (different enum, different concern).
bidCountnumber | null- Number of bids received. Present for auction listings, null for fixed-price (Buy It Now) listings.
categoryIdstring | null- Deprecated. The categoryId filter of your request, not the category of the item. null when the request has no categoryId.
listingType"sold" | "active"- Whether this is a completed sale ("sold", the default) or a currently-listed item ("active", returned when sold=false).
shippingPricestring | null- Shipping cost as a decimal string. null when shipping is free, pickup or not known — read shippingType to tell which.
shippingType"free" | "paid" | "pickup" | "unknown" | null- Shipping category.
totalPricestring | null- Listing price (soldPrice or currentPrice) plus shippingPrice. Equal to the listing price when shipping is free or not known. null when there is no price or when the two currencies differ.
sellerUsernamestring | null- eBay seller username.
sellerPositivePercentnumber | null- Seller positive feedback percentage.
sellerFeedbackScorenumber | null- Seller total feedback count.
itemLocationstring | null- Seller's location as shown on the eBay search results card. null when the card shows no location, so null does not prove that a listing is domestic. Localized per site language (e.g., "United States" on ebay.com, "Großbritannien" on ebay.de).
scrapedAtstring- ISO 8601 timestamp of when SoldComps fetched the listing.
Sold-listing fields (sold=true)
endedAtstring | null- Date the sale completed, as YYYY-MM-DD (date only — eBay never exposes a time of day). For active listings use timeLeft instead.
soldPricestring | null- The listing price at time of sale, as a decimal string. On Best Offer sales (bestOfferAccepted=true), this is normally the asking price (an upper bound), not the realized price — unless hydrateBoa=true, in which case soldPrice is updated to the actual accepted offer amount when a match is found and its currency matches soldCurrency. For active listings the asking price is in currentPrice.
soldCurrencystring | null- ISO 4217 currency of soldPrice. Active listings use currentCurrency.
bestOfferAcceptedboolean- true when the seller accepted a best offer rather than the listing selling at the listed price. With hydrateBoa=true, the accepted amount is returned in boaAcceptedPrice, and soldPrice is updated to it when the currencies match. Requires includeCompleteListing=true (the default). For active listings, whether the listing accepts offers is in acceptsOffers.
boaHydratedbooleanoptional- Only present with hydrateBoa=true, on items where bestOfferAccepted is true (omitted on all other items). true when the accepted offer was found in eBay's Price Guide; false when the lookup found no match — soldPrice then still holds the listing price.
boaAcceptedPricestring | nulloptional- The actual accepted Best Offer amount from eBay's Price Guide. Set whenever boaHydrated is true; null when boaHydrated is false. When boaAcceptedCurrency matches soldCurrency, soldPrice (and totalPrice) are also replaced with this amount; when the currencies differ, soldPrice keeps the listing price in the site currency.
boaAcceptedCurrencystring | nulloptional- ISO 4217 currency of boaAcceptedPrice. Set whenever boaHydrated is true; null when boaHydrated is false.
boaOriginalPricestring | nulloptional- The listing (asking) price before hydration — useful for computing the Best Offer discount. Set whenever boaHydrated is true; null when boaHydrated is false.
Active-listing fields (sold=false)
currentPricestring | null- Current asking price — the from/low bound of a multi-variant range. The active-mode counterpart to soldPrice.
currentPriceMaxstring | null- The to/high bound when a listing spans a price range (e.g. "$899.99 to $1099.99"). null for single-price listings; currentPrice is always the low bound.
currentCurrencystring | null- ISO 4217 currency code for currentPrice/currentPriceMax (e.g. "USD", "GBP"). The active-mode counterpart to soldCurrency.
watcherCountnumber | null- Number of eBay users watching this listing — a live demand signal. When eBay shows an approximate count ("N+"), this is N as a floor (at least N). null when none shown.
unitsSoldnumber | null- Units already sold on this currently-listed multi-quantity listing — a live sales-velocity signal. When eBay shows an approximate count ("N+" / "Más de N"), this is N as a floor. null when none shown.
acceptsOffersboolean- true when the listing accepts Best Offers ("or Best Offer"). The active-mode analogue of bestOfferAccepted.
timeLeftstring | null- Auction time remaining as a raw, localized, relative string exactly as eBay renders it, including the locale suffix ("6d 4h left", "Noch 5 Std 47 Min", "1g 6h rimasti"). A snapshot at scrape time — not an absolute end timestamp. null for fixed-price / Buy It Now listings.
Request
curl --request GET \
--url 'https://sold-comps.p.rapidapi.com/rapidapi/scrape-ebay?keyword=iphone+15+pro&count=60' \
--header 'X-RapidAPI-Key: YOUR_RAPIDAPI_KEY' \
--header 'X-RapidAPI-Host: sold-comps.p.rapidapi.com'Response
{
"keyword": "iphone 15 pro",
"page": 1,
"totalItems": 60,
"totalResults": "14,000+",
"hasNextPage": true,
"autoSelectedCategory": { "id": "9355", "name": "Cell Phones & Smartphones" },
"items": [
{
"itemId": "256123456789",
"url": "https://www.ebay.com/itm/256123456789?nordt=true",
"thumbnailUrl": "https://i.ebayimg.com/images/g/3nkAAeSwCitqGLiR/s-l500.webp",
"fullResThumbnailUrl": "https://i.ebayimg.com/images/g/3nkAAeSwCitqGLiR/s-l1600.webp",
"epid": "20049285656",
"title": "Apple iPhone 15 Pro 256GB Natural Titanium - Unlocked",
"condition": "Pre-Owned",
"conditionId": 3000,
"sellerType": null,
"buyingFormat": "buyItNow",
"bestOfferAccepted": false,
"bidCount": null,
"categoryId": null,
"listingType": "sold",
"endedAt": "2026-03-10",
"soldPrice": "899.99",
"soldCurrency": "USD",
"shippingPrice": null,
"shippingCurrency": null,
"shippingType": "free",
"totalPrice": "899.99",
"sellerUsername": "top-deals-store",
"sellerPositivePercent": 99.8,
"sellerFeedbackScore": 14200,
"itemLocation": "United States",
"scrapedAt": "2026-03-14T21:00:00.000Z"
}
]
}/v1/item/{itemId}Item detail lookup
includeDescription=true to also fetch the seller's item description (~200ms extra latency, no additional quota cost).Parameters
itemIdstringrequired- eBay item number (9-15 digits), e.g. 168647489856. Also accepts a full eBay item URL — the handler extracts the numeric ID.
ebaySitestringoptionaldefault:ebay.com- eBay domain. Determines the currency of the returned price and shipping (e.g. USD on ebay.com, GBP on ebay.co.uk).
ebay.comebay.co.ukebay.deebay.frebay.itebay.esebay.caebay.com.au includeDescriptionbooleanoptionaldefault:false- When true, fetches the seller's item description as sanitized plain text. Adds ~200ms latency, no additional quota cost.
Response fields
itemIdstring- eBay item number.
urlstring- Canonical item URL.
titlestring | null- Full listing title.
pricestring | null- Current or sold price as a numeric string (e.g. "799.99"). On a sale with an accepted Best Offer this is the accepted amount, not the asking price.
originalPricestring | null- The list price eBay shows struck through next to the sold price — the asking price before an accepted Best Offer or a markdown. null when the page shows none.
currencystring | null- ISO currency code (e.g. "USD", "GBP"). Depends on ebaySite.
conditionstring | null- Item condition label (e.g. "Pre-Owned", "Graded - PSA 10").
conditionDescriptionstring | null- Seller's condition notes, if provided.
endedboolean- Whether the listing has ended (sold or expired).
endedDatestring | null- When the listing ended (e.g. "Sep 03, 2026 15:43:00 PDT"). Localized on non-English sites. null for active listings.
soldBannerstring | null- Sold banner text (e.g. "Item sold on Thu, Sep 3 at 3:43 PM"). English sites only; null on non-English sites and active listings.
bestOfferAcceptedboolean- true when the sold listing shows a struck-through list price next to the sold price. price is then the amount paid and originalPrice is the list price. This is the case for an accepted Best Offer and also for a seller markdown. false in all other cases, including active listings.
bidCountnumber | null- Number of bids on auction listings. null for Buy It Now / Best Offer.
itemSpecificsRecord<string, string>- All item specifics as key-value pairs (e.g. {"Brand": "Apple", "Model": "iPhone 15 Pro", "Storage Capacity": "256 GB"}). Typically 10-30 fields per listing.
imagesstring[]- All listing image URLs at full resolution (1600px). Primary image first.
sellerobject | null- Seller details: username (string), feedbackPercent (number, e.g. 99.8), itemsSold (string — localized, e.g. "4.7K items sold" on English sites, "88 Artikel verkauft" on ebay.de), joinedDate (string — localized, e.g. "Joined Jun 2026" on English sites, "Mitglied seit Jun 2026" on ebay.de).
shippingstring | null- Shipping cost text (e.g. "Free shipping", "US $9.99").
locationstring | null- Item location (e.g. "San Jose, California, United States").
returnPolicystring | null- Return policy text.
descriptionstring | null- Seller's item description as plain text. null when the description has not been fetched — pass includeDescription=true to fetch it.
categoryPathstring | null- Breadcrumb path (e.g. "Cell Phones & Accessories > Cell Phones & Smartphones").
categoryIdstring | null- Leaf category ID from the breadcrumb.
scrapedAtstring- ISO 8601 timestamp of when the data was fetched.
Request
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
"https://api.sold-comps.com/v1/item/168647489856"Response
{
"itemId": "168647489856",
"url": "https://www.ebay.com/itm/168647489856",
"title": "2022 Pokemon Card 2022 S-Chinese Mimikyu CSM1.5C 014/060 Grade 10",
"price": "4.99",
"originalPrice": null,
"currency": "USD",
"condition": "Graded - Other 10",
"conditionDescription": null,
"ended": true,
"endedDate": "Sep 03, 2026 15:43:00 PDT",
"soldBanner": "Item sold on Thu, Sep 3 at 3:43 PM",
"bestOfferAccepted": false,
"bidCount": 1,
"itemSpecifics": {
"Condition": "Graded - Other 10: Professionally graded",
"Game": "Pokémon TCG",
"Language": "Chinese",
"Manufacturer": "The Pokémon Company",
"Card Type": "Pokémon",
"Finish": "Holo",
"Card Size": "Standard",
"Material": "Card Stock",
"Vintage": "No",
"Country of Origin": "China"
},
"images": [
"https://i.ebayimg.com/images/g/PWcAAeSwRYJqdpUE/s-l1600.jpg",
"https://i.ebayimg.com/images/g/EaMAAeSwYPFqdpPo/s-l1600.jpg"
],
"seller": {
"username": "ptcg-Pokémon",
"feedbackPercent": 100,
"itemsSold": "4.7K items sold",
"joinedDate": "Joined Jun 2026"
},
"shipping": "US $9.99",
"location": "Fuzhou City, Fujian, China",
"returnPolicy": "Seller does not accept returns. If the item you received doesn't match the listing description, your purchase may be eligible for eBay Money Back Guarantee if the return request is made within 3 days from delivery.",
"description": null,
"categoryPath": "Toys & Hobbies > Collectible Card Games > Single Cards",
"categoryId": "1893526",
"scrapedAt": "2026-09-03T18:30:00.000Z"
}/v1/mercariSearch Mercari listings (Beta)
sold parameter.
This endpoint is in beta and may return errors under heavy load.
Failed requests are not charged against your quota.Query parameters
keywordstringrequired- Mercari search term.
pageintegeroptionaldefault:1- Page number. Maps to offset = (page - 1) * count. Increment until hasNextPage is false.
countinteger (1–100)optionaldefault:100- Items per page (max 100).
sortOrderenumoptionaldefault:bestMatch- Sort order for results.
bestMatchnewestlowestPricehighestPricemostPopular minPricenumberoptional- Minimum price filter in dollars.
maxPricenumberoptional- Maximum price filter in dollars.
itemConditionenumoptionaldefault:any- Condition filter.
anynewlikeNewgoodfairpoor categoryIdstringoptional- Mercari category ID (an integer). For more than one, separate them with commas, e.g. "1,2". A value that is not a number is ignored, with no error.
brandIdstringoptional- Mercari brand ID (an integer). For more than one, separate them with commas, e.g. "1,2". A value that is not a number is ignored, with no error.
soldbooleanoptionaldefault:true- true = sold listings (default), false = active/currently-listed items.
Response fields (each item)
itemIdstring- Mercari item ID (e.g. "m19578215278").
urlstring- Canonical Mercari listing URL.
titlestring- Listing title.
pricestring- Price in dollars as a string with 2 decimal places (e.g. "25.00").
currencystring- Always "USD" (Mercari US is USD-only).
originalPricestring | null- Pre-discount price. null when same as price.
conditionstring | null- "New", "Like New", "Good", "Fair", or "Poor".
conditionIdnumber | null- Numeric condition ID (1–5).
statusstring- "sold" or "active".
imageUrlstring | null- Full-resolution CDN image URL.
thumbnailUrlstring | null- 200×200 thumbnail URL.
sellerIdstring | null- Numeric seller ID as string.
brandstring | null- Brand name (e.g. "Pokemon").
categoryIdnumber | null- Leaf category numeric ID.
categoryNamestring | null- Leaf category label.
marketplacestring- Always "mercari".
Request
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
"https://api.sold-comps.com/v1/mercari\
?keyword=pokemon+cards\
&count=10\
&sortOrder=newest"Response
{
"keyword": "pokemon cards",
"page": 1,
"count": 10,
"totalResults": 5844,
"totalItems": 10,
"hasNextPage": true,
"items": [
{
"itemId": "m19578215278",
"url": "https://www.mercari.com/us/item/m19578215278/",
"title": "Pokemon TCG Charizard VMAX Rainbow 074/073 PSA 10",
"price": "185.00",
"currency": "USD",
"originalPrice": null,
"condition": "Like New",
"conditionId": 2,
"status": "sold",
"imageUrl": "https://static.mercdn.net/item/detail/orig/photos/m19578215278_1.jpg",
"thumbnailUrl": "https://static.mercdn.net/c!/w=200/thumb/photos/m19578215278_1.jpg",
"sellerId": "472918365",
"brand": "Pokemon",
"categoryId": 753,
"categoryName": "Trading Cards",
"marketplace": "mercari"
}
],
"marketplace": "mercari",
"scrapedAt": "2026-09-02T14:30:00.000Z"
}/v1/poshmark/soldSearch Poshmark sold listings
enrich=true, each request costs 2 quota slots — the extra slot covers the per-listing detail API call that adds sold date, days to sell, seller location, and other enrichment fields.
The extra slot is charged on every 200, also when the page has 0 items or the detail calls failed.Query parameters
keywordstringrequired- Poshmark search term.
pageintegeroptionaldefault:1- Page number. Each page returns up to 48 items (Poshmark's native page size). Increment until hasNextPage is false.
minPricenumberoptional- Minimum price filter (USD).
maxPricenumberoptional- Maximum price filter (USD).
departmentenumoptionaldefault:all- Poshmark department filter.
allwomenmenkidshomepetselectronics conditionenumoptionaldefault:all- Condition filter. "nwt" = New With Tags only. This is not the condition field of an item, which is an enrichment field with Poshmark's own label.
allnwt brandstringoptional- Filter by brand name (e.g. "Louis Vuitton").
sortByenumoptionaldefault:sold_recently- Sort order for results.
sold_recentlyprice_ascprice_desclikes enrichbooleanoptionaldefault:false- When true, each listing is enriched via Poshmark's detail API, adding soldAt, listedAt, daysToSell, colors, description, category, condition, commentsCount, shareCount, shippingCost, sellerLocation, sellerSoldCount, and sellerAvgShipTime. Costs 2 quota slots instead of 1. When false (default), only search-page fields are returned (faster, 1 slot).
Enrichment costs 2 quota slots.
With enrich=true, each request consumes 2 slots from your monthly quota instead of 1.
The extra slot covers the per-listing detail API call that populates brand, likesCount, sellerUsername, soldAt, listedAt, daysToSell, category, condition, colors, description, shippingCost, commentsCount, shareCount, sellerLocation, sellerSoldCount, and sellerAvgShipTime.
When enrich=false (the default), those fields are null ([] for colors) and only 1 slot is consumed.
With 1 slot left in your quota and no credits, an enrich=true request returns 429.
Response fields (each item)
listingIdstring- Poshmark listing ID (24-char hex).
urlstring- Canonical Poshmark listing URL.
titlestring- Listing title.
soldPricenumber | null- Sale price in USD.
originalPricenumber | null- Original listing price in USD.
sizestring | null- Size label (e.g. "OS", "M", "10").
nwtboolean- New With Tags flag.
thumbnailUrlstring | null- Listing thumbnail URL.
scrapedAtstring- ISO 8601 timestamp when the listing was scraped.
Enrichment fields (enrich=true only)
These fields are populated only when enrich=true.
When enrichment is off or fails for a listing, they return null (or [] for colors).
brandstring | null- Brand name.
likesCountnumber | null- Number of likes on the listing.
sellerUsernamestring | null- Poshmark seller username.
soldAtstring | null- ISO timestamp when the item sold.
listedAtstring | null- ISO timestamp when the item was first published.
daysToSellnumber | null- Days between listedAt and soldAt.
categorystring | null- Department > Category path, two levels at most (e.g. "Women > Bags").
conditionstring | null- Item condition label from Poshmark (e.g. "Pre-owned"). Not related to the condition query parameter (all / nwt); for New With Tags use the nwt field.
colorsstring[]- Color names. Empty array when not enriched.
descriptionstring | null- Full listing description text.
shippingCostnumber | null- Shipping cost in USD.
commentsCountnumber | null- Number of comments on the listing.
shareCountnumber | null- Number of shares.
sellerLocationstring | null- Seller city and state (e.g. "Los Angeles, CA").
sellerSoldCountnumber | null- Total listings the seller has sold.
sellerAvgShipTimenumber | null- Seller's average ship time in days.
Enriched response (enrich=true)
With enrich=true, each item includes the full set of enrichment fields.
The default (enrich=false) response is shown at the top of this endpoint.
{
"keyword": "louis vuitton neverfull",
"page": 1,
"totalItems": 48,
"hasNextPage": true,
"items": [
{
"listingId": "6478a1b2c3d4e5f6a7b8c9d0",
"url": "https://poshmark.com/listing/Louis-Vuitton-Neverfull-6478a1b2c3d4e5f6a7b8c9d0",
"title": "Louis Vuitton Neverfull MM Damier Ebene",
"soldPrice": 1250,
"originalPrice": 1960,
"shippingCost": 7.97,
"brand": "Louis Vuitton",
"size": "OS",
"category": "Women > Bags",
"condition": "Pre-owned",
"nwt": false,
"colors": ["Brown"],
"description": "Authentic Louis Vuitton Neverfull MM in Damier Ebene...",
"soldAt": "2026-07-15T18:30:00.000Z",
"listedAt": "2026-06-01T12:00:00.000Z",
"daysToSell": 44.27,
"likesCount": 23,
"commentsCount": 4,
"shareCount": 12,
"sellerUsername": "luxurycloset",
"sellerLocation": "Los Angeles, CA",
"sellerSoldCount": 847,
"sellerAvgShipTime": 1.5,
"thumbnailUrl": "https://di2ponv0v5otw.cloudfront.net/posts/2026/07/15/...",
"scrapedAt": "2026-08-09T14:30:00.000Z"
}
]
}Request
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
"https://api.sold-comps.com/v1/poshmark/sold\
?keyword=louis+vuitton+neverfull\
&page=1\
&department=women\
&sortBy=sold_recently"Response
{
"keyword": "louis vuitton neverfull",
"page": 1,
"totalItems": 48,
"hasNextPage": true,
"items": [
{
"listingId": "6478a1b2c3d4e5f6a7b8c9d0",
"url": "https://poshmark.com/listing/Louis-Vuitton-Neverfull-6478a1b2c3d4e5f6a7b8c9d0",
"title": "Louis Vuitton Neverfull MM Damier Ebene",
"soldPrice": 1250,
"originalPrice": 1960,
"shippingCost": null,
"brand": null,
"size": "OS",
"category": null,
"condition": null,
"nwt": false,
"colors": [],
"description": null,
"soldAt": null,
"listedAt": null,
"daysToSell": null,
"likesCount": null,
"commentsCount": null,
"shareCount": null,
"sellerUsername": null,
"sellerLocation": null,
"sellerSoldCount": null,
"sellerAvgShipTime": null,
"thumbnailUrl": "https://di2ponv0v5otw.cloudfront.net/posts/2026/07/15/...",
"scrapedAt": "2026-08-09T14:30:00.000Z"
}
]
}/v1/tcgplayer/searchSearch TCGPlayer products (Beta)
Query parameters
keywordstringrequired- TCGPlayer search term.
pageintegeroptionaldefault:1- Page number. Maps to offset-based pagination internally.
countintegeroptionaldefault:24- Items per page (max 50).
sortOrderenumoptionaldefault:bestMatch- Sort order for results.
bestMatchbestSellingazpriceHighToLowpriceLowToHigh
Response fields (each item)
productIdnumber- TCGPlayer's unique product identifier — the number in the product URL.
namestring- Full product name as shown on TCGPlayer.
setNamestring | null- The TCG set/expansion this card belongs to (e.g. "Battle Academy 2022").
raritystring | null- Card rarity level (e.g. "Holo Rare", "Common", "Ultra Rare").
numberstring | null- Card number within the set (e.g. "043/185").
setCodestring | null- Short set abbreviation (e.g. "BA22") — shown in parentheses after the set name on TCGPlayer.
setIdnumber | null- TCGPlayer's numeric set identifier — useful for programmatic set-level queries.
marketPricenumber | null- TCGPlayer's Market Price — a proprietary algorithm based on recent sales. The primary valuation metric for TCG cards.
lowestPricenumber | null- TCGPlayer's aggregate lowest-price metric. Can be stale or reflect a different condition than what the website shows. See lowestListingPrice for the actual cheapest current listing.
lowestListingPricenumber | null- Cheapest current seller listing price — the price shown as "X listings from $Y" on TCGPlayer search results. Includes all conditions (the website filters to Near Mint by default).
lowestPriceWithShippingnumber | null- Cheapest all-in price (card + shipping) across all listings — what a buyer would actually pay minimum.
medianPricenumber | null- Listed median price. Null for low-volume products.
totalListingsnumber | null- Total active seller listings across all conditions and printings. The website may show fewer because it filters to Near Mint by default.
foilOnlyboolean | null- Whether this product only comes in foil/holo printing — no "Normal" variant exists.
imageUrlstring | null- Card image URL. Null when the search API omits it.
urlstring- Direct link to the TCGPlayer product page.
productLinestring | null- The game (e.g. "Pokemon", "Magic", "Yu-Gi-Oh!").
marketplacestring- Always "tcgplayer".
listingsarray | null- Cheapest seller listings for this product. See listing fields below.
Seller listing fields (listings array)
Each product includes the cheapest seller listings from TCGPlayer. These are the individual "buy now" offers — the same data shown when you click a product on TCGPlayer.
pricenumber- Seller's card price before shipping.
shippingPricenumber- Shipping cost. Most TCGPlayer sellers charge $1.49 standard.
totalPricenumber- price + shippingPrice — total cost to the buyer.
conditionstring | null- Card condition: Near Mint, Lightly Played, Moderately Played, Heavily Played, or Damaged.
printingstring | null- Print variant: Normal, Holofoil, Reverse Holofoil, 1st Edition, etc.
languagestring | null- Card language (e.g. "English").
quantitynumber | null- How many copies this seller has available.
sellerNamestring | null- Seller's store or username on TCGPlayer.
sellerRatingnumber | null- Seller feedback rating (0–100%).
verifiedSellerboolean | null- TCGPlayer Verified — seller meets TCGPlayer's quality and shipping standards.
directSellerboolean | null- TCGPlayer Direct — cards shipped to and authenticated by TCGPlayer's warehouse, then shipped to buyer. Similar to "Fulfilled by Amazon".
Request
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
"https://api.sold-comps.com/v1/tcgplayer/search\
?keyword=charizard\
&count=10"Response
{
"keyword": "charizard",
"page": 1,
"count": 10,
"totalResults": 706,
"totalItems": 10,
"hasNextPage": true,
"items": [
{
"productId": 274439,
"name": "Charizard",
"setName": "Pokemon GO",
"rarity": "Holo Rare",
"number": "010/078",
"setCode": "PGO",
"setId": 3121,
"marketPrice": 3.68,
"lowestPrice": 0.99,
"lowestListingPrice": 1.15,
"lowestPriceWithShipping": 2.48,
"medianPrice": 4.39,
"totalListings": 88,
"foilOnly": false,
"imageUrl": null,
"url": "https://www.tcgplayer.com/product/274439",
"productLine": "Pokemon",
"marketplace": "tcgplayer",
"listings": [
{
"price": 1.15,
"shippingPrice": 1.49,
"totalPrice": 2.64,
"condition": "Lightly Played",
"printing": "Normal",
"language": "English",
"quantity": 3,
"sellerName": "CardShop TCG",
"sellerRating": 99.8,
"verifiedSeller": true,
"directSeller": false
}
]
}
],
"marketplace": "tcgplayer",
"scrapedAt": "2026-09-07T20:00:00.000Z"
}/v1/tcgplayer/salesTCGPlayer sales history (Beta)
productId from search results.
With condition, you get up to 5 of the most recent sales of that condition, so one request per condition gives more sales.
variant and language are different: they filter the sales that came back (5 at most), so they can return fewer than 5 sales, or none.
totalResults and hasNextPage are TCGPlayer's own values: totalResults can be larger than the number of items returned, and this endpoint has no page parameter.
Same auth and middleware stack as the eBay endpoints.
Each request costs 1 quota slot.
This endpoint is in beta and may return errors under heavy load.
Failed requests are not charged against your quota.Query parameters
productIdintegerrequired- TCGPlayer product ID (from search results).
conditionenumoptional- Returns up to 5 of the most recent sales of this condition. Without it, up to 5 of the most recent sales of any condition.
nearMintlightlyPlayedmoderatelyPlayedheavilyPlayeddamaged variantstringoptional- Filter the returned sales (5 at most) by printing variant (e.g. "Holofoil", "Normal"). Not case-sensitive. Applied after the fetch, so it can return fewer than 5 sales, or none.
languagestringoptional- Filter the returned sales (5 at most) by card language (e.g. "English"). Not case-sensitive. Applied after the fetch, so it can return fewer than 5 sales, or none.
listingTypeenumoptionaldefault:All- Filter by listing photo presence.
AllListingWithPhotosListingWithoutPhotos
Response fields (each item)
pricenumber- The price the card sold for (before shipping).
shippingPricenumber- Shipping cost paid.
totalPricenumber- price + shippingPrice — total transaction amount.
conditionstring | null- Condition of the card that sold.
variantstring | null- Printing variant (e.g. "Holofoil").
languagestring | null- Card language.
quantitynumber | null- How many cards in this transaction.
soldDatestring | null- ISO 8601 timestamp when the sale occurred.
listingTypestring | null- Listing type (e.g. "ListingWithoutPhotos", "ListingWithPhotos").
marketplacestring- Always "tcgplayer".
Request
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
"https://api.sold-comps.com/v1/tcgplayer/sales\
?productId=274439"Response
{
"productId": 274439,
"totalResults": 5,
"hasNextPage": false,
"items": [
{
"price": 4.66,
"shippingPrice": 4.90,
"totalPrice": 9.56,
"condition": "Near Mint",
"variant": "Holofoil",
"language": "English",
"quantity": 1,
"soldDate": "2026-09-07T18:32:25.75+00:00",
"listingType": "ListingWithoutPhotos",
"marketplace": "tcgplayer"
}
],
"marketplace": "tcgplayer",
"scrapedAt": "2026-09-07T20:00:00.000Z"
}/usageUsage and remaining requests
Authorization: Bearer key as the search endpoints.
This call is free: it does not count against your monthly quota, your credits, or the per-minute limit of the search endpoints.
/usage and /requests share a limit of 60 calls per minute.Response fields
planstring- Your current plan, e.g. starter. plan_label is its display name.
usage.limitnumber- Monthly request cap for your plan.
usage.usednumber- Requests counted in the current billing period.
usage.remainingnumber- limit minus used, never below 0.
usage.period_startstring- ISO 8601 start of the current billing period.
usage.reset_atstring- ISO 8601 time when the billing period resets.
rate_limit.rpmnumber- Your per-minute request cap on the search endpoints.
rate_limit.remainingnumber | null- Requests remaining in the current minute window. null if it cannot be read at the moment.
rate_limit.resetnumber | null- Unix epoch seconds when the minute window resets.
credits.balancenumber- Purchased pay-as-you-go credits left.
Request
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
"https://api.sold-comps.com/usage"Response
{
"plan": "starter",
"plan_label": "Starter",
"usage": {
"limit": 2000,
"used": 1234,
"remaining": 766,
"period_start": "2026-09-04T16:20:11.000Z",
"reset_at": "2026-10-04T16:20:11.000Z"
},
"rate_limit": {
"rpm": 60,
"remaining": 58,
"reset": 1791217260
},
"credits": {
"balance": 100
}
}/requestsRequest history
401, 429 or 400 (apart from page_limit) are not listed.
A request usually appears within a few seconds of its response.
This call is free and shares the 60 calls per minute limit of /usage.
To page, call again with cursor set to next_cursor while has_more is true.Query parameters
limitnumberoptionaldefault:50- Rows per page, 1–100. Values outside the range are clamped.
cursorstringoptional- next_cursor from the previous page. Send the same from / to with it.
fromstringoptional- Date as YYYY-MM-DD (UTC). Only requests on or after this day. History goes back at most 90 days; an older date is moved to that limit.
tostringoptional- Date as YYYY-MM-DD (UTC). Only requests on or before this day; the whole day is included.
Response fields (each request)
request_idstring- ID of the request.
created_atstring- ISO 8601 time of the request, UTC.
endpointstring | null- The endpoint that was called, e.g. /v1/scrape or /api/bulk-search. null on old rows.
sourcestring- api = called with an API key, dashboard = a search in the dashboard, max-mode = one page of a Max Mode job (one row per page).
apidashboardmax-mode marketplacestring- ebay, poshmark, mercari or tcgplayer.
listing_typestring | null- Sold or active listings. eBay requests only; null for other marketplaces.
soldactive keywordstring- The search keyword. For /v1/item it is the item ID, for /v1/tcgplayer/sales the product ID.
page / count / sitenumber / number | null / string | null- The page, page size and eBay site of the request. site is null for other marketplaces.
filtersobject- The other search parameters as the API applied them, defaults included (category, sort order, price range, condition, dates, …). null where a parameter was not set or does not apply. marketplace_params holds the Poshmark, Mercari and TCGPlayer parameters.
result_countnumber | null- Number of items returned.
has_next_pageboolean | null- hasNextPage of the response.
duration_msnumber | null- How long the request took.
successboolean- true if the request returned 200.
errorstring | null- Why a failed request failed. null on success.
at_capacitytimeoutitem_not_foundpage_limitupstream_error max_mode_job_idstring | null- The Max Mode job this page belongs to.
usage.used from /usage is the number your quota is measured with.
A count of successful rows from /requests can differ from it: a request with hydrateBoa=true that finds a Best Offer price counts as 2, a Poshmark request with enrich=true counts as 2, requests paid with credits are not in used, and failed requests are not counted.
Request
curl -H "Authorization: Bearer sc_YOUR_KEY_HERE" \
"https://api.sold-comps.com/requests?limit=50&from=2026-10-01"Response
{
"requests": [
{
"request_id": "0b9f6f0e-6f0c-4c62-9a43-7c1f0d1c2a11",
"created_at": "2026-10-04T14:03:22.418Z",
"endpoint": "/v1/scrape",
"source": "api",
"marketplace": "ebay",
"listing_type": "sold",
"keyword": "pokemon charizard psa 10",
"page": 1,
"count": 240,
"site": "ebay.com",
"filters": {
"category_id": "0",
"sort_order": "endedRecently",
"min_price": null,
"max_price": null,
"item_location": "default",
"item_condition": "any",
"buying_format": null,
"condition_id": null,
"aspect_filter": null,
"exact_match": true,
"sold_after": null,
"sold_before": null,
"seller_type": null,
"include_complete_listing": true,
"marketplace_params": null
},
"result_count": 240,
"has_next_page": true,
"duration_ms": 2140,
"success": true,
"error": null,
"max_mode_job_id": null
}
],
"has_more": true,
"next_cursor": "MjAyNi0xMC0wNCAxNDowMzoyMi40MTgxMjd8NDgyMTE5MzQ"
}