eBay Sold Listings Scraper: 3 Years Price History, Best Offer
Pricing
from $2.95 / 1,000 results
eBay Sold Listings Scraper: 3 Years Price History, Best Offer
Get confirmed eBay sold prices with up to 3 years of history and the real accepted Best Offer price, not the asking price. Search 8 eBay marketplaces, filter by condition, category and price range, export JSON or CSV for comps, resale pricing and price analytics.
Pricing
from $2.95 / 1,000 results
Rating
5.0
(5)
Developer
Sam Smith
Maintained by CommunityActor stats
0
Bookmarked
15
Total users
4
Monthly active users
4 days ago
Last modified
Categories
Share
eBay Sold Listings API: 3 Years of Price History, Real Sold Prices Only
Get eBay sold listings and completed listings as clean JSON, with up to 3 years of sales history and the real accepted Best Offer price, not the crossed out asking price. Sold comps for resale pricing, price analytics and market research, across 8 eBay marketplaces, no eBay login or developer approval needed.
Most eBay sold scrapers stop at 90 days, because that is all the public sold search shows. And when a sale goes through as an accepted Best Offer, they return the listing's asking price with a flag at best, an eBay page limitation they state themselves. This Actor fixes both: full multi year history and the price the buyer actually paid.
Why this one
| This Actor | Typical eBay sold scraper | |
|---|---|---|
| History | up to 3 years (1095 days) | 90 days |
| Best Offer sales | real accepted price + best_offer: true | asking price, flag at best |
| Speed | about 2 seconds per page of 240 sales | 5 to 10 seconds |
| Sold time | date and time | date only |
| Results per page | up to 240 | up to 240 |
| Marketplaces | 8 (US, UK, DE, FR, IT, ES, CA, AU) | usually US only |
In a side by side test on 4 popular searches, all 49 Best Offer sales that both tools returned were priced too high by a 90 day scraper. A Rolex Submariner listed at $24,995 actually sold for $15,500.
We then measured it properly across 5,859 Best Offer sales: 99.0% of them read high on the asking price, by a median of 14.9%. Full method and data: the Best Offer gap study.
What you can do with it
- Price inventory from real sales, including last year's prices for seasonal items.
- Track how resale prices move over months, not weeks.
- Build sold comps for trading cards, sneakers, watches, phones, consoles and collectibles.
- Feed pricing models, repricers, dashboards and spreadsheets with clean data.
Who this is for
Resellers and flippers pricing inventory, liquidation and estate sale buyers valuing manifests, card and sneaker tools showing live comps, repricing and cross listing software, analysts tracking secondary market prices, and anyone who lost access to sold data when eBay retired findCompletedItems and put sold listings behind a login.
Input
| Field | Description |
|---|---|
keywords | One search per line, for example iphone 15 pro 256gb. Minus words exclude: iphone 15 -pro -plus. |
days | How far back to search, 1 to 1095 (3 years). Default 90. |
maxResults | Max sales per keyword, newest first. Default 240. |
condition | any, new, open_box, refurbished, used or parts. |
bestOffer | mark (default) flags every sale and gives the real accepted price, only returns accepted Best Offer sales only, off skips the check. |
site | eBay marketplace: US (default, includes matching sales from other sites), UK, DE, FR, IT, ES, CA or AU. |
category | Optional eBay category id, comma separate for several, for example 31387 for wristwatches. |
minPrice / maxPrice | Only sales inside this sold price range. |
nativePrice | Also return the price in the currency the sale happened in, read from the listing. Off by default, see below. |
nativePriceBudget | Caps listing reads per run for the above. Default 200, max 1000. |
Example:
{"keywords": ["charizard psa 10", "rolex submariner 126610"],"days": 365,"maxResults": 500,"condition": "any","bestOffer": "mark"}
Output
One row per sold listing:
{"keyword": "nintendo switch oled","item_id": "227424612273","title": "Nintendo Switch OLED Model Console 64GB Blue/Neon Yellow Joy-Con *EXCELLANT Cond","price": 190.61,"best_offer": true,"us_sale": true,"native_price": 717.94,"native_currency": "GBP","last_sold": "2026-10-07T22:05:00Z","units_sold": 1,"total_sales": 190.61,"format": "FIXED_PRICE","bids": 0,"shipping_cost": 5.7,"free_shipping_pct": 0,"condition": "used","url": "https://www.ebay.com/itm/227424612273","image": "https://i.ebayimg.com/00/s/OTY5WDE1OTA=/z/jBYAAeSwuTdqh6QE/$_1.JPG?set_id=8800005007"}
priceis the price the item actually sold for. For an accepted Best Offer it is the accepted offer.best_offeristruefor accepted Best Offer sales,falsefor sales at the listed price or at auction,nullwhen it could not be confirmed.us_saleistruewhen the sale was made on eBay US andfalsewhen it was made on another eBay site. On the default search, which merges US with international coverage, this lets you separate the two without running a search per marketplace. Useful if you are building a US only price guide and the default's international sales would skew it.native_priceandnative_currencyappear when you switch on Original currency price.pricestays USD, so nothing else changes. They arenullwith anative_reasonon two kinds of row: a listing that sold several units, where the price is an average across those sales and so matches no single amount the page ever showed, and a listing that is still running, where the seller can change the price after the sale. On a UK search of single collectibles we measured 35 of 40 rows filled.conditionappears when you filter by one condition.units_soldandtotal_salescover multi quantity listings.
Export as JSON, CSV, Excel or connect to Google Sheets, Make, Zapier and n8n through Apify integrations.
Card comps: why the filters matter
Keyword search alone will not give you a card price. Measured on 17 October 2026, over three years of sales:
| Query | Median | Sales | Range |
|---|---|---|---|
charizard base set psa 10, raw sold feed | $14.73 | 239 listings | $1.30 to $30,000 |
| same words, junk filtered and outliers removed | $545.00 | 60 sales | p25 $236.77, p75 $2,861.08 |
The first number is not wrong, it is the honest median of what eBay returns: sleeves titled "fits PSA 10 Charizard", bulk lots, raw cards described as a "PSA 10 contender", and fan art proxies all match those words, and all of them are cheap.
Adding the card number to the query does not fix it. 4/102 is Base Set Charizard and it is also a later reprint, and a longer query makes eBay widen the match rather than narrow it.
What fixes it is filtering on parsed structure: graded, grader, grade and the junk flags (lot, mystery, accessory, replica, keyword_stuffing, not_graded_claim). Every sale carries a parsed card object with grade, grader, card number, year, language and first edition, so you can filter after retrieval instead of guessing in the query.
Full write up: why your card comps are wrong.
Need an API instead?
The same data is available as a REST API with monthly plans at compsapi.com: one GET request, about 2 seconds, up to 240 sales per page.
MCP server
The same data is available as a hosted MCP server, so an assistant can request comps directly. Details at compsapi.com.
FAQ
Is this a Terapeak alternative? For sold price research, yes: comparable history depth as JSON you can export and build on, without a Seller Hub subscription.
Is this the eBay Marketplace Insights API? No. Marketplace Insights is closed to new applicants and only covers 90 days. This Actor gives you up to 3 years without an eBay developer approval, a direct Marketplace Insights alternative.
Is this a findCompletedItems replacement? Yes. eBay retired the findCompletedItems API; this returns the same completed and sold listings data with more history.
Which eBay site? eBay US by default, with matching sales from other eBay sites included. Set site to UK, DE, FR, IT, ES, CA or AU to search one marketplace on its own.
What currency are the prices in? Always USD, whichever site you pick. eBay's research backend converts every amount to USD before we receive it, so a UK search returns USD too. A marketplace pin changes which sales you get, never the currency. If you need the original GBP or EUR amount, switch on Original currency price and each single, settled sale also carries native_price and native_currency, read from the listing rather than converted.
Why is original currency off by default, and what is the budget for? Every non US sale needs its own listing read, so it is the one input here with a real cost behind it. The budget caps those reads per run, 200 by default. Rows past the budget keep every other field with native_price null, and the run log tells you what it used. Prices already read are cached permanently, because a settled sale never changes price, so running the same search again is effectively free. Start with the default and raise it only if you need deeper coverage in one go.
How fresh is the data? Sales usually appear within minutes of the sale.
Why do some searches return accessories? eBay matches keywords in titles. Make searches specific (model number, size, grade) and use minus words, for example rolex submariner -bezel -strap -insert.
If this Actor saves you time, a rating helps other resellers find it. Found a problem or missing a field? Open an issue and it usually ships within days.
Not affiliated with eBay Inc. eBay is a trademark of eBay Inc.
How far back do eBay sold listings go? eBay's own public sold filter shows about 90 days, and the Marketplace Insights API is capped at 90 days and closed to new applicants. This Actor reaches 1,095 days, which is three years.
Why do my card searches return junk? eBay matches any arrangement of your words anywhere in the title, so accessories, lots and proxies all match. Filter on the parsed card fields and the junk flags rather than adding words to the query. See the card comps section above.