eBay sold prices in Google Sheets (with auto-refresh)
Put live eBay sold prices into Google Sheets with a custom =EBAYSOLD() function in Apps Script: median price, sale count, and a refreshable comps tab.
Resellers live in spreadsheets. This guide adds a custom =EBAYSOLD() function to Google Sheets so any cell can show the median sold price for an item, plus a script that fills a full comps tab.
1. Add the script
In your sheet open Extensions, Apps Script, paste this, and save:
const API = "https://api.ebaysoldlistingsapi.com/scrape";
const KEY = PropertiesService.getScriptProperties().getProperty("EBAY_SOLD_API_KEY");
function fetchSold_(keyword, site) {
const cache = CacheService.getScriptCache();
const ck = (site || "ebay.com") + "|" + keyword;
const hit = cache.get(ck);
if (hit) return JSON.parse(hit);
const url = API + "?keyword=" + encodeURIComponent(keyword) + "&ebaySite=" + (site || "ebay.com");
const res = UrlFetchApp.fetch(url, { headers: { Authorization: "Bearer " + KEY }, muteHttpExceptions: true });
if (res.getResponseCode() !== 200) throw new Error(JSON.parse(res.getContentText()).error);
const prices = JSON.parse(res.getContentText()).results
.map((r) => Number(r.soldPrice)).filter((n) => n > 0).sort((a, b) => a - b);
cache.put(ck, JSON.stringify(prices), 21600); // 6 hours
return prices;
}
/**
* Median eBay sold price for a keyword.
* @param {string} keyword Search term, e.g. "steam deck oled"
* @param {string} site Optional marketplace, e.g. "ebay.co.uk"
* @customfunction
*/
function EBAYSOLD(keyword, site) {
const p = fetchSold_(keyword, site);
if (!p.length) return "no sales";
const m = Math.floor(p.length / 2);
return p.length % 2 ? p[m] : (p[m - 1] + p[m]) / 2;
}
/** Number of completed sales found. @customfunction */
function EBAYSOLDCOUNT(keyword, site) {
return fetchSold_(keyword, site).length;
}Then open Project Settings, Script properties and add EBAY_SOLD_API_KEY with your key, so it never sits in a cell.
2. Use it
| A: Item | B: Formula | Result |
|---|---|---|
| steam deck oled | =EBAYSOLD(A2) | median sold price |
| shure sm7b | =EBAYSOLD(A3) | median sold price |
| barbour jacket | =EBAYSOLD(A4, "ebay.co.uk") | median in GBP |
| ps5 slim | =EBAYSOLDCOUNT(A5) | number of sales |
Results are cached for six hours, so reopening the sheet does not spend requests. Each uncached keyword uses one request from your plan.
3. Full comps tab from CSV
For every individual sale instead of one number, pull the CSV version of the endpoint into a tab:
function importComps() {
const kw = SpreadsheetApp.getActive().getSheetByName("Inputs").getRange("A1").getValue();
const res = UrlFetchApp.fetch(API + "?format=csv&keyword=" + encodeURIComponent(kw),
{ headers: { Authorization: "Bearer " + KEY } });
const rows = Utilities.parseCsv(res.getContentText());
const sh = SpreadsheetApp.getActive().getSheetByName("Comps") || SpreadsheetApp.getActive().insertSheet("Comps");
sh.clearContents();
sh.getRange(1, 1, rows.length, rows[0].length).setValues(rows);
}Add a time-driven trigger (Triggers, Add trigger, Time-driven) to refresh it daily.
Can I get eBay sold prices in Google Sheets for free?
Yes, within the free plan's 50 requests a month. With six-hour caching, that covers a small inventory sheet.
Why not IMPORTXML on the eBay sold page?
eBay blocks automated page fetches from Google's servers and changes its markup often, so IMPORTXML breaks. An API returns stable JSON or CSV.
Does it work in Excel?
Yes. In Excel use Data, From Web with the CSV URL (format=csv) and an Authorization header through Power Query.
Try it with real data
Get completed eBay sales as JSON. Fifty free requests a month, no card required.
Get your API key