Guides / Scrape eBay
How to Scrape eBay in 2026
eBay uses anti-bot detection, JavaScript rendering, various listing formats (auction, Buy It Now, best offer), and rate limiting. Parsing eBay is especially tricky because search results mix different listing types with different data structures. With Browser7, you get fully rendered search results and listing data in a single API call.
What makes eBay hard to scrape
Anti-bot detection
eBay uses browser fingerprinting, behavioral analysis, and IP reputation scoring to detect automated traffic. Datacenter IPs are blocked, and suspicious request patterns trigger CAPTCHA challenges or temporary bans.
JavaScript rendering
eBay renders search results, product details, and seller information using client-side JavaScript. A simple HTTP request returns incomplete page content. You need a real browser to get pricing, condition, shipping, and seller data.
Various listing formats
eBay search results mix auction listings, Buy It Now listings, and best offer listings. Each format has slightly different HTML structures and data fields (current bid vs fixed price, time remaining vs quantity available). Parsing logic needs to handle all formats.
Rate limiting
eBay enforces rate limits and will block IPs that make too many requests in a short period. High-volume scraping without proper proxy rotation results in CAPTCHA challenges or temporary IP bans.
Scrape eBay search results
Browser7 handles proxy rotation, browser fingerprinting, CAPTCHA solving, and JavaScript rendering automatically. This example scrapes iPhone 15 search results and returns the fully rendered HTML with all listing cards.
from browser7 import Browser7
client = Browser7(
api_key="b7_your_api_key",
base_url="https://ca-api.browser7.com/v1"
)
result = client.render(
"https://www.ebay.com/sch/i.html?_nkw=iphone+15",
country_code="US",
)
print(result.html)That is the complete code. No proxy configuration, no browser setup, no CAPTCHA handling logic. The response contains the fully rendered HTML of the eBay search results page, including all listing cards with titles, prices, conditions, and shipping information.
Data you can extract
The rendered HTML contains all the data eBay shows to a real visitor. Common data points to extract:
Listing details
- Listing title and item specifics
- Item condition (new, used, refurbished)
- Listing type (auction, Buy It Now, best offer)
- Item images and gallery URLs
- Item location and shipping origin
Pricing
- Current price or bid amount
- Buy It Now price
- Shipping cost or free shipping
- Number of bids (for auctions)
- Time remaining (for auctions)
Seller info
- Seller username
- Seller feedback score
- Seller feedback percentage
- Top Rated Seller badge
- Return policy
Search metadata
- Total results count
- Search result positions
- Sponsored vs organic results
- Available filters and categories
- Related search suggestions
Complete example: render and parse listing data
Here is a complete example that renders eBay search results and extracts structured data from the HTML. Listing cards use the li.s-card selector. The code skips "Shop on eBay" sponsored cards that appear at the top of results. Prices use the span.su-styled-text.primary.bold class, and shipping info is in secondary styled-text spans.
from browser7 import Browser7
from bs4 import BeautifulSoup
import json
client = Browser7(
api_key="b7_your_api_key",
base_url="https://ca-api.browser7.com/v1"
)
result = client.render(
"https://www.ebay.com/sch/i.html?_nkw=iphone+15",
country_code="US",
)
soup = BeautifulSoup(result.html, "html.parser")
listings = []
for card in soup.select("li.s-card"):
# Skip "Shop on eBay" sponsored cards
title_el = card.select_one("div.s-card__title span")
if not title_el:
continue
title = title_el.get_text(strip=True)
if title.lower().startswith("shop on ebay"):
continue
listing = {
"title": title,
"price": None,
"condition": None,
"shipping": None,
}
# Price from primary bold styled text
price_el = card.select_one("span.su-styled-text.primary.bold")
if price_el:
listing["price"] = price_el.get_text(strip=True)
# Condition from subtitle
condition_el = card.select_one("div.s-card__subtitle span")
if condition_el:
listing["condition"] = condition_el.get_text(strip=True)
# Shipping from secondary styled text spans
shipping_spans = card.select("span.su-styled-text.secondary")
for span in shipping_spans:
text = span.get_text(strip=True)
if "shipping" in text.lower() or "free" in text.lower():
listing["shipping"] = text
break
listings.append(listing)
print(json.dumps(listings[:5], indent=2))CSS selectors may change if eBay updates their page structure. Inspect the current page if any fields return null.
Sample output:
[
{
"title": "Apple iPhone 15 128GB Unlocked - Black",
"price": "$629.99",
"condition": "New",
"shipping": "Free shipping"
},
{
"title": "Apple iPhone 15 Pro Max 256GB - Natural Titanium (Unlocked)",
"price": "$849.00",
"condition": "Pre-Owned",
"shipping": "Free shipping"
},
...
]Scrape page 2 and beyond
eBay search results use the &_pgn= parameter for pagination. Page 2 is &_pgn=2, page 3 is &_pgn=3, and so on.
from browser7 import Browser7
from bs4 import BeautifulSoup
client = Browser7(
api_key="b7_your_api_key",
base_url="https://ca-api.browser7.com/v1"
)
# Page 2: add &_pgn=2
result = client.render(
"https://www.ebay.com/sch/i.html?_nkw=iphone+15&_pgn=2",
country_code="US",
)
soup = BeautifulSoup(result.html, "html.parser")
for card in soup.select("li.s-card"):
title_el = card.select_one("div.s-card__title span")
price_el = card.select_one("span.su-styled-text.primary.bold")
if title_el:
title = title_el.get_text(strip=True)
if not title.lower().startswith("shop on ebay"):
price = price_el.get_text(strip=True) if price_el else "N/A"
print(f"{title[:80]} - {price}")Take a screenshot of search results
Capture eBay search results as an image for price monitoring dashboards, market research reports, or tracking listing trends and pricing over time.
import base64
from browser7 import Browser7
client = Browser7(
api_key="b7_your_api_key",
base_url="https://ca-api.browser7.com/v1"
)
result = client.render(
"https://www.ebay.com/sch/i.html?_nkw=iphone+15",
country_code="US",
block_images=False,
include_screenshot=True,
screenshot_full_page=True,
screenshot_format="png"
)
# Save the screenshot
with open("ebay-search.png", "wb") as f:
f.write(base64.b64decode(result.screenshot))
print("Screenshot saved")What this costs
Every eBay page render costs $0.01 - the same as any other website. Residential proxies, JavaScript rendering, CAPTCHA solving, and screenshots are all included. There are no per-domain surcharges, no credit multipliers, and no bandwidth fees.
10,000 eBay search pages costs $100. You know this before you start, not after.