eBay Sold Listings Intelligence
Pricing
from $25.00 / 1,000 results
eBay Sold Listings Intelligence
Get real market prices from eBay sold listings. See what items ACTUALLY sold for, not asking prices. Includes pricing analytics, market velocity, demand levels, and recommended listing price. Perfect for resellers, collectors, estate sales, inheritance sales.
Pricing
from $25.00 / 1,000 results
Rating
4.1
(5)
Developer
Marielise
Maintained by CommunityActor stats
2
Bookmarked
333
Total users
34
Monthly active users
11 days ago
Last modified
Categories
Share
Extract real market prices from eBay completed sales. Unlike listing prices (what sellers hope to get), this eBay scraper shows you what buyers actually paid. Get pricing analytics, market velocity, condition-based insights, and sales trends for any product on eBay.
Perfect for: eBay resellers, estate sale pricing, collectors, Poshmark sellers, consignment shops, and anyone researching actual market values.
Features
| Feature | Description |
|---|---|
| Real Sold Prices | Actual transaction prices, not wishful listing prices |
| Recommended Price | Statistically optimal listing price based on recent sales |
| Price Range Analysis | 10th-90th percentile range where 80% of sales happen |
| Market Velocity | How fast items sell (very_fast to very_slow), measured from each listing's real start and end dates. Returns null when eBay does not expose a listing date (for example multi-quantity store listings, which never end), rather than reporting a guess. |
| Demand Level | Sales per day across the window the returned sales actually span |
| Condition Breakdown | Median price and premium/discount per condition, so you can see exactly what "Parts Only" or "Refurbished" costs you. On a live iPhone 13 Pro run, for-parts units sold 48% below the overall median and new units 108% above it. |
| Listing Type Analysis | Auction vs Buy It Now price comparison, with average bid count |
| Ships From | Item location per sale, so a cheap-looking comp that ships from overseas is visible as such |
| Multi-Market Support | 8 eBay sites (US, UK, DE, FR, IT, ES, CA, AU), each read in its own currency |
| Honest nulls | Anything eBay did not state comes back null. A blocked run reports status: "blocked" with null pricing instead of a fabricated $0.00 "recommended price" - and bills nothing. |
| Batch Processing | Up to 200 sold listings per run |
How to Use
Step 1: Configure Your Search
Enter a search query describing what you want to research. Be specific for better results.
Step 2: Set Filters (Optional)
Narrow down results by condition, price range, listing type, or time period.
Step 3: Run and Get Results
The Actor scrapes eBay sold listings and returns:
- Pricing summary with recommended price and market insights
- Individual sold items with full details
- CSV export for spreadsheet analysis
- Markdown report for easy sharing
Input Examples
Basic Price Check
Find out what an iPhone 13 Pro sells for:
{"query": "iPhone 13 Pro 128GB","maxItems": 50}
Filtered Search
Research vintage Levi's in specific conditions:
{"query": "vintage Levi's 501","condition": ["good", "very_good"],"soldWithinDays": 60,"maxItems": 100}
International Market Research
Check PlayStation 5 prices in the UK:
{"query": "PlayStation 5","ebaySite": "ebay.co.uk","maxItems": 50}
Collectibles Research
Research Pokemon card sales with price filters:
{"query": "Pokemon Charizard card","priceMin": 50,"priceMax": 500,"soldWithinDays": 30,"maxItems": 100}
Input Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
query | string | Yes* | - | Search keywords (e.g., "iPhone 13 Pro 128GB") |
ebayUrl | string | Yes* | - | Or paste an eBay URL to find similar items |
ebaySite | string | No | ebay.com | eBay marketplace (US, UK, DE, FR, IT, ES, CA, AU) |
soldWithinDays | integer | No | 30 | Only items sold in last N days (max 90) |
condition | array | No | all | Filter: new, open_box, certified_refurbished, like_new, very_good, good, acceptable, for_parts |
priceMin | number | No | - | Minimum sold price |
priceMax | number | No | - | Maximum sold price |
listingType | array | No | all | Filter: auction, buy_it_now, best_offer |
categoryId | string | No | - | eBay category ID to narrow search |
maxItems | integer | No | 50 | Items to scrape (10-200) |
sortBy | string | No | date_desc | Sort order: date_desc, date_asc, price_desc, price_asc |
includeAnalytics | boolean | No | true | Generate pricing intelligence summary |
outputFormat | string | No | full | Output detail: full, summary_only, items_only |
enrichFromItemPages | boolean | No | true | Reads listing start dates, bid counts and watcher counts from a sample of item pages. This is the only source of daysToSell and marketVelocity. Set to false for a noticeably faster run when you only need prices. |
proxy | object | No | Apify RESIDENTIAL | Leave as is. eBay reputation-blocks datacenter IPs, so residential is the floor here, not an escalation. |
Note: Provide eitherqueryorebayUrl, not both. The Actor extracts search terms from eBay URLs automatically. If you supply neither, the Actor does not fail - it runs a small demo search foriPhone 13 Pro 128GBso you can see the output shape, and says so in the log.
Output
The Actor outputs data in multiple formats for flexibility.
Dataset Output
Results are saved to the Apify dataset with two record types:
Every example below is real output, copied verbatim from a live run of
{"query": "iPhone 13 Pro 128GB", "maxItems": 30, "soldWithinDays": 30}. Field names are
exactly as the Actor emits them, so you can code against them directly.
Summary Record (1 per run, always the last record):
{"type": "summary","status": "ok","summary": {"recommendedPrice": { "cents": 27900, "display": "$279.00", "currency": "USD" },"priceRange": {"low": { "cents": 13999, "display": "$139.99", "currency": "USD" },"high": { "cents": 58001, "display": "$580.01", "currency": "USD" }},"marketVelocity": "fast","averageDaysToSell": 4.6,"demandLevel": "high","quickTake": "iPhone 13 Pro 128GB sells fast (5 days avg) at $139.99-$580.01. High demand. List at $279.00 for optimal sale.","confidence": "low","confidenceReason": "Limited data: only 27 sales found - results may vary. Days to sell measured from 4 listing(s) with a known listing date."},"analytics": {"prices": {"mean": { "cents": 31611, "display": "$316.11", "currency": "USD" },"median": { "cents": 27900, "display": "$279.00", "currency": "USD" },"min": { "cents": 7800, "display": "$78.00", "currency": "USD" },"max": { "cents": 61895, "display": "$618.95", "currency": "USD" },"standardDeviation": 14671,"percentile10": { "cents": 13999, "display": "$139.99", "currency": "USD" },"percentile90": { "cents": 58001, "display": "$580.01", "currency": "USD" }},"volume": {"totalSold": 27,"soldPerDay": 13.5,"avgDaysToSell": 4.6,"medianDaysToSell": 3},"byCondition": {"good": { "count": 10, "avgPrice": { "display": "$301.84" }, "medianPrice": { "display": "$275.00" }, "pctOfTotal": 37, "pctVsMedian": -1 },"for_parts": { "count": 6, "avgPrice": { "display": "$147.75" }, "medianPrice": { "display": "$145.00" }, "pctOfTotal": 22, "pctVsMedian": -48 },"new": { "count": 4, "avgPrice": { "display": "$501.49" }, "medianPrice": { "display": "$580.01" }, "pctOfTotal": 15, "pctVsMedian": 108 },"certified_refurbished": { "count": 6, "avgPrice": { "display": "$394.87" }, "medianPrice": { "display": "$428.50" }, "pctOfTotal": 22, "pctVsMedian": 54 },"open_box": { "count": 1, "avgPrice": { "display": "$254.89" }, "medianPrice": { "display": "$254.89" }, "pctOfTotal": 4, "pctVsMedian": -9 }},"byListingType": {"auction": { "count": 2, "avgPrice": { "display": "$80.75" }, "medianPrice": { "display": "$80.75" }, "avgBidCount": 12 },"buyItNow": { "count": 25, "avgPrice": { "display": "$334.94" }, "medianPrice": { "display": "$300.00" } }},"dateRange": { "from": "2026-08-10T23:00:00.000Z", "to": "2026-08-10T23:00:00.000Z", "daysAnalyzed": 2 }},"meta": {"searchQuery": "iPhone 13 Pro 128GB","searchUrl": "https://m.ebay.com/sch/i.html?_nkw=iPhone+13+Pro+128GB&_fsrp=1&LH_Sold=1&LH_Complete=1&_ipg=240&_sop=13","totalMatches": 4800,"itemsReturned": 27,"itemsAnalyzed": 27,"scrapedAt": "2026-08-12T06:32:31.564Z","processingMs": 25940,"dataFreshness": "Last 30 days"}}
status is ok, no_results or blocked. Always check it before reading pricing
fields - on a blocked run summary and analytics are null rather than zeroed, and no
item records are billed. See Troubleshooting.
Item Records (one per sold listing):
{"type": "item","itemId": "227470350737","title": "IPhone 12 Pro Max - Unlocked - 128GB - Pacific Blue - MG9T3LL/A (PD1126756)","url": "https://www.ebay.com/itm/227470350737","soldPrice": { "cents": 24999, "display": "$249.99", "currency": "USD" },"shippingPrice": null,"totalPrice": { "cents": 24999, "display": "$249.99", "currency": "USD" },"soldDate": "2026-08-10T23:00:00.000Z","listDate": "2026-08-10T19:21:23.000Z","daysToSell": 0.2,"condition": {"condition": "good","conditionDetail": "Pre-Owned"},"listingType": "buy_it_now","bidCount": null,"watchers": 5,"seller": {"username": null,"feedbackScore": null,"feedbackPct": null,"topRated": false},"shipping": {"cost": null,"freeShipping": false,"shippingType": null,"shipsFrom": "United States"},"thumbnailUrl": "https://i.ebayimg.com/images/g/POcAAeSwUcpqeiSy/s-l300.webp","imageUrls": ["https://i.ebayimg.com/images/g/POcAAeSwUcpqeiSy/s-l300.webp"],"categoryPath": null,"categoryId": null,"extractedAt": "2026-08-12T06:32:31.562Z"}
Field coverage: what is always there, and what is not
Prices, titles, conditions, sold dates and origin are present on essentially every record.
Four fields are frequently or always null, and the Actor returns null rather than a
plausible-looking guess:
| Field | Coverage | Why |
|---|---|---|
daysToSell, listDate | Partial - a sample of items, and only some of those | eBay's search results carry no listing date, so it is read from item pages (see enrichFromItemPages). Even then, the number is only emitted when the listing ended because this item sold. A multi-quantity store listing that has been live since 2022 and is still running has no meaningful "time to sell", so it returns null instead of "747 days". |
watchers, bidCount | Partial | Also item-page data. bidCount is present for auctions read from the card. |
seller.* | Always null | eBay does not put seller identity or feedback on the sold-listing cards this Actor reads. The keys are kept so the record shape stays stable, but do not build on them. |
categoryPath, categoryId | Always null | Not exposed on the sold-listing cards. |
Key-Value Store Outputs
| File | Format | Description |
|---|---|---|
OUTPUT.json | JSON | Complete output with summary, analytics, and all items |
sold_items.csv | CSV | All sold items in spreadsheet-friendly format |
REPORT.md | Markdown | Human-readable pricing intelligence report |
Understanding the Results
Market Velocity
| Level | Days to Sell | What It Means |
|---|---|---|
very_fast | < 2 days | Hot item, sells immediately - price competitively or slightly higher |
fast | 2-5 days | Strong demand - good opportunity for quick sales |
moderate | 5-10 days | Normal market - standard pricing works well |
slow | 10-20 days | Slower market - may need competitive pricing |
very_slow | > 20 days | Niche market - patience required or price adjustment needed |
Confidence Score
| Level | Sales Count | Reliability |
|---|---|---|
high | 100+ sales | Very reliable - sufficient data for accurate pricing |
medium | 30-99 sales | Good indication - reliable for most decisions |
low | < 30 sales | Use with caution - limited data, results are directional |
Demand Level
| Level | Daily Sales | Market Indication |
|---|---|---|
very_high | > 50 per day | Commodity market - price is set by competition, not scarcity |
high | 10-50 per day | Active market with many buyers |
medium | 2-10 per day | Healthy market activity |
low | 0.5-2 per day | Limited buyer interest - expect a wait |
very_low | < 0.5 per day | Thin market - treat the price range as directional only |
How this is measured:soldPerDayis the number of sales returned divided by the number of days those sales actually span, not bysoldWithinDays. Asking for 90 days in a market whose oldest visible sale is 12 days old divides by 12, not 90. Because the sample is capped bymaxItems, a largermaxItemsgives a steadier reading.
Supported eBay Sites
| Country | Domain | Currency |
|---|---|---|
| United States | ebay.com | USD |
| United Kingdom | ebay.co.uk | GBP |
| Germany | ebay.de | EUR |
| France | ebay.fr | EUR |
| Italy | ebay.it | EUR |
| Spain | ebay.es | EUR |
| Canada | ebay.ca | CAD |
| Australia | ebay.com.au | AUD |
Use Cases
Estate Sale Pricing
Got 200+ items to price? Run batch searches and get market data in minutes instead of hours of manual research. Export to CSV for inventory management.
Reseller Profit Margins
Know real sold prices before buying. See if that $50 thrift find actually sells for $200 or just $60. Calculate profit margins with confidence.
Collector Price Verification
Is that asking price fair? Compare against actual recent sales, not wishful listings. Make informed buying decisions based on real market data.
Consignment Shops
Data-driven pricing builds client trust. Show them the market data behind your suggested prices. Export professional reports with the markdown output.
Arbitrage Research
Compare prices across eBay marketplaces. Find items that sell higher in the UK than the US, or discover regional price differences.
API Integration
Node.js
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });const run = await client.actor('marielise.dev/ebay-sold-listings-intelligence').call({query: 'vintage band t-shirt',maxItems: 100,soldWithinDays: 30});const { items } = await client.dataset(run.defaultDatasetId).listItems();// Get the summary record. It is always the last record in the dataset.const summary = items.find(item => item.type === 'summary');// Always check status first: on a blocked run `summary.summary` is null rather than zeroed,// and no item records were written or billed.if (!summary || summary.status !== 'ok') {console.log('No pricing data collected:', summary?.status, summary?.blockReason);} else {console.log('Recommended Price:', summary.summary.recommendedPrice.display);console.log('Quick Take:', summary.summary.quickTake);}// Get individual sold itemsconst soldItems = items.filter(item => item.type === 'item');console.log(`Found ${soldItems.length} sold items`);
Python
from apify_client import ApifyClientclient = ApifyClient('YOUR_API_TOKEN')run = client.actor('marielise.dev/ebay-sold-listings-intelligence').call(run_input={'query': 'vintage band t-shirt','maxItems': 100,'soldWithinDays': 30})items = client.dataset(run['defaultDatasetId']).list_items().items# Get the summary recordsummary = next(item for item in items if item['type'] == 'summary')# Always check status first: on a blocked run 'summary' is None rather than zeroed,# and no item records were written or billed.if summary['status'] != 'ok':print('No pricing data collected:', summary['status'], summary.get('blockReason'))else:print(f"Recommended Price: {summary['summary']['recommendedPrice']['display']}")print(f"Quick Take: {summary['summary']['quickTake']}")# Get individual sold itemssold_items = [item for item in items if item['type'] == 'item']print(f"Found {len(sold_items)} sold items")
cURL
curl -X POST "https://api.apify.com/v2/acts/marielise.dev~ebay-sold-listings-intelligence/runs?token=YOUR_API_TOKEN" \-H "Content-Type: application/json" \-d '{"query": "vintage band t-shirt","maxItems": 100}'
Pricing
This Actor uses Pay Per Event pricing. You are charged $0.025 per result, where a result is one record in the default dataset, plus a negligible per-run start fee.
A run of maxItems: N produces N item records plus 1 summary record, so it bills N+1
results:
| maxItems | Results billed | Run cost | Typical use case |
|---|---|---|---|
| 10 (minimum) | 11 | ~$0.28 | Fast sanity check on one item |
| 50 (default) | 51 | ~$1.28 | Standard price research |
| 100 | 101 | ~$2.53 | Higher-confidence market read |
| 200 (maximum) | 201 | ~$5.03 | Comprehensive analysis, best confidence |
Runs that collect nothing charge nothing. If eBay blocks the run, or the search genuinely
has no sold listings, the Actor writes zero records to the dataset and reports the outcome
in the key-value store instead. There is no null result to pay for. You also keep full control
via the run-level Max total charge setting, which caps spend regardless of maxItems.
To control cost, lower maxItems - it is the only input that changes what you are billed.
Performance
Measured end-to-end run times, ebay.com over residential proxies:
| Configuration | Measured run time |
|---|---|
25 items, enrichFromItemPages: false | ~19 s |
30 items, enrichFromItemPages: true | ~26-47 s |
40 items, enrichFromItemPages: true | ~49 s |
Runtime is dominated by how many eBay refuses before one gets through, not by item count.
enrichFromItemPages: false is consistently the faster and cheaper mode; turn it off when you
only need prices and do not need daysToSell.
Limitations
- 200 items maximum per run
- ~90 days maximum sales history. This is eBay's own window for sold listings:
soldWithinDaysnarrows that window, it cannot extend past it seller.*is alwaysnull- eBay does not publish seller identity on sold-listing cards. See Field coveragedaysToSellcovers a sample, not every item, and is deliberatelynullfor listings that did not end at the sale (multi-quantity store listings especially)soldPerDayanddemandLeveldescribe the sample window, not eBay's whole catalogue. They are computed from the sales actually returned over the span those sales cover, so raisingmaxItemsgives a steadier figure- eBay rejects a share of residential IPs at random, so an occasional run returns fewer items than requested, or is blocked outright
Troubleshooting
No results found
If you get zero results, try:
- Broaden your search - Use fewer or more general keywords
- Extend the time range - Increase
soldWithinDaysto 60 or 90 - Remove filters - Clear condition or price filters
- Check spelling - Verify your search terms
Low confidence score
For rare or niche items:
- Use broader search terms
- Extend the date range to 60-90 days
- Consider the results as directional guidance rather than exact pricing
Proxy errors
eBay blocks datacenter IP addresses, so this Actor uses residential proxies by default. Keep that setting.
If you experience blocking:
- Confirm the proxy configuration is still set to
RESIDENTIAL. Switching to datacenter proxies will cause nearly every request to be blocked. - Simply re-run the Actor. eBay rejects a share of residential IPs at random, and each retry rotates to a fresh one.
If eBay refuses every attempt, the run succeeds with an explicit failure record rather than a silent empty result:
{ "type": "summary", "status": "blocked", "blockReason": "signin_gate", "summary": null, "analytics": null }
summary and analytics are null, never zeroed. A $0.00 "recommended price" would look like a real answer, so the Actor does not produce one when it collected no data. Check status before reading pricing fields.
blockReason tells you what to do next, and the three causes have nothing in common:
blockReason | What happened | What helps |
|---|---|---|
signin_gate | eBay redirected the sold-listings search to its sign-in page. This is content gating, not an IP block. | Re-run. Changing proxy groups will not help; the same gate is served to every exit node. |
antibot | eBay's anti-bot protection refused the requests outright. | Confirm RESIDENTIAL proxies, then re-run to draw different exit nodes. |
parser_stale | eBay served valid results this Actor could no longer read. A defect in the Actor, not a block. | Retrying and changing proxies both do nothing. Report it. |
Every run, including failed ones, writes RUN_DIAGNOSTICS.json to the key-value store with per-phase counters (warm-ups, gated pages, cards seen, and why each card was rejected).
FAQ
How is this different from searching eBay manually?
eBay shows individual listings. This Actor aggregates data and calculates analytics - averages, medians, price ranges, condition impact, and sell speed. What takes hours manually takes seconds here.
How accurate is the pricing data?
Data comes directly from eBay's completed listings - these are real transactions. Accuracy depends on sample size (check the confidence score). More sales = more reliable data.
Why is there a 200 item limit?
eBay rate limits scraping requests. For most pricing research, 50-100 items gives statistically reliable data. Run multiple searches for different items or variations.
Does this work for rare items?
For unique items, you'll get fewer results and lower confidence. Use broader search terms, extend the date range to 60-90 days, and treat results as directional rather than precise.
Can I search multiple items at once?
Each run searches for one item/query. For batch research, schedule multiple runs or use the Apify API to run searches programmatically.
What's the difference between query and ebayUrl?
Use query to search by keywords. Use ebayUrl to find items similar to a specific eBay listing - the Actor extracts the item title and searches for comparable sales.
How much does a run cost?
$0.025 per result, and a run bills maxItems + 1 results (the extra one is the summary
record). A default 50-item run is about $1.28. Lower maxItems to spend less, and use the
run-level Max total charge setting as a hard cap. A run that collects nothing writes no
dataset records and therefore bills nothing.
Why is daysToSell null on most items?
eBay's search results do not carry a listing start date, so it can only come from the item
page - and the Actor reads a bounded sample of those, not all of them, to keep runs fast and
cheap. Even for a page it did read, the number is only reported when the listing ended
because that item sold. A multi-quantity store listing that has been live for two years and
is still running has no meaningful time-to-sell, so it returns null rather than "747 days".
Set enrichFromItemPages: false if you do not need this at all.
Why is seller information always null?
eBay does not put the seller's username or feedback on the sold-listing cards this Actor
reads. The seller keys are kept so the record shape never changes between runs, but they
will not populate. Everything the cards do carry - price, shipping, condition, sold date,
item location - is extracted.
Why did I get fewer items than I asked for?
Two normal reasons. Either eBay simply has fewer sold listings matching your search, or some
of the sales it returned fell outside your soldWithinDays window and were filtered out.
Check meta.totalMatches and meta.itemsReturned in the summary record to tell which.
Do I need residential proxies?
Yes. eBay reputation-blocks datacenter IP ranges, so residential is the working floor, not an escalation of last resort. The default proxy configuration is already correct - changing it to datacenter proxies will cause almost every run to be blocked.
Can I use this for eBay UK, Germany, or other marketplaces?
Yes. Set ebaySite to any of the 8 supported marketplaces. Each is read in its own currency
(GBP on ebay.co.uk, EUR on ebay.de), and prices are never silently converted - if an exit
node causes eBay to render a page in the wrong currency, that page is discarded rather than
mixed into your averages.
Support
Questions or issues? We're here to help:
- Comments: Leave a comment on the Actor page
- Issues: Open an issue on GitHub
We respond to all feedback within 24 hours.