Skip to content

How to Scrape eBay: Listings, Prices, Conditions and Sold Counts

Scrape eBay listings by keyword or URL and get title, price, condition, seller, sold count, shipping and identifiers as rows, with eBay's bot check handled for you. A real run, its cost, and code for curl, Python and Node.js.

Published
Reading time
8 min read
Pixel-art robot with an orange >_ on its terminal head pulls a listing card with a photo and price off an auction board topped with the eBay logo and drops it into a crate
In this article
  1. What data you can get from eBay
  2. How to scrape eBay listings without code
  3. How to scrape eBay with the API
  4. A real run: mechanical keyboards from $50 to $150
  5. What it costs
  6. What to watch out for when scraping eBay
  7. Is it legal to scrape eBay?
  8. Why Scrape.ly for eBay scraping
  9. FAQ
  10. Can you scrape eBay without getting blocked?
  11. Can you scrape eBay sold listings?
  12. How do I scrape eBay listings with Python?
  13. Can I scrape a specific eBay category?
  14. How much does it cost to scrape eBay?

Here is how to scrape eBay in one sentence: send a keyword or a search URL to a scraper that reads eBay's public search results and saves each active listing with its title, price, condition, seller, sold count, item location and shipping. The fastest way to do it is the eBay Scraper on Scrape.ly, which clears eBay's bot check for you and returns clean rows at $4 per 1,000 listings, with no eBay account, API key or proxy of your own.

This guide covers the no-code steps, the API (curl, Python, Node.js and AI agents over MCP), the cost and the pitfalls. Everything below comes from a real run on 22 October 2026: mechanical keyboards between $50 and $150, with the exact input, output, log and charge.

What data you can get from eBay

The eBay Scraper writes one row per active listing. These are the fields you'll use most:

Field What it holds
title, subTitle Listing title and subtitle
price, priceWithCurrency Current price as a number, and as eBay shows it ("US $74.00 or Best Offer")
wasPrice, wasPriceWithCurrency The previous price, when eBay shows one
condition eBay's real condition label: Brand New, Open Box, Certified - Refurbished …
sold, available, availableText How many have sold, quantity left, and eBay's text for both
seller The seller's eBay name
shippingCost, shippingCostWithCurrency, shipsTo, excludesShipping Shipping price and destinations
itemLocation Where the item is located, as eBay shows it
brand, type, upc, ean, mpn Product attributes and identifiers, when listed
categories eBay's category path
image, images Main photo and all photos
url, itemNumber Listing link and eBay item number

Fields appear when eBay shows them for that listing, so upc or wasPrice can be empty. The Actor collects active listings only: sold and completed search URLs are skipped, but every row carries the item's sold count.

How to scrape eBay listings without code

  1. Open the Actor's page in the Scrape.ly Store.
  2. Pick a ready-made input. We used the preset Mechanical keyboards 50-150 USD, 10 listings. "Try this input" opens it in the console.
  3. Change the keyword and price bounds to yours. This is the exact input of our run:
json
{
  "keyword": "mechanical keyboard",
  "minPrice": 50,
  "maxPrice": 150,
  "maxItems": 10
}
  1. Click Start. Expect 20 to 30 seconds for 10 listings: most of that is eBay's bot check, which the Actor solves itself.
  2. Export the listings as JSON, CSV or Excel.

The fields that matter most:

  • keyword: what you'd type into eBay's search box. Active listings only.
  • startUrls: search, category or listing URLs, such as the preset Cables from a search URL, 8 listings. Category pages work as search URLs (/sch/... with a category ID). The keyword runs first, then each URL.
  • maxItems: listings to save for the whole run (default 10), counted across the keyword and all URLs.
  • minPrice, maxPrice: price bounds in the site's currency. For a keyword, eBay applies them; for pasted URLs, the Actor filters after reading the page.

How to scrape eBay with the API

Create an API token under Settings → API & Integrations and export it as SCRAPELY_TOKEN.

Our run took 35 seconds because of the bot check, which is close to the 45-second limit of the synchronous endpoint. Use the asynchronous flow: start the run, wait, then read the items.

shell
# 1. start the run; the response's data.id is the run ID
curl -X POST "https://api.scrape.ly/v2/actors/shelfbright~ebay-scraper/runs" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keyword": "mechanical keyboard", "minPrice": 50, "maxPrice": 150, "maxItems": 10}'
# 2. wait (up to 60 s per call; repeat until status is SUCCEEDED)
curl "https://api.scrape.ly/v2/actor-runs/RUN_ID?waitForFinish=60" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"
# 3. read the listings (CSV here)
curl "https://api.scrape.ly/v2/actor-runs/RUN_ID/dataset/items?format=csv" \
  -H "Authorization: Bearer $SCRAPELY_TOKEN"

