← All posts

How to Scrape eBay: Use the Browse and Finding APIs First

Quick answer: Use eBay's official APIs before scraping. The Browse API returns live listing data (title, price, condition, seller, images) as structured JSON, and eBay's Buy and Marketplace Insights APIs cover search and sold-item analytics. eBay's User Agreement prohibits unauthorized scraping, and the APIs give you cleaner data. Reserve public-page fetching for narrow gaps the APIs do not cover.

If you want eBay data for price research, inventory monitoring, or a shopping tool, eBay has one of the more mature developer programs of any marketplace. That is the front door. Let me walk through it.

Start With the eBay Developer Program

eBay exposes a family of REST APIs through its developer program. You create a developer account, register an app to get credentials, and use OAuth to obtain tokens. The APIs most relevant to "scraping" intent are:

  • Browse API: search and retrieve live listings, including item details, price, condition, seller info, shipping, and images. This is usually the one you want.
  • Finding API: keyword and category search across active listings (the older search interface, still widely used).
  • Marketplace Insights API: access to sold and completed item data for pricing analytics (access is gated and application-based).

For read access to public catalog and listing data, eBay uses an application token via OAuth client credentials. For account-specific actions, it uses user tokens. Request only what you need.

What the Browse API Returns

The Browse API is the workhorse. A single search returns structured items you would otherwise try to parse out of HTML:

Field Example
itemId a stable per-item identifier
title Vintage film camera, tested
price { value: 89.99, currency: USD }
condition Used
seller { username, feedbackPercentage }
itemWebUrl canonical listing URL

Because it is JSON straight from eBay, you skip the whole fragile-parser problem. When eBay redesigns a page, your integration does not care.

Approach Data Auth Standing
Scraping eBay HTML Fragile, parsed None (evades) Prohibited by User Agreement
Browse / Finding API Live listings, search OAuth token Permitted
Marketplace Insights Sold-item analytics OAuth, gated Permitted, application-based

When Fetching a Public Page Fits

Sometimes you need one detail from a single public listing that the API does not return in the shape you want, or you are enriching a small set of URLs a user pasted. Fetching a public page you are permitted to read, at a respectful rate, is a fair fallback.

What it should not become: a substitute for the API to bulk-collect listings, a way to reach account-only data, or a tool to bypass eBay's bot protection. If content sits behind login or a challenge, stop there. For the reasoning, see whether web scraping is legal and ethical web scraping best practices.

For permitted public-page enrichment, link.sc fetches a URL and returns clean markdown or structured JSON, so you do not run a browser fleet for occasional pages.

A Code Sketch: Browse API First

Primary path: search live listings via the Browse API.

import requests

# eBay Browse API uses an OAuth application token (Authorization: Bearer).
EBAY_TOKEN = "your-oauth-application-token"

def search_ebay(query, limit=50):
    url = "https://api.ebay.com/buy/browse/v1/item_summary/search"
    r = requests.get(
        url,
        headers={
            "Authorization": f"Bearer {EBAY_TOKEN}",
            "Content-Type": "application/json",
        },
        params={"q": query, "limit": limit},
        timeout=30,
    )
    r.raise_for_status()
    items = r.json().get("itemSummaries", [])
    return [
        {
            "title": it["title"],
            "price": it["price"]["value"],
            "currency": it["price"]["currency"],
            "condition": it.get("condition"),
            "url": it["itemWebUrl"],
        }
        for it in items
    ]

One header note. eBay's APIs use Authorization: Bearer with an OAuth token, which is standard and fine. link.sc uses x-api-key with an lsc_... key instead. Two different services, two different auth schemes.

And the permitted public-page fallback:

import requests

def fetch_public_listing(url):
    r = requests.post(
        "https://api.link.sc/v1/fetch",
        headers={"x-api-key": "lsc_your_key_here"},
        json={"url": url, "format": "markdown"},
        timeout=60,
    )
    r.raise_for_status()
    return r.json()["content"]

Price Research and Monitoring

For competitive pricing, the Browse API plus a polite polling schedule handles active listings, and the Marketplace Insights API (once approved) covers sold-item history for real price signals. Snapshot the data yourself over time to build trends. The general architecture (change detection, snapshotting, normalization) is in the ecommerce price scraping guide, and it sits cleanly on top of eBay's official APIs.

ToS and Ethics Note

Not legal advice. But the summary is consistent: eBay's User Agreement prohibits unauthorized scraping, eBay ships a full API program so you do not have to, and the API data is cleaner and more stable. Use the APIs, request only the scopes and tokens you need, respect rate limits, and treat seller data with care. When something is gated (like sold-item analytics), apply for access rather than scraping around the gate.

The short version: Browse API first, respect the rate limits, and reserve fetching for the occasional permitted public page.


Want to combine official marketplace APIs with clean fetches from the public web? Start free with link.sc.