eBay Product Scraper avatar

eBay Product Scraper

Under maintenance

Pricing

from $5.00 / 1,000 scraped product results

Go to Apify Store
eBay Product Scraper

eBay Product Scraper

Under maintenance

Fast, reliable eBay scraper. Extract product search results, pricing, shipping, seller specs, item condition & high-res images to JSON/Excel. No API key needed.

Pricing

from $5.00 / 1,000 scraped product results

Rating

0.0

(0)

Developer

Elena Vance

Elena Vance

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

an hour ago

Last modified

Share

Extract eBay listings — price, shipping, condition, seller rating, item specifics, images and descriptions — from keyword searches or direct listing URLs. No eBay API key, no login.

Results are stored in an Apify dataset you can export as JSON, CSV, Excel, XML or HTML.


What makes this scraper reliable

eBay does not simply return 403 when it does not like a request. It answers with a bot challenge page carrying a 200 OK status — a page that looks perfectly valid to a naive scraper and parses to zero rows. That is the single most common reason an eBay scraper "succeeds" while returning nothing.

This Actor is built around that reality:

  • Every response is screened before parsing. Challenge pages, eBay's branded error shell and blocked status codes all retire the current session and retry on a fresh proxy IP and browser fingerprint.
  • A page that loads but parses to nothing is treated as a failure, not as an empty result — unless eBay's own "no matches found" copy is on the page. Silent zero-row runs are impossible by construction.
  • The two ways of scraping nothing are told apart. A run where no page could be loaded fails with an actionable message; a search that genuinely has no matches succeeds and says so. Neither one finishes green with an unexplained empty dataset.
  • Both generations of eBay's markup are supported. eBay replaced the long-standing s-item search layout with s-card; the extractor reads either.

Adaptive crawling: fast when it can be, resilient when it must be

A browser is expensive — memory, time, and on residential proxies, bandwidth. Plain HTTP is roughly an order of magnitude cheaper, but eBay blocks it from some IP pools.

Rather than guessing, the Actor spends one probe request at startup to find out which transport eBay accepts for this run:

ResultWhat happens
Probe succeedsRuns on the fast HTTP crawler. Anything that later gets blocked is automatically retried in a real browser.
Probe is blockedRuns on the Playwright browser crawler, which executes the challenge JavaScript.

In browser mode, images, fonts, media and analytics are blocked before they are fetched, which cuts proxy bandwidth several-fold without losing any scraped data.

You can override the decision with Crawler mode (auto / http / browser).

Consistent, comparable rows

Two details that quietly ruin an eBay dataset are handled for you:

  • Proxy country is pinned to the marketplace. eBay quotes prices, shipping and currency in the requesting IP's locale, so an unpinned residential pool returns rows priced in whatever countries the proxies happened to land in. Searching ebay.de pins the pool to Germany unless you choose a country yourself.
  • The list layout is requested explicitly. Above 60 results per page eBay switches to a gallery card that silently drops seller name, feedback, watch and sold counts. The Actor forces the list layout at every page size, so those fields are present whether you ask for 10 items or 10,000.

Input

Provide a search keyword, start URLs, or both.

FieldTypeDefaultDescription
searcharray of stringsKeywords to search, e.g. ["macbook pro m3"]. Each is crawled separately.
startUrlsarrayeBay search-results URLs or listing (/itm/...) URLs. Non-eBay URLs are rejected.
ebaySitestringebay.comMarketplace for keyword searches. 18 regional sites supported.
maxItemsinteger2Hard cap on stored products. The run stops as soon as it is reached.
maxPagesPerQueryinteger5Pagination depth per search.
scrapeDetailsbooleantrueOpen each listing page for specifics, galleries, returns and description.
scrapeDescriptionbooleantrueFetch the seller's description iframe (one extra request per listing).
includeDescriptionHtmlbooleanfalseAlso store the description as raw HTML.
sortBystringbestMatchbestMatch, lowestPrice, highestPrice, newlyListed, endingSoonest.
itemConditionstringallall, new, refurbished, used.
listingTypestringallall, buyItNow, auction.
proxyConfigurationobjectApify Proxy, RESIDENTIALResidential proxies are strongly recommended.
crawlerModestringautoauto, http, browser.
maxConcurrencyinteger10Upper bound on parallel requests.
maxRequestRetriesinteger5Retries per request, each on a fresh identity.
debugSnapshotsbooleanfalseSave page HTML to the key-value store when extraction fails.

Example input

