<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Colin Daniels</title>
    <description>The latest articles on DEV Community by Colin Daniels (@trawl).</description>
    <link>https://dev.to/trawl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4196785%2Fd53634a7-491a-45e8-acb8-2021cd1a9fa2.png</url>
      <title>DEV Community: Colin Daniels</title>
      <link>https://dev.to/trawl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/trawl"/>
    <language>en</language>
    <item>
      <title>eBay sold listings API in 2026: findCompletedItems is gone, here's what still works</title>
      <dc:creator>Colin Daniels</dc:creator>
      <pubDate>Tue, 20 Oct 2026 19:08:24 +0000</pubDate>
      <link>https://dev.to/trawl/ebay-sold-listings-api-in-2026-findcompleteditems-is-gone-heres-what-still-works-2407</link>
      <guid>https://dev.to/trawl/ebay-sold-listings-api-in-2026-findcompleteditems-is-gone-heres-what-still-works-2407</guid>
      <description>&lt;p&gt;If you search "ebay sold listings api" you land on a decade of Stack Overflow answers that all say the same thing: call &lt;code&gt;findCompletedItems&lt;/code&gt; on the Finding API with &lt;code&gt;SoldItemsOnly=true&lt;/code&gt;. That call has been dead since February 2025, when eBay shut the Finding API down. This is what the options look like now, with code for the one that actually returns sold prices.&lt;/p&gt;

&lt;p&gt;Disclosure up front: I build &lt;a href="https://trawl.dev" rel="noopener noreferrer"&gt;trawl&lt;/a&gt;, which is the last option below. The first four are eBay's own and the scrapers, and I've tried to describe them fairly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What findCompletedItems did
&lt;/h2&gt;

&lt;p&gt;One GET with keywords, an optional category and a &lt;code&gt;SoldItemsOnly&lt;/code&gt; filter, and you got back up to 100 completed listings per page with the final price, end time and condition. It was the backbone of every pricing tool, flipping spreadsheet and resale app that needed to know what things actually sell for. eBay restricted it in 2020 and removed it with the rest of the Finding API in 2025.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: the Browse API (no)
&lt;/h2&gt;

&lt;p&gt;eBay's replacement for Finding is the Browse API. It searches live listings. There is no sold filter, no completed filter and no way to reach ended items. If a tutorial tells you to use Browse for sold prices, it was written by someone who didn't run it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 2: the Marketplace Insights API (if they let you)
&lt;/h2&gt;

&lt;p&gt;This is the official sold-data API: &lt;code&gt;item_sales/search&lt;/code&gt; returns the last 90 days of sales for a keyword or category. The catch is access. It is a "limited release" API, you apply through developer support with a business case, and most applicants hear nothing. If you can get it, it's the right answer for 90 days of data. Comparison with what you'll read below is at &lt;a href="https://trawl.dev/compare/trawl-vs-ebay-marketplace-insights-api" rel="noopener noreferrer"&gt;trawl vs the Marketplace Insights API&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 3: Terapeak (not an API)
&lt;/h2&gt;

&lt;p&gt;Terapeak lives inside Seller Hub and shows up to three years of sold history in a browser. It has no API, no export beyond the page you're looking at, and it needs a seller account. It is good for a human looking up one item and useless for a program.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 4: scrapers
&lt;/h2&gt;

&lt;p&gt;Apify, RapidAPI and GitHub have dozens of scrapers that load eBay's sold-listings search page and parse it. They work until they don't: the page is behind a login wall for sold results more often each year, the HTML changes, and you only ever see the 90 days the page shows. For a one-off pull of a few hundred rows they're fine. For anything you run daily, you are now maintaining a scraper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 5: a sold-listings database with an API
&lt;/h2&gt;

&lt;p&gt;The approach that holds up is to query a database of completed sales rather than eBay's pages. &lt;a href="https://trawl.dev" rel="noopener noreferrer"&gt;trawl&lt;/a&gt; does that for ebay.com and ebay.co.uk: one GET returns every matching completed sale, newest first, with the final price, sale date, condition, shipping, buying format and item id, from a database of 400M+ sales that reaches back past the 90 days eBay shows. There's a free tier with no card.&lt;/p&gt;

&lt;p&gt;The old call, rewritten:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# pip install requests
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.trawl.dev/ebay/v1/sold&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TRAWL_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iphone 15 pro 256gb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# every word must appear in the title
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9355&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="c1"&gt;# Cell Phones &amp;amp; Smartphones, optional
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;condition&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;used&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;             &lt;span class="c1"&gt;# new, used, parts, other
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_pages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                  &lt;span class="c1"&gt;# 100 results per page, up to 20
&lt;/span&gt;    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sold&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; sold listings, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;sold&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;credits_charged&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; credits&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sold&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;date_sold&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;currency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sale_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A result row looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Apple iPhone 15 Pro 256GB Unlocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sale_price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;525.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"shipping_price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"currency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"used"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"condition_raw"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Pre-Owned"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"buying_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Buy It Now"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"date_sold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-14T00:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"item_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"item_link"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.ebay.com/itm/..."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things that map onto what people used findCompletedItems for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Price history past 90 days.&lt;/strong&gt; Add &lt;code&gt;date_from&lt;/code&gt; and &lt;code&gt;date_to&lt;/code&gt; (YYYY-MM-DD) and the same query answers for last spring. The &lt;a href="https://trawl.dev/guides/ebay-sold-listings-history" rel="noopener noreferrer"&gt;sold listings history guide&lt;/a&gt; walks a year.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A whole category.&lt;/strong&gt; Send &lt;code&gt;category&lt;/code&gt; with no &lt;code&gt;query&lt;/code&gt; and you get every sale in it, newest first, and a &lt;code&gt;next_cursor&lt;/code&gt; to keep walking past 2,000 results. That was never possible with findCompletedItems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Item specifics.&lt;/strong&gt; &lt;code&gt;attr=Grade:10&amp;amp;attr=Professional Grader:PSA&lt;/code&gt; filters on the listing's own specifics, which is how card and collectible pricing works.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The field-by-field translation of a &lt;code&gt;findCompletedItems&lt;/code&gt; request, in Python, Node and Go, is in the &lt;a href="https://trawl.dev/guides/findcompleteditems-alternative" rel="noopener noreferrer"&gt;findCompletedItems alternative guide&lt;/a&gt;. The same search also runs as an &lt;a href="https://apify.com/trawl/ebay-sold-listings-api" rel="noopener noreferrer"&gt;Actor on Apify&lt;/a&gt; if you'd rather pay per result there than hold an API key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which one
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You have Marketplace Insights access and 90 days is enough: use it, it's official.&lt;/li&gt;
&lt;li&gt;You need one lookup by hand: Terapeak in Seller Hub.&lt;/li&gt;
&lt;li&gt;You need a few hundred rows once: any scraper.&lt;/li&gt;
&lt;li&gt;You need sold prices in a program, daily, with history, or by category: a database-backed API is the only option that doesn't turn into maintenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions about the data or the API are welcome in the comments; I'll answer the ones about the competition too.&lt;/p&gt;

</description>
      <category>ebay</category>
      <category>api</category>
      <category>python</category>
      <category>data</category>
    </item>
  </channel>
</rss>
