The eBay sold comps API: comps for one item in one call
The eBay sold comps API is GET /ebay/v1/sold. One call returns the last sales of an item, used or new, as JSON. This script turns 100 of them into a price.
Do these steps
Click the button to copy this prompt, then paste it into your coding agent. The link tells it which page you came from.
Read https://trawl.dev/llms.txt?from=/guides/ebay-sold-comps-api and help me integrate this API into my project.- Set your API key. Get a key from the free tier. terminal
export TRAWL_API_KEY=your_key - Name the item as a buyer would type it. Every word must be in the title. Put the words that mark a different item in
exclude. - Run the script in your language. Python needs the requests package. Node 18 needs nothing more. The search costs 1 credit.
# comps.py (pip install requests)
import os
import statistics
import requests
# Sold comps for one item: the last 100 sales of the same thing, used, priced from the sales.
r = requests.get(
"https://api.trawl.dev/ebay/v1/sold",
headers={"x-api-key": os.environ["TRAWL_API_KEY"]},
params={
"query": "iphone 15 pro 256gb",
"condition": "used",
"exclude": "max,case,cracked,parts,locked",
"max_pages": 1, # up to 100 sales, 1 credit
},
timeout=30,
)
r.raise_for_status()
sold = r.json()
sales = sold["results"]
prices = sorted(s["sale_price"] for s in sales)
n = len(prices)
print(f"{sold['count']} comps, {sold['credits_charged']} credit")
print(f"median {statistics.median(prices):.2f}, low {prices[0]:.2f}, high {prices[-1]:.2f}")
print(f"middle half {prices[n // 4]:.2f} to {prices[3 * n // 4]:.2f}")
print("latest five:")
for s in sales[:5]:
print(f" {s['date_sold'][:10]} {s['sale_price']:>8.2f} {s['title'][:56]}")// comps.mjs (Node 18 or newer, no packages)
const params = new URLSearchParams({
query: "iphone 15 pro 256gb",
condition: "used",
exclude: "max,case,cracked,parts,locked",
max_pages: "1", // up to 100 sales, 1 credit
});
const r = await fetch(`https://api.trawl.dev/ebay/v1/sold?${params}`, {
headers: { "x-api-key": process.env.TRAWL_API_KEY },
});
if (!r.ok) throw new Error(`${r.status} ${await r.text()}`);
const sold = await r.json();
const sales = sold.results;
const prices = sales.map((s) => s.sale_price).sort((a, b) => a - b);
const n = prices.length;
const median = n % 2 ? prices[(n - 1) / 2] : (prices[n / 2 - 1] + prices[n / 2]) / 2;
console.log(`${sold.count} comps, ${sold.credits_charged} credit`);
console.log(`median ${median.toFixed(2)}, low ${prices[0].toFixed(2)}, high ${prices[n - 1].toFixed(2)}`);
console.log(`middle half ${prices[Math.floor(n / 4)].toFixed(2)} to ${prices[Math.floor((3 * n) / 4)].toFixed(2)}`);
console.log("latest five:");
for (const s of sales.slice(0, 5)) {
console.log(` ${s.date_sold.slice(0, 10)} ${s.sale_price.toFixed(2).padStart(8)} ${s.title.slice(0, 56)}`);
}100 comps, 1 credit
median 527.49, low 345.00, high 749.00
middle half 484.99 to 564.99
latest five:
2026-10-15 495.00 Apple IPhone 15 Pro 256GB Natural Titanium, Unlocked. A2
2026-10-15 500.00 Apple iPhone 15 Pro-256GB Natural Titanium-UNLOCKED-90%
2026-10-15 455.00 iPhone 15 pro Unlocked 256gb - Excellent Condition - 86%
2026-10-15 425.00 iPhone 15 Pro 256GB Unlocked
2026-10-15 519.00 Apple iPhone 15 Pro in mint condition 256GB Titanium Blu100 comps, 1 credit
median 527.49, low 345.00, high 749.00
middle half 484.99 to 564.99
latest five:
2026-10-15 495.00 Apple IPhone 15 Pro 256GB Natural Titanium, Unlocked. A2
2026-10-15 500.00 Apple iPhone 15 Pro-256GB Natural Titanium-UNLOCKED-90%
2026-10-15 455.00 iPhone 15 pro Unlocked 256gb - Excellent Condition - 86%
2026-10-15 425.00 iPhone 15 Pro 256GB Unlocked
2026-10-15 519.00 Apple iPhone 15 Pro in mint condition 256GB Titanium BluWhat counts as a comp
A comp is a sale of the same item in the same condition. The eBay Sold Listings API matches every word of query in the title, so "iphone 15 pro 256gb" also matches a 15 Pro Max. exclude drops "max", and the cases, cracked screens, parts and carrier-locked phones with it. condition keeps used phones only. One page is 100 sales.
From comps to a price
The script sorts the 100 sale prices. The median is the price in the middle. The middle half runs from the 25th price to the 75th, and is the range most sales fall in. The low and high are the outliers: a wrong listing, a bundle, a mistake. Use the median to price, the middle half to set a floor and a ceiling, and ignore the mean, which the outliers move.
More comps, older comps
A count of 100 means the page is full and older sales exist. Raise max_pages for up to 2,000 in one response, or set date_from and date_to for a period. The eBay sold listings history guide reads a year of one query's sales, a month per call. For a graded card or a set, filter on an item specific with attr, as the scrape eBay sold listings Python guide does with a grade.
One comp in full
Each sale has an item_id. The eBay Sold Item Details API opens it: the item specifics, every image, the seller, the description, and whether the sale closed on an accepted Best Offer. Pass details=1 to the search to get that for every comp in the same call. How this compares to a service that reads eBay's sold search for you is the subject of Trawl vs the SoldComps API.