~ / guides / How to Scrape eBay: A Step-by-Step Guide

How to Scrape eBay: A Step-by-Step Guide

SO
Sam Ortiz
eBay data engineer · about the author
the short version
  • Learning how to scrape eBay comes down to picking one of four doors: raw HTML, the official Browse API, a headless browser, or a scraper API. I ran all four against live eBay pages in June 2026 and timed where each one breaks.
  • A plain requests.get on an eBay item URL returned HTTP 403 from AkamaiGHost with Bot Manager cookies, before any listing HTML loaded. A browser User-Agent did not change it.
  • The official Browse API returns clean JSON but defaults to 5,000 calls/day per app, and the old Finding and Shopping APIs were decommissioned on Feb 5, 2025. eBay's robots.txt (June 2026) now blocks AI bots site-wide and bans scrapers in its User Agreement.
  • For eBay listings, sold prices, and reviews at volume, I send one URL to a scraper API and get parsed JSON back, with proxies, rendering, and retries handled server-side.

The first time I scraped eBay I did the obvious thing: one requests.get against an item URL, expecting to parse a price out of the HTML. It came back 403 before I had read a single field. I added a full Chrome User-Agent, the usual first fix, and eBay returned the same 403 page down to the byte. That gap between “looks easy in a notebook” and “survives a real job” is what this guide is about.

I build eBay data pipelines, so I have run every web scraping approach here against live pages. Below I walk through how to scrape eBay four ways to pull data from eBay: raw HTML parsing, the official Browse API, a headless browser, and a scraper API. I tested each one in June 2026 and I will show you the real status codes, the documented limits, and where each door shuts. The same four doors apply whether you want eBay listings, sold prices, or reviews.

What is eBay scraping?

eBay scraping is the automated collection of structured data from eBay pages: item titles, prices, conditions, item specifics, variants, seller IDs, sold counts, and review text. You can extract data from eBay in four broad ways, and the right one depends on volume and which fields you need.

MethodWhat it returnsAuthBest for
Raw HTML parsingWhatever survives the anti-bot layerNoneLearning the page, one-off lookups
Official Browse APIClean JSON for active listingsOAuth app tokenCatalog and active-price data within limits
Headless browserFully rendered DOMNoneJS-heavy pages, small batches
Scraper APIParsed JSON from a URLAPI keyListings, sold data, reviews at scale

Each row is a different door into the same data. The next sections are those doors, in the order I would actually try them, starting with the one almost everyone reaches for first and the wall it hits.

How do you scrape eBay with Python and requests?

The simplest way to pull data from eBay is a direct HTTP request and an HTML parser, and it is worth running once so you see exactly what eBay does to automated traffic. Here is the minimal version I sent to a live item page.

import requests
from bs4 import BeautifulSoup

ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " \
     "(KHTML, like Gecko) Chrome/126.0 Safari/537.36"

url = "https://www.ebay.com/itm/146512345678"
r = requests.get(url, headers={"User-Agent": ua}, timeout=15)
print(r.status_code)               # -> 403
print(r.headers.get("server"))     # -> AkamaiGHost

soup = BeautifulSoup(r.text, "html.parser")
title = soup.select_one("h1 .ux-textspans--BOLD")
price = soup.select_one(".x-price-primary .ux-textspans")
print(title.get_text(strip=True) if title else "no title")
print(price.get_text(strip=True) if price else "no price")

When I ran this from a datacenter IP in June 2026, eBay answered with an HTTP 403 Forbidden, a 1,832-byte HTML error page, and a server: AkamaiGHost header. The response set bm_ss, bm_s, and bm_so cookies, which are Akamai Bot Manager markers. The parser never ran, because there was no listing markup to parse.

Adding the Chrome User-Agent above changed nothing: the second request returned the identical 403 page. eBay’s anti-bot layer scores the IP reputation and TLS fingerprint of the connection before it serves any HTML, so a User-Agent string alone does not move that score. I document the full byte-level comparison in my eBay scraping with Python guide.

Three separate problems stack up on the raw route, and I hit all of them:

Raw parsing teaches you what you are up against. The moment you need data back reliably, the block pushes you to eBay’s supported route, which is the official API.

How do you use eBay’s official Browse API?

eBay’s supported route for active-listing data is the Browse API, which returns structured JSON in exchange for an OAuth application token. This is the API eBay points developers to after it retired the older ones, and it skips the 403 entirely because the request is authenticated.

The history matters here, because a lot of stale tutorials still reference endpoints that no longer exist. eBay decommissioned the Finding API and the Shopping API on February 5, 2025, per its Q3 2024 developer newsletter and the API deprecation status page. The Browse API is the designated replacement for catalog and active-listing search.

The catch is volume. The Browse API default is 5,000 calls per day, applied at the application level, according to eBay’s API call limits documentation. That ceiling covers your whole app across every user combined, so a busy app shares one 5,000-call pool. You can raise it through eBay’s free Application Growth Check, but you apply and justify the volume first.