{
"search": ["macbook pro m3"],
"ebaySite": "ebay.com",
"maxItems": 200,
"scrapeDetails": true,
"itemCondition": "used",
"sortBy": "lowestPrice",
"proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}

Speed vs. depth

scrapeDetails: false is not a stripped-down mode — the search page alone already yields price, original price, shipping, condition, buying format, seller name and feedback, item location, watch counts and the main image. It costs one request per 60–240 listings instead of one per listing, so it is dramatically faster and cheaper. Turn details on when you need item specifics, full image galleries, variations, return policy or descriptions.


Pricing

This Actor is pay per event — you pay only for what a run actually does, not for compute time:

EventPriceWhen it's charged
Actor Start$0.02Once per run (scales with memory: 1 event per GB, minimum 1)
Scraped Product Result$0.003Once per listing saved to the dataset

Worked example: a default run (2048 MB, maxItems: 2) costs 2 × $0.02 for the start event, plus up to 2 × $0.003 for results — around $0.07. Turning off scrapeDetails doesn't change the per-result price, but it finishes faster and uses less proxy bandwidth per item.

maxItems scales the cost linearly — a 100-item run costs about $0.34, a 20-item run about $0.10. These two events are the entire cost of a run — there's no separate platform/compute charge on top. See the Pricing tab on this Actor's page for the current, canonical numbers.


Output

One dataset row per listing:

{
"itemId": "307090982870",
"url": "https://www.ebay.com/itm/307090982870",
"title": "Apple MacBook Pro 16\" (512GB SSD, M3 Pro, 18GB) Space Black",
"subtitle": "Brand New · 16 in · 512 GB",
"condition": "Brand New",
"price": 1849.26,
"priceText": "$1,849.26",
"currency": "USD",
"originalPrice": null,
"shipping": 279.46,
"shippingText": "+$279.46 shipping estimate",
"freeShipping": false,
"buyingFormat": "Best Offer",
"itemLocation": "United Kingdom",
"watchers": 13,
"soldCount": null,
"seller": { "name": "reece_c94", "feedbackPercent": 100, "feedbackScore": 136 },
"brand": "Apple",
"mpn": "MRW13LL/A",
"specifics": { "Brand": "Apple", "Screen Size": "16 in", "Processor": "M3 Pro" },
"images": ["https://i.ebayimg.com/images/g/VxsAAeSwYelqaEGZ/s-l1600.webp"],
"variations": [],
"returnPolicy": "30 days returns. Buyer pays for return shipping.",
"availability": "More than 10 available",
"descriptionText": "…",
"isSponsored": true,
"scrapedAt": "2026-08-18T09:12:44.481Z"
}

Notable fields:

  • price / currency — parsed from the marketplace's own locale format, so 1.249,99 on ebay.de and 1,249.99 on ebay.com both become 1249.99.
  • shipping0 for free shipping, null when eBay does not state a cost (never silently guessed as 0).
  • isSponsored — eBay renders a reversed, transparent decoy label on every card; this field resolves the real aria-labelledby target, so it flags only genuine paid placements.
  • url — canonicalised to https://<marketplace>/itm/<id>, with tracking parameters stripped, so the same listing is never scraped twice.
  • seller.feedbackScore — locale-aware: 4.286 on ebay.de and 143.4K on ebay.com both resolve to a plain integer.

Requests that fail after all retries are written to a separate failed-requests dataset, keeping the main dataset free of error rows.


Troubleshooting

"Scraped 0 items — no page could be loaded" eBay is rejecting the IP pool. Enable Apify Proxy with the RESIDENTIAL group, try a different proxy country, and lower maxConcurrency.

"eBay returned no listings for this input" The pages loaded fine and eBay genuinely had no matches, so the run succeeds with an empty dataset rather than failing. Check the keyword, the marketplace and the condition/listing-type filters.

Fewer items than maxItems The search had fewer matches, maxPagesPerQuery capped the crawl, or some listings ended mid-run. Raise maxPagesPerQuery if the search itself had more results.

"…markup may have changed" eBay altered its HTML. Re-run with debugSnapshots: true; the offending page is stored in the key-value store, which is exactly what a bug report needs.

A field I set doesn't seem to be applied An out-of-range number or an unrecognized value (a typo in sortBy, crawlerMode, ebaySite, etc.) does not fail the run — it falls back to that field's default and logs a warning explaining what was ignored and why. Check the run log for a line starting with "Falling back to defaults for...".


Development

npm install
npm test # 104 unit + integration tests, no network required
apify run --purge # local run; reads storage/key_value_stores/default/INPUT.json

Tests run against a fixture captured from a live eBay results page, so a markup change breaks the suite rather than the production run.

This Actor collects data that eBay publishes publicly, without logging in. You are responsible for using the scraped data in line with eBay's terms and the laws that apply to you — in particular, do not collect or process personal data without a lawful basis.