ebaysoldlistingsAPI
Guide

eBay sold listings in Python: a complete example

Pull eBay sold listings into Python with requests, compute a clean median price, handle retries, run batch jobs, and load everything into pandas. Copy-paste code.

· 7 min read

This is a complete, production-ready Python workflow for eBay sold data: one search, a clean price, retries that survive busy moments, batch jobs for many keywords, and a pandas DataFrame at the end.

1. Setup

pip install requests pandas
export EBAY_SOLD_API_KEY="eb_..."   # from your dashboard

2. One search with retries

import os, time, requests

API = "https://api.ebaysoldlistingsapi.com"
HEADERS = {"Authorization": f"Bearer {os.environ['EBAY_SOLD_API_KEY']}"}
RETRY = {429, 502, 503, 504}

def sold(keyword, **params):
    for attempt in range(4):
        r = requests.get(f"{API}/scrape", params={"keyword": keyword, **params},
                         headers=HEADERS, timeout=90)
        if r.status_code not in RETRY:
            r.raise_for_status()
            return r.json()["results"]
        time.sleep(int(r.headers.get("Retry-After", 2 ** attempt)))
    r.raise_for_status()

rows = sold("shure sm7b", itemCondition="used")
print(len(rows), "sales")

Failed requests are never billed, so retrying 429, 502, 503, and 504 costs nothing. Do not retry 400 (bad parameter) or 402 (quota).

3. A price you can trust

Use the median, and trim the extremes that come from parts-only units and big bundles:

import statistics

def fair_price(rows, trim=0.1):
    prices = sorted(float(r["soldPrice"]) for r in rows if r.get("soldPrice"))
    k = int(len(prices) * trim)
    core = prices[k:len(prices) - k] or prices
    return {
        "n": len(prices),
        "median": statistics.median(core),
        "p25": core[len(core) // 4],
        "p75": core[(3 * len(core)) // 4],
    }

print(fair_price(rows))

4. Into pandas

import pandas as pd

df = pd.DataFrame(rows)
df["soldPrice"] = df["soldPrice"].astype(float)
df["endedAt"] = pd.to_datetime(df["endedAt"])
print(df.groupby("condition")["soldPrice"].agg(["count", "median"]))
weekly = df.set_index("endedAt")["soldPrice"].resample("W").median()

Prefer a file? Add format=csv and load it straight in: pd.read_csv(io.StringIO(r.text)).

5. Many keywords: batch jobs

job = requests.post(f"{API}/scrape/batch", headers=HEADERS, json={
    "keywords": ["shure sm7b", "steam deck oled", "ps5 slim"],
    "ebaySite": "ebay.com",
}).json()

while True:
    status = requests.get(f"{API}/scrape/batch/{job['jobId']}", headers=HEADERS).json()
    if status["status"] == "complete":
        break
    time.sleep(5)

for r in status["results"]:
    print(r["keyword"], r["status"], r["count"])

Each keyword counts as one request, and failed keywords are not charged. Download the whole job as one CSV from downloadUrl.

Is there a Python SDK?

You do not need one. The API is a single REST endpoint, so requests (or httpx) is all it takes. The examples above are complete.

What timeout should I use?

At least 90 seconds. Most searches return in a few seconds, but hard searches can take longer while the API retries on your behalf.

How do I get other countries?

Pass ebaySite, for example sold('barbour jacket', ebaySite='ebay.co.uk'). Prices return in the local currency.

Try it with real data

Get completed eBay sales as JSON. Fifty free requests a month, no card required.

Get your API key