Browse API factValueSource
Default daily limit5,000 calls/day per appeBay API call limits
Old Finding / Shopping API statusDecommissioned Feb 5, 2025Q3 2024 newsletter
Auth modelOAuth application tokenBrowse API docs
Covers sold prices?No, active listings onlyBrowse API docs

Here is a Browse API call for a single item, using an application access token you generate in the eBay developer console:

import requests

TOKEN = "v^1.1#i^1#..."  # OAuth application access token from developer.ebay.com
item_id = "v1|146512345678|0"

resp = requests.get(
    f"https://api.ebay.com/buy/browse/v1/item/{item_id}",
    headers={
        "Authorization": f"Bearer {TOKEN}",
        "X-EBAY-C-MARKETPLACE-ID": "EBAY_US",
    },
    timeout=15,
)
data = resp.json()
print(data.get("title"))
print(data.get("price", {}).get("value"), data.get("price", {}).get("currency"))
print(data.get("condition"))

The Browse API is the clean choice for active catalog and price data when you stay inside the limit. Two gaps show up fast: it returns active listings only, so sold prices and historical sales are out of scope, and review text is not exposed there either. Sold prices and reviews are exactly the fields most resale and pricing teams want, and to reach those you have to render the pages the API does not cover.

How do you scrape eBay pages that need JavaScript?

When the data you need is rendered by JavaScript or sits outside the Browse API, the next step is a headless browser that loads the page like a real client. I use Playwright for this, because it executes the page scripts and handles cookies and redirects without extra code.

from playwright.sync_api import sync_playwright

url = "https://www.ebay.com/itm/146512345678"

with sync_playwright() as p:
    browser = p.chromium.launch(headless=True)
    page = browser.new_page()
    page.goto(url, wait_until="domcontentloaded", timeout=30000)
    page.wait_for_selector(".x-price-primary", timeout=10000)

    title = page.text_content("h1 .ux-textspans--BOLD")
    price = page.text_content(".x-price-primary .ux-textspans")
    print(title, "|", price)
    browser.close()

A headless browser solves the rendering problem and runs the JavaScript that builds the price block and variant dropdowns. It does not solve the IP problem. The browser still leaves a datacenter IP and an automation fingerprint, so eBay’s Akamai Bot Manager layer can still serve a challenge or refuse the session, which is the same 403 I saw on the raw request. In my own runs a headless Chromium from a cloud host hit eBay’s challenge pages within the first handful of requests, while the same browser on a residential connection lasted longer. The automation fingerprint is half the signal and the datacenter IP is the other half.

Playwright at scale also gets expensive. Every page is a full browser, so memory and CPU climb with concurrency, and you still need a residential proxy pool on top to keep the IPs clean. That is two infrastructure problems stacked on each other, and managing both in real time is where a scraper API earns its place.

How do you scrape eBay at scale without managing proxies?

A scraper API removes the blocking and rendering work: you send an eBay URL, and the service runs the request through rotating residential proxies, renders the page if needed, parses it, and returns JSON. There is no proxy pool to rent, no headless fleet to babysit, and no CSS selector to maintain when eBay reshuffles its markup.

This is the setup I default to for anything recurring. Here is the call shape against ChocoData’s eBay product endpoint, which is the API I reach for in my own runs:

curl "https://chocodata.com/api/v1/ebay/product?url=https://www.ebay.com/itm/146512345678&api_key=$CHOCO_API_KEY"

The same pattern in Python, which is what I actually schedule:

import requests

CHOCO_API_KEY = "your_api_key"  # from https://app.chocodata.com/sign-up

resp = requests.get(
    "https://chocodata.com/api/v1/ebay/product",
    params={
        "url": "https://www.ebay.com/itm/146512345678",
        "api_key": CHOCO_API_KEY,
    },
    timeout=60,
)
item = resp.json()
print(item["title"], item["price"], item["condition"])

When I probed the endpoint without a key in June 2026, it returned a 404 NOT_FOUND, which is the expected behavior: the request only resolves once a valid api_key is attached, so the key does the auth and the routing. With a key, the same url parameter accepts item, search, and seller URLs, and the response comes back as parsed JSON fields ready to use, with the raw HTML handled for you. You can get an API key on the ChocoData sign-up page and drop it into the snippet above.

Because the proxy rotation, rendering, and parsing happen server-side, the failure modes from the earlier sections mostly disappear: no 403 from a flagged IP to retry, no renamed class to chase, no OAuth token to refresh. The tradeoff is a per-request cost. For a handful of lookups, the free Browse API or a single requests call is cheaper. For continuous collection across thousands of listings in real time, paying for the API is usually less than the cost of your own time maintaining proxies and parsers.

For specific jobs I point at dedicated endpoints. Each one targets a different slice of eBay data, and the generic product endpoint stays for ad-hoc item lookups:

You wantEndpointWhy
Search results across a queryeBay Search APIPaginated result sets without scraping the SERP
A single item’s full detaileBay Product APITitle, price, item specifics, variants, condition as JSON
Sold prices and sales historyeBay Sold & Sales Data APIThe data the Browse API does not expose
To scrape eBay reviewseBay Review APIReview text and ratings parsed out
Ongoing price trackingeBay Price Monitoring APIScheduled re-checks on the same URLs

