CompSniper
Spreadsheet guide

How to pull eBay sold prices into Google Sheets automatically

Type a keyword in column A and get the median sold price, the typical range and the number of sales next to it, refreshed every morning. One short Apps Script and a free API key.
By Marc Andrew6 minute read
Short answer
Google Sheets cannot read eBay sold prices on its own, and IMPORTDATA cannot send an API key. Use Apps Script: it calls the CompSniper API for every keyword in column A and writes the median, the typical range (p25 to p75) and the number of sales, using up to 240 real eBay sales per keyword with the real accepted Best Offer price. A daily trigger keeps it fresh. 100 free requests a month, no eBay account.
01

Set up the sheet

Create a sheet with a header row and one search per row in column A. Write searches the way you would on eBay, with the details that change the price (model, size, grade). Columns B to F fill in automatically.

Sheet layout
   A (keyword)                         B (median)  C (low)  D (high)  E (sales)  F (updated)
1  Keyword                             Median      P25      P75       Sales      Updated
2  nintendo switch oled                ...         ...      ...       ...        ...
3  2023 topps chrome wembanyama psa 10 ...         ...      ...       ...        ...
4  shure sm7b                          ...         ...      ...       ...        ...

Then create a free CompSniper account and copy your API key from the dashboard.

02

Paste the script and add your key

Open Extensions > Apps Script, replace the sample code with the script below and save. In Project Settings > Script properties, add COMPSNIPER_API_KEY with your key, so the key never sits in a cell. Reload the sheet: a Sold prices menu appears. Click Update sold prices and approve the permissions once.

Apps Script
// Extensions > Apps Script, paste this, then save.
// Project Settings > Script properties: add COMPSNIPER_API_KEY = your cs_live_ key.

const API = "https://api.compsniper.com/v1/scrape";

function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu("Sold prices")
    .addItem("Update sold prices", "updateSoldPrices")
    .addToUi();
}

function updateSoldPrices() {
  const key = PropertiesService.getScriptProperties().getProperty("COMPSNIPER_API_KEY");
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  const lastRow = sheet.getLastRow();
  if (lastRow < 2) return;

  const keywords = sheet.getRange(2, 1, lastRow - 1, 1).getValues();
  const rows = keywords.map(([keyword]) => {
    if (!keyword) return ["", "", "", "", ""];
    const url = API + "?count=240&bestOfferPrice=true&keyword=" + encodeURIComponent(keyword);
    const res = UrlFetchApp.fetch(url, {
      headers: { Authorization: "Bearer " + key },
      muteHttpExceptions: true,
    });
    if (res.getResponseCode() !== 200) {
      return ["Error " + res.getResponseCode(), "", "", "", new Date()];
    }
    const s = JSON.parse(res.getContentText()).summary;
    if (!s || !s.count) return ["No sales", "", "", 0, new Date()];
    return [s.median, s.p25, s.p75, s.count, new Date()];
  });

  sheet.getRange(2, 2, rows.length, 5).setValues(rows);
}

Each keyword is one request to GET /v1/scrape, which returns up to 240 recent eBay sales. The median and range are calculated after accessories, parts and wrong models are removed. Add &ebaySite=ebay.co.uk (or .de, .fr, .it, .es, .ca, .com.au) for local prices on another eBay site.

03

Refresh it automatically every day

Add this function to the same script and run it once from the editor. Google then runs updateSoldPrices every morning, with the date of the last refresh in column F.

Apps Script: daily trigger
// Run this once from the Apps Script editor: refreshes the sheet every morning.
function createDailyRefresh() {
  ScriptApp.newTrigger("updateSoldPrices")
    .timeBased()
    .everyDays(1)
    .atHour(6)
    .create();
}
04

List every sale behind a price

The median is the quick answer. When you want the evidence, this optional function writes every sale for the keyword in A2 to a Sales tab: sold date, title, eBay's listed price, what the buyer actually paid on accepted Best Offers, shipping and the listing link.

Apps Script: Sales tab
// Optional: list every sale for one keyword on a "Sales" tab.
function pullSales() {
  const key = PropertiesService.getScriptProperties().getProperty("COMPSNIPER_API_KEY");
  const keyword = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange("A2").getValue();
  const res = UrlFetchApp.fetch(
    API + "?count=240&bestOfferPrice=true&keyword=" + encodeURIComponent(keyword),
    { headers: { Authorization: "Bearer " + key } }
  );
  const items = JSON.parse(res.getContentText()).items;
  const tab = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sales")
    || SpreadsheetApp.getActiveSpreadsheet().insertSheet("Sales");
  tab.clear();
  tab.appendRow(["Sold", "Title", "Sold price", "Paid (Best Offer)", "Shipping", "Currency", "Link"]);
  items.forEach((i) => tab.appendRow([
    i.endedAt, i.title, i.soldPrice, i.acceptedOfferPrice || "", i.shippingPrice, i.soldCurrency, i.url,
  ]));
}

Prefer no code? The dashboard exports any search as a CSV you can open in Sheets: see how to export eBay sold listings to CSV and Excel. For more than 90 days, call GET /v1/research/sold from the same script for up to 3 years of sales.

Frequently asked questions

eBay sold prices in Google Sheets

How do I get eBay sold prices into Google Sheets automatically?

Paste a short Apps Script into your sheet that calls the CompSniper API for each keyword in column A and writes the median, typical range and number of sales next to it. Add a daily time-driven trigger and the sheet refreshes itself every morning. A free CompSniper key includes 100 requests a month.

Can I use IMPORTDATA or IMPORTXML instead?

No. IMPORTDATA cannot send the Authorization header an API needs, and eBay's sold pages do not load reliably through IMPORTXML. Apps Script's UrlFetchApp can send the header, so it is the reliable way.

Does it show the real price on Best Offer sales?

Yes. The script adds bestOfferPrice=true, so accepted Best Offer sales carry acceptedOfferPrice, what the buyer actually paid, on US-dollar sales. The optional Sales tab shows it next to eBay's listed price.

How many keywords can one sheet update?

Each keyword is one API request. Apps Script runs for up to 6 minutes per run, which is enough for a few dozen keywords; split a longer list across several tabs or triggers. Each request returns up to 240 sales.

Can I get sales older than 90 days in Sheets?

Yes. Call GET /v1/research/sold from the same script for up to 3 years of eBay sold history, on every plan including free.

Do I need an eBay developer account?

No. You only need a CompSniper API key. No eBay account, developer approval or cookies.

Fill your sheet with real sold prices

Create a free API key, paste the script and click Update sold prices.