Python (pip install scrapely-client-python). call() waits however long the run takes; this example ranks listings by price including shipping:

python
import os
from scrapely_client import ScrapelyClient

client = ScrapelyClient(os.environ["SCRAPELY_TOKEN"], api_url="https://api.scrape.ly")

run = client.actor("shelfbright/ebay-scraper").call(
    run_input={"keyword": "mechanical keyboard", "minPrice": 50, "maxPrice": 150, "maxItems": 10}
)
print(run.status)  # SUCCEEDED, FAILED, ABORTED or TIMED-OUT
listings = list(client.dataset(run.default_dataset_id).iterate_items())
for item in sorted(listings, key=lambda i: i["price"] + (i.get("shippingCost") or 0)):
    total = item["price"] + (item.get("shippingCost") or 0)
    print(f'{total:7.2f}  {item["condition"]:24}  sold {item.get("sold") or 0:>3}  {item["title"][:50]}')

Node.js (npm install scrapely-client):

javascript
import { ScrapelyClient } from 'scrapely-client';

const client = new ScrapelyClient({ token: process.env.SCRAPELY_TOKEN, baseUrl: 'https://api.scrape.ly' });

const run = await client.actor('shelfbright/ebay-scraper').call({
  keyword: 'mechanical keyboard',
  minPrice: 50,
  maxPrice: 150,
  maxItems: 10,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.map((i) => [i.priceWithCurrency, i.condition, i.sold, i.url]));

For AI agents, add the Scrape.ly MCP server. In Cursor, put this in ~/.cursor/mcp.json:

json
{
  "mcpServers": {
    "scrapely": {
      "url": "https://api.scrape.ly/mcp",
      "headers": { "Authorization": "Bearer YOUR_TOKEN" }
    }
  }
}

In Claude Code, run claude mcp add --transport http scrapely https://api.scrape.ly/mcp and sign in with /mcp. Then ask: "Use scrapely to run shelfbright/ebay-scraper for 'mechanical keyboard' between $50 and $150, 10 listings, and give me a table of price, condition and sold count." Because the run takes more than 45 seconds at larger sizes, the agent polls get-actor-run and then reads the rows. The eBay API page shows the same Actor as an API product, and the Actors API docs list every endpoint.

A real run: mechanical keyboards from $50 to $150

We ran the "Mechanical keyboards 50-150 USD, 10 listings" preset on 22 October 2026. It returned 10 listings in 35 seconds and was charged $0.0466. The first five rows:

Listing Price Condition Seller Sold Shipping
Redragon K550 RGB Gaming Keyboard, 104 Keys + 12 Macro G Keys Wired US $74.00 or Best Offer Open Box [seller 1] 64 Free
Logitech MX Mechanical Mini Wireless TKL Keyboard Tactile Quiet Switches US $109.99 Certified - Refurbished [seller 2] 19 Free
Logitech K845ch Mechanical Illuminated Keyboard Cherry MX Blue New In Box US $75.00 or Best Offer Brand New [seller 3] 2 US $10.00
Logitech G PRO X TKL Wireless Gaming Keyboard – Tactile Switches US $129.99 Certified - Refurbished [seller 2] 25 Free
Corsair K65 PLUS Wireless 75% RGB Hot-Swap Gaming Keyboard Certified Refurb US $55.45 Certified - Refurbished [seller 4] 45 Free

eBay sellers can be private individuals, so we show seller names as [seller 1] to [seller 4]; [seller 2] listed two of the five keyboards. What the full ten show:

  • The price filter held. All 10 prices sat between $55.45 and $129.99.
  • Condition matters as much as price. Five of ten were "Certified - Refurbished", two "Open Box", two "Brand New" and one "Excellent - Refurbished". Compare like with like before you call something cheap.
  • Shipping changes the ranking. Eight of ten shipped free; the other two added $10.00 and $8.29.
  • Demand is visible. The listings had sold 369 units between them, from 2 to 75 each. Four were open to a Best Offer.
  • Identifiers come along. Nine of ten had a UPC and seven an MPN, which is what you need to match the same product across sellers or retailers.

The log, without the platform's start-up lines:

Text
2026-10-22T18:26:22.284Z [Scrapely] Container started (setup 1.0 s)
2026-10-22T18:26:23.495Z [scrapely.actor] INFO  Anti-bot solver source: platform.
2026-10-22T18:26:45.959Z [scrapely.actor] INFO  Reading 10 listings (10 found so far).
2026-10-22T18:26:55.779Z [scrapely.actor] INFO  Saved 10 listings. Challenge solves: 4
2026-10-22T18:26:56.408Z [Scrapely] Container state: status=exited exitCode=0 oomKilled=false

The 22 seconds between start and "Reading 10 listings" is eBay's bot check. The Actor solved four challenges with the platform's own solver, on the default datacenter proxy. You don't configure anything for it.

What it costs

The Actor charges one event, $0.004 per listing saved, which is $4.00 per 1,000 listings. Platform usage (compute and proxy) is billed on top.

For our run: 10 listings × $0.004 = $0.04 in listing fees. The run was charged $0.0466 in total, because it also used $0.0047 of compute (the bot check is most of the run time), $0.0019 of datacenter proxy traffic and $0.00005 of dataset writes. A 1,000-listing job costs $4.00 in listing fees; a keyword or URL that matches nothing saves no rows and pays no listing fee.

What to watch out for when scraping eBay

  • Active listings only. Sold and completed searches are skipped. Use sold on each active row to see demand, and run the same search on a schedule to watch prices move.
  • Use /sch/ URLs. /b/ browse URLs can stay on eBay's challenge page. A search or category search URL (/sch/...) works.
  • Bot checks add time, not work. A 10-listing run typically takes 20 to 30 seconds. If eBay keeps its check up, the Actor retries once from a new exit and then fails with a clear message instead of handing you an empty dataset.
  • Layouts change. Hand-written scrapers break on eBay's markup: ScrapingBee's guide (updated 25 September 2026) parses li.s-card cards, while many older guides target li.s-item. With the Actor, you read price and condition fields, not CSS classes.
  • The limit is per run. maxItems counts across the keyword and all URLs, and a search stops when eBay shows no more result pages.
  • Seller names. Many sellers are individuals. Store seller names only if you need them, and treat them as personal data.

The Actor reads public listing pages that anyone can open without an account, and it never logs in or buys anything. Listing prices, titles and conditions are factual product data. eBay's User Agreement still sets rules for how its site may be accessed and used, so read the current version before you build a product on eBay data, and keep your request volume reasonable.

Privacy law applies to the people behind listings. A private seller's name and location are personal data under the GDPR and the CCPA. Collect only the fields you need, keep them secure, and have a lawful basis for processing them. This is not legal advice: if eBay data drives a commercial product, ask a lawyer about your case.

Why Scrape.ly for eBay scraping

  • The bot check is solved for you. Top tutorials add premium proxies, mobile user agents and retry logic to get past eBay's defenses. The Actor ships with the solver and the proxy, as the log above shows.
  • Rows instead of selectors. Bright Data's Python tutorial walks through nine steps for one product page. Here a keyword returns structured rows with condition, sold count, shipping and UPC.
  • Predictable cost. $4.00 per 1,000 listings plus small usage, and a maximum charge per run if you want a hard cap.
  • Built for monitoring. Schedule the same search daily, send rows to Google Sheets or a webhook, and compare prices across Amazon, Walmart and Google Shopping, as in our price scraping guide.

FAQ

Can you scrape eBay without getting blocked?

Yes. The Actor clears eBay's bot check itself and uses a built-in datacenter proxy, so you don't need your own proxies or solver. In our run it solved four challenges and saved all ten listings.

Can you scrape eBay sold listings?

The Actor returns active listings; sold and completed search URLs are skipped. Each active row includes how many units have sold (sold), which shows demand without leaving the live market.

How do I scrape eBay listings with Python?

Install scrapely-client-python, call shelfbright/ebay-scraper with a keyword or URLs, and iterate over the dataset, as in the example above. The client waits for the run, including the bot check.

Can I scrape a specific eBay category?

Yes. Paste the category's search URL (/sch/... with the category ID) into startUrls. Category pages are read like search URLs, and price bounds are applied after the page is read.

How much does it cost to scrape eBay?

$0.004 per listing, so $4.00 per 1,000, plus a little compute and proxy usage. Our 10-listing run was charged $0.0466. The Free plan's $5 of monthly credit covers over 1,000 listings in listing fees.

  • ebay
  • ecommerce
  • price monitoring
  • reselling
  • python
  • api

About the author

Actor publisher on the Scrape.ly Store

Prices, stock and seller data from shops and marketplaces, from Amazon and AliExpress to Vinted and Leboncoin. For price trackers, catalogue teams and resellers. A Scrapely studio.

//Keep reading\\

The internet is full of data.
Start owning yours.

Scrape.ly gives you the infrastructure, the tooling, and the team to extract, process, and operationalize web data at any scale. Setup takes minutes. The advantage lasts forever.

No credit card. No setup calls.