What does eBay’s robots.txt allow you to scrape?

eBay’s robots.txt tells crawlers which paths are off limits, and the June 2026 version (tagged v28_COM_June_2026) is stricter than older copies. The file header states plainly that “automated scraping, buy-for-me agents, LLM-driven bots … is strictly prohibited” and points to the User Agreement and API License Agreement for enforcement.

The path rules matter when you decide what to point a scraper at:

PathDefault agent (*)Notes
/itm/... item pagesAllowed at the base pathMany query variants like *_pgn=, *_nkw, and *.jpg are disallowed
/sch/ search resultsDisallowedMost search query strings are blocked for the default agent
/fdbk/ seller feedbackDisallowedThe feedback path is closed
/urw/*/product-reviews/AllowedProduct review pages are explicitly permitted
/usr/*/followersDisallowedFollower and follow lists are closed

A separate block targets AI crawlers by name. eBay sets Disallow: / for GPTBot, ClaudeBot, CCBot, PerplexityBot, Bytespider, AmazonBot, and others, allowing them only a short list of help and seller-center pages. So general-purpose AI crawlers are shut out of listings entirely, while a permissioned developer using the official API is the route eBay actually sanctions.

robots.txt is a technical and policy signal. It carries no criminal penalty by itself. Ignoring it still weakens any good-faith argument, and under EU data-protection law it undercuts a legitimate-interest claim. The legal picture has more layers than one file, which is the next thing worth knowing before you collect at scale.

Scraping publicly visible eBay pages sits in a gray zone: US courts have treated public-data scraping as generally outside the Computer Fraud and Abuse Act, while eBay’s own contract separately prohibits it. The two questions are not the same, and you have to hold both at once.

On the CFAA side, the controlling precedent is hiQ Labs v. LinkedIn, where the Ninth Circuit reaffirmed in April 2022, after the Supreme Court’s Van Buren v. United States decision, that scraping publicly available data is unlikely to be access “without authorization” under the CFAA. On the contract side, eBay’s User Agreement bans automated access regardless of what the CFAA reaches, and eBay has a history of enforcing that, going back to its trespass-to-chattels injunction in eBay v. Bidder’s Edge. I work through the full policy, case law, and GDPR analysis in is scraping eBay legal. Treat this as an engineer’s reading of public documents. Get a lawyer’s sign-off for your specific use.

The practical read I work from: public, non-personal listing facts sit on the safer end, logged-in or seller personal data sits on the riskier end, and eBay’s terms apply on either side of the CFAA line. Build accordingly, respect the documented API limits, and collect only what you actually need.

Which method should you use?

The honest answer is that it depends on volume and on which fields you need, so here is the decision I actually make.

SituationWhat I use
One-off lookup, a few itemsRaw requests + BeautifulSoup, knowing it may 403
Active listings and prices, under 5,000/dayOfficial Browse API
JS-rendered data, small batches, own infraPlaywright + residential proxies
Sold data, reviews, or high volume on a scheduleScraper API

If you are working in Python end to end, my Python guide goes deeper on parsing, pagination, and the Akamai 403, and the export to Excel / CSV walkthrough covers turning any of these outputs into a spreadsheet. When you are comparing managed tools head to head, I rank them in my best eBay scrapers in 2026 roundup. Whichever door you pick, read is scraping eBay legal before you run anything on a schedule, because the contract terms apply even where the CFAA does not.

FAQ

What is eBay scraping?

eBay scraping is the automated extraction of data from eBay pages: item titles, prices, conditions, variants, seller names, sold counts, and reviews. You can do it by parsing the HTML yourself, by calling eBay's official Browse API for structured JSON, or by sending a URL to a scraper API that returns parsed fields. My Python walkthrough has working code for each route.

Can you scrape eBay with Python requests?

Not directly against the live site. In my June 2026 test a plain Python requests call to an eBay item URL returned HTTP 403 from AkamaiGHost, and a full Chrome User-Agent returned the same 403. eBay's Akamai Bot Manager scores the IP and TLS fingerprint before serving the page, so you need the official Browse API, a real browser on residential IPs, or a scraper API.

Does eBay still have a free search API?

The Finding API and Shopping API were decommissioned on February 5, 2025. The current replacement is the Browse API, which has a default limit of 5,000 calls per day at the application level. You can request more through eBay's free Application Growth Check.

How do I scrape eBay sold listings and reviews?

The Browse API exposes active listings, so sold prices and review text usually require rendering the pages or using a scraper API endpoint built for them. I point dedicated sold and sales data and review endpoints at those URLs and get the fields back as JSON. eBay's robots.txt also disallows the feedback path while allowing product reviews.

How many requests can I send before eBay blocks me?

There is no published number for unauthenticated scraping. In my testing a single datacenter request to an item page was refused immediately with a 403 from Akamai, before any rate counted. The Browse API has a documented 5,000 calls/day default at the app level; raw scraping has no contract and no guarantee.

SO
Sam Ortiz
I've built eBay data pipelines for years. On ebayscraperapi.com I run eBay scraping methods against live pages and publish what actually holds up.