eBay Scraper - Listings, Sellers & Sold Price Check
Under maintenancePricing
from $3.50 / 1,000 listings
eBay Scraper - Listings, Sellers & Sold Price Check
Under maintenanceTrack competitor prices on eBay without the eBay API. Scrape any search into typed rows: price with currency, sold count, condition, shipping, seller username and feedback. Then pass item IDs to checkItems to see which ones sold, at what price and on what date. Hard cap on results.
Pricing
from $3.50 / 1,000 listings
Rating
0.0
(0)
Developer
Henry Crawl
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
eBay Scraper - Listings, Sellers, Feedback & Sold Count
Track competitor prices on eBay without the eBay API. Point it at any eBay search, category page or filtered listing URL and get typed rows back — no developer account, no OAuth, no rate-limit paperwork.
Every row carries the seller username, feedback percentage and feedback count that most
eBay scrapers leave empty, prices already parsed into numbers with a currency code, the
sold counter where eBay shows one, and a hard cap on how many listings a run may return so
the bill cannot surprise you.
Common uses: repricing against competitors, tracking a category's price band over time, building a supplier or seller shortlist, and feeding price data into a dashboard.
What you get per listing
| Field | Example | Notes |
|---|---|---|
itemId | 197740124597 | Stable eBay id, use it to deduplicate across runs |
title | YETI Rambler 20 oz Tumbler… | |
priceRaw | $35.00 | Exactly as eBay rendered it |
priceValue | 35 | Parsed number, ready to filter and aggregate |
priceMax | 48.5 | Filled when the listing shows a price range |
currency | USD | Derived from the rendered price |
condition | Brand New | |
sellerName | oliviabrian1234 | |
sellerFeedbackPercent | 100 | |
sellerFeedbackCount | 489 | 6K and 94.2K are expanded to real numbers |
soldCount | 461 | Present on the listings where eBay shows it |
watchers | 60 | |
bidCount | 3 | Auctions only |
shippingRaw | +$28.60 delivery | |
shippingValue | 28.6 | 0 when shipping is free |
freeShipping | false | |
itemLocation | United States | Where the item ships from |
imageUrl, itemUrl | ||
pageNumber, searchKeyword, inputUrl | Provenance of every row | |
ebaySite, proxyCountry, scrapedAt | The exact context the data was captured in |
Two ways to search
1. Build a search from filters — no URL needed. Add one or more keywords; each runs as its own search with the same filters:
{"keywords": ["yeti rambler 20 oz tumbler", "stanley quencher 40 oz"],"ebaySite": "www.ebay.com","proxyCountry": "US","condition": "new","buyingFormat": "buy_it_now","minPrice": 20,"maxPrice": 60,"sortBy": "price_lowest","maxListings": 2000}
2. Paste URLs — any eBay search, category or filtered listing page:
{"startUrls": ["https://www.ebay.com/sch/i.html?_nkw=yeti+rambler&_sacat=0&rt=nc&LH_BIN=1"],"proxyCountry": "US","maxListings": 500}
Filters available: eBay site, keyword exclusions, category, min/max price, condition, buying format, free shipping, and the same sort options as eBay's own dropdown.
Sold prices: ask the listing, not the search
eBay puts sold search behind sign-in — signed out, …&LH_Sold=1&LH_Complete=1 redirects to
signin.ebay.com/...&sgfl=srch. Getting past that would mean running automated searches
through a real eBay account, and the account, not the scraper, is what eBay suspends. This
actor does not go there.
An individual listing page is a different surface, and it is open: signed out it answers
normally, eBay's robots.txt allows /itm/<id>, and the sale is stated in plain text. So pass
checkItems the listings you care about and get the real numbers:
{"checkItems": ["225076150467","https://www.ebay.com/itm/223223631102","398249946847"],"proxyCountry": "US"}
223223631102 SOLD AU $9.98 sold 2026-07-09T06:19:17.000Z225076150467 SOLD C $40.00 sold 2026-07-12T01:24:17.000Z398249946847 ACTIVE US $100.00186082326577 ENDED_NOT_SOLD US $9.99117340485562 ENDED_PRICE_UNAVAILABLE
saleStatus is the field to trust, and it has five values:
| Value | Meaning |
|---|---|
SOLD | It sold. soldAt carries the exact timestamp, price what it went for |
ACTIVE | Still listed; price is the current asking price |
ENDED_NOT_SOLD | The seller pulled it. Not a sale |
ENDED_NO_SALE | An auction closed with no bids |
ENDED_PRICE_UNAVAILABLE | Ended auction on a catalogue-matched item — see the limit below |
Why not just read availability? Because eBay marks a pulled listing OutOfStock exactly
like a sold one. Treating that as a sale quietly turns unsold stock into fake comps, and
nothing downstream can spot the error. The sentence eBay prints is the only field that
separates them, so that is what saleStatus is built from.
The honest limits
- There is no keyword search for sold items here. That is the part eBay gates. You supply the listings — usually item IDs a previous search run returned, re-checked days later.
- Ended auctions can lose their final price. When the item matches an eBay catalogue
product, eBay redirects the ended listing to that catalogue page, which does not show the
winning bid. Those rows come back
ENDED_PRICE_UNAVAILABLEwith no price rather than carrying the catalogue's asking price as if it were a sale. - One page per row. A search page yields up to 240 listings; a listing page yields one. Set
maxListingsaccordingly — it caps this mode too. checkItemsignoreskeywordsandstartUrls; run the search separately.
Still free, still public: soldCount on active listings — the "X sold" figure eBay prints
— needs no item check at all and comes with every search row.
Proxy country matters more than you would expect
eBay localises listing pages: prices, currency, shipping costs, and even which
listings appear depend on the country of the IP making the request. Requesting
www.ebay.com from outside the US can return prices in a different currency
entirely. Set proxyCountry to the market you care about — it defaults to US.
ebaySite and proxyCountry are independent: ebaySite picks which regional eBay
to load, proxyCountry decides which market you appear to be shopping from.
Residential proxies are used by default. eBay refuses datacenter IP ranges, so a datacenter group will simply produce a failed run.
The result cap is real
maxListings stops the run at exactly that number. Scrapers that treat their limits
as suggestions produce surprise bills; this one exits as soon as the cap is met, and
also stops on its own if three consecutive pages return nothing usable.
Runs fail loudly, not silently
Every run writes a DIAGNOSTICS record to the key-value store with the block rate,
bytes per item, and the fill rate of every single output field:
{"itemsExtracted": 200,"blockRate": "0%","mbPer1000Items": 19.06,"fieldCoverage": { "priceValue": "100%", "sellerName": "92%", "currency": "100%" }}
If nothing was extracted, or more than half the pages were blocked, the run is marked failed with the reason. A dataset full of empty columns is worse than an error, because the problem only shows up after you have used the data.
Typical uses
- Competitor and marketplace price monitoring, with the seller behind each price
- Turnover research using
soldCounton live listings - Tracking which sellers list a given brand, and at what price
- Building product and pricing datasets for internal tools or dashboards
Notes and limits
soldCountandwatchersappear only on the listings where eBay displays them; they are reported asnullelsewhere rather than guessed.- eBay places a promotional label in the footer of every result card, organic ones included, so this actor does not claim to separate promoted listings from organic ones. It does drop the "Shop on eBay" placeholder cards, which carry no data.
- Keep
maxConcurrencylow. eBay authorises by session, so parallelism burns sessions faster than it saves time.
Support
Found a field that stopped filling, or need a filter that is not exposed yet? Open an issue on the actor page with the input you used — layout changes on eBay are normal and get fixed.
FAQ
Do I need an eBay API key or developer account? No. This reads eBay's public search and category pages, so there is nothing to register for and no OAuth flow. You only need an Apify account.
How do I get eBay sold prices without the API?
Read the listing page instead of the search. An individual /itm/<id> page is public — it
answers a signed-out request normally, and eBay's robots.txt allows that path — and it states
the sale outright: "This listing sold on Sat, Jul 11 at 6:24 PM." Pass those item IDs to
checkItems and you get the sold price, the exact ISO timestamp and the seller, with no key,
no OAuth and no account. What stays out of reach is searching sold items by keyword; that
particular page is the one eBay puts behind sign-in.
I applied for eBay's Marketplace Insights API and was denied. What are the alternatives?
That API returns 90 days of sold data but is Limited Release, and denials are the norm rather
than the exception — developers with apps in production for years and thousands of users report
being turned down, including ones already in the eBay Partner Network. Rather than reapply,
two public sources cover most of what it was wanted for: soldCount on active listings (the
"X sold" figure eBay prints itself) and checkItems on specific listings, which returns the
actual sale price and date from the listing page.
How can I tell whether an eBay listing ended because it sold or because the seller pulled it?
Not from the availability field, which is the usual mistake — eBay marks both cases
OutOfStock. The difference is the sentence eBay prints on the page, and this actor reads it:
This listing sold on … becomes saleStatus: SOLD, while
This listing was ended by the seller on … because …ENDED_NOT_SOLD, and an auction that closed without bids
becomes ENDED_NO_SALE. Treating "ended" as "sold" is what quietly fills a comps table with
prices nobody ever paid.
Can I get eBay sold data without logging in?
For specific listings, yes — listing pages are served to signed-out visitors, and that is all
checkItems uses. For keyword searches of sold items, no: signed out, a sold search redirects
to signin.ebay.com. The workarounds circulating for that involve driving automated searches
through a real eBay account, and it is the account that gets suspended, so this actor does not
implement them.
Can it get sold prices and completed listings?
Yes for specific listings, no for keyword searches. Pass checkItems a list of item IDs or
/itm/ URLs and each row comes back with saleStatus, the actual sold price and the exact
sale timestamp, read from the public listing page — no eBay account or cookies involved. What
it cannot do is search for sold items by keyword: that surface is behind eBay's sign-in wall,
and the only way through is to automate someone's real account, which risks that account.
How do I get the item IDs to check?
From a search run of this same actor. Scrape a keyword today, keep the itemId column, then
feed those IDs to checkItems a week later — the ones that come back SOLD give you the price
and the date they sold at, which is the turnover picture sold comps are usually bought for.
Does an ended listing always mean it sold?
No, and this is where sold data usually goes wrong. eBay marks a listing the seller pulled as
OutOfStock, exactly like one that sold. This actor reads the status sentence instead, so a
pulled listing returns ENDED_NOT_SOLD and never enters your dataset as a sale.
Why do my prices come back in the wrong currency?
eBay prices by IP country. Requested from outside the US, ebay.com can answer in the local
currency with local delivery. Set proxyCountry to match the marketplace you actually want,
and check the currency field on the rows rather than assuming.
How do I avoid a surprise bill?
maxListings is a hard stop, not a suggestion. The run also fails loudly rather than
returning half a dataset: zero items, or a block rate above 50%, ends the run with an error
so you never pay for a quietly incomplete scrape.
What happens when eBay blocks a request? The session is retired and the request retried on a fresh one. Every run reports its block rate, bytes per item and per-field coverage in the log, so you can see the quality of the data instead of guessing.
How do I get eBay sold data?
Three routes exist and only one is open to most people. eBay's Marketplace Insights API returns
90 days of sold data but is Limited Release, and denials are routine — developers with apps in
production for years report being turned down. Terapeak shows the same data in a browser but has
no public API behind it. The third route is the listing page itself: /itm/<id> is served to
signed-out visitors, eBay's robots.txt allows it, and it states the outcome in plain text along
with an exact timestamp. That is what checkItems reads. You supply the item IDs — typically
ones a search run of this actor returned earlier — and you get back the real sale price and date.
How do I find eBay sold prices for items I am tracking?
Run a search for the products you care about and keep the itemId column, then pass those IDs
to checkItems a few days or weeks later. Listings that sold come back saleStatus: SOLD with
the price they went for and an exact soldAt timestamp; ones still running come back ACTIVE
with the current asking price. Repeating that on a schedule is what turns a list of listings
into a price history, and none of it needs an eBay account.
Is there an eBay sold listings API I can call?
Not a public one from eBay. This actor is the closest practical substitute for the item-level
case: give it eBay item IDs and it returns typed rows — saleStatus, price, currency,
soldAt, sellerName, quantitySold — over Apify's normal API, so you can call it from any
language. The honest gap versus the official API is search: eBay gates keyword search of sold
items behind sign-in, so this cannot find sold items by keyword, only report on listings you
already have IDs for.
How do I see eBay sold history without a browser extension? The sold-history extensions people use are reading the same public pages, one at a time, in your browser. This does it server-side and in bulk, and returns typed rows instead of a rendered page, which is the difference that matters if you want the numbers in a spreadsheet or a database rather than on screen.
How do I build an eBay price history for a product?
By snapshotting it yourself, because eBay does not publish one. Run a search for the product on a
schedule and keep every row — each carries priceValue, currency, soldCount and scrapedAt,
so a week of runs is already a price series with the seller behind each point. Where it gets more
useful is combining that with checkItems: feed back the itemId values from earlier runs and
the listings that have since sold return SOLD with the price they actually went for and an
exact timestamp, which turns an asking-price series into a record of what the market paid.
Related scrapers
Same approach applied elsewhere — typed rows, a cap that is actually enforced, and a diagnostics record on every run:
- eBay Seller Scraper — the companion to this one: point it at a seller instead of a search.
- Amazon Product Scraper — prices, ASIN and demand signals, with every row checked against the currency you asked for.
- Indeed Jobs Scraper — absolute posting dates rather than relative labels.
- LinkedIn Jobs Scraper — no login, no cookie, and cheap to run because it needs no browser.