In this Article
Dieser Leitfaden zeigt Ihnen Schritt für Schritt, wie Sie eBay mit Python scrapen: mit einem funktionierenden Scraper für Suchergebnisse, einzelne Angebote, Produktvarianten und Bewertungen sowie der Anti-Bot- und Proxy-Konfiguration, die ihn zuverlässig am Laufen hält. Sie benötigen Python 3, einige Bibliotheken und etwa 30 Minuten für die Basisversion. Am Ende verfügen Sie über wiederverwendbare Funktionen für eBay-Web-Scraping, die sauberes JSON und CSV exportieren.
Ich bin Andrii Byzov, KI-nativer Fractional CMO und Betreiber von E-Commerce-Datenpipelines. eBay ist ein wertvolles, aber gut geschütztes Ziel. Deshalb verbindet diese Anleitung zum Scrapen von eBay den Code mit den Aspekten, die in den meisten Leitfäden fehlen: Paginierung, versteckte Variantendaten und das Vermeiden von Sperren. Kurz gesagt, so scrapen Sie eBay sicher: Senden Sie echte Browser-Header, rotieren Sie Residential Proxys und beachten Sie Ratenlimits. Welche IPs sich eignen, erfahren Sie in unserem Leitfaden zu den besten Proxys für eBay-Scraping.
Wichtige Fakten
- eBay hat zwei Seitentypen: Suchergebnisse und Produktangebote. Da ihre HTML-Strukturen unterschiedlich sind, benötigen Sie zwei Scraper.
- Varianten (Größe, Farbe, Speicher) sind in Inline-JSON verborgen, nicht im sichtbaren HTML. Sie extrahieren sie mit einem regulären Ausdruck und
json.loads(). - Echte Browser-Header sind unverzichtbar: Ohne einen passenden
User-Agentliefert eBay selbst bei einfachen Anfragen häufig 403 oder leere Seiten zurück. - Datacenter IPs werden bei eBay schnell erkannt; rotierende Residential Proxys tragen hohe Volumina und liefern regionsgerechte Preise.
- Angebote unterscheiden sich je nach Land: eBay.com, eBay.co.uk und eBay.de zeigen unterschiedliche Preise und Versandoptionen. Geotargeting ist daher für präzises eBay-Daten-Scraping wichtig.
Schritt 1: Umgebung einrichten
Erstellen Sie eine isolierte Umgebung und installieren Sie die Bibliotheken, die Ihr Setup für eBay-Web-Scraping benötigt. Jede hat eine eigene Aufgabe: requests ruft Seiten ab, beautifulsoup4 + lxml parsen das HTML und httpx verarbeitet asynchrone Anfragen, sobald Sie skalieren.
# Create an isolated project folder and virtual environment
mkdir ebay-scraper && cd ebay-scraper
python3 -m venv env
source env/bin/activate # Windows: env\Scripts\activate
# requests -> send HTTP requests
# beautifulsoup4 -> parse the returned HTML
# lxml -> fast HTML parser backend for BeautifulSoup
# httpx -> async requests for scaling later
pip install requests beautifulsoup4 lxml httpx
Schritt 2: Die Seitenstruktur von eBay verstehen
Bevor Sie Code schreiben, sollten Sie verstehen, dass eBay zwei grundlegend verschiedene Seitentypen hat. Zuverlässiges Scrapen von eBay beginnt damit, die passenden Selektoren für jeden Typ zu kennen. Für jeden Seitentyp werden andere Selektoren benötigt. Öffnen Sie eine beliebige Seite, drücken Sie F12 (oder klicken Sie mit der rechten Maustaste und wählen Sie → Untersuchen) und bewegen Sie den Mauszeiger über ein Element, um seine Klasse zu finden. Auf die folgende Übersicht beziehen Sie sich in Schritt 3 und 4.
Suchergebnisseite
Jedes Ergebnis befindet sich in einem li.s-item-Container, in dem Titel, Preis und Link verschachtelt sind. Der URL-Parameter _pgn steuert die Paginierung; Sie benötigen ihn in Schritt 3.
Produktangebotsseite
Ein einzelnes Angebot enthält den Preis in .x-price-primary, den Titel in h1 span und Artikeldetails in den Zeilen von .ux-labels-values. Beachten Sie, dass sich die lange Beschreibung in einem separaten iframe#desc_ifr befindet, einer Unterseite, die Sie mit einer eigenen Anfrage scrapen.
| Daten | Selektor für Suchergebnisse | Selektor für Angebotsseite |
|---|---|---|
| Container | li.s-item |
— |
| Titel | .s-item__title |
h1 span |
| Preis | .s-item__price |
.x-price-primary |
| Link / Bild | a.s-item__link / .s-item__image img |
— |
| Artikeldetails | — | .ux-labels-values |
| Beschreibung | — | iframe#desc_ifr |
Schritt 3: eBay-Suchergebnisse scrapen
Der erste Scraper erhält eine Suchanfrage und gibt eine Liste von Artikeln mit Titel, Preis, URL und Bild zurück. Damit beginnt die Mehrzahl der eBay-Web-Scraping-Projekte. Ohne den passenden User-Agent-Header liefert eBay selbst bei dieser einfachen Anfrage 403 oder eine leere Seite zurück. Deshalb werden die Header von Anfang an gesetzt. Dasselbe Muster können Sie anpassen, um eBay-Angebote zu beliebigen Suchbegriffen zu scrapen.
import requests
from bs4 import BeautifulSoup
from urllib.parse import quote_plus
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9"}
def scrape_search(query, proxies=None):
"""Return a list of eBay search results for a query."""
url = f"https://www.ebay.com/sch/i.html?_nkw={quote_plus(query)}"
html = requests.get(url, headers=HEADERS, proxies=proxies, timeout=30)
soup = BeautifulSoup(html.text, "lxml")
items = []
for card in soup.select("li.s-item"):
title = card.select_one(".s-item__title")
price = card.select_one(".s-item__price")
link = card.select_one("a.s-item__link")
image = card.select_one(".s-item__image-wrapper img")
if not (title and link):
continue
items.append({
"title": title.get_text(strip=True),
"price": price.get_text(strip=True) if price else None,
"url": link["href"],
"image": image.get("src") if image else None,
})
return items
print(scrape_search("smartphone")[:3])
Paginierung verarbeiten
Eine Ergebnisseite reicht nicht aus. Diese Schleife durchläuft den Parameter _pgn (Seite 2, 3 … N) und endet, wenn die Ergebnisliste leer ist oder Sie ein Seitenlimit erreichen. Genau diesen Teil lassen die meisten Python-Tutorials zu eBay-Scrapern aus.
from urllib.parse import quote_plus
def scrape_all_pages(query, max_pages=10, proxies=None):
"""Page through results via the _pgn parameter until empty or max_pages."""
all_items = []
for page in range(1, max_pages + 1):
url = (f"https://www.ebay.com/sch/i.html?_nkw={quote_plus(query)}"
f"&_pgn={page}")
html = requests.get(url, headers=HEADERS, proxies=proxies, timeout=30)
soup = BeautifulSoup(html.text, "lxml")
cards = soup.select("li.s-item")
if not cards: # no more results -> stop
break
for card in cards:
title = card.select_one(".s-item__title")
link = card.select_one("a.s-item__link")
if title and link:
all_items.append({"title": title.get_text(strip=True),
"url": link["href"]})
return all_items
Schritt 4: eBay-Produktangebotsseiten scrapen
Wenn Sie eBay-Angebote einzeln scrapen, übernimmt parse_product(url) eine einzelne Angebots-URL und gibt strukturierte Felder zurück: Titel, Preis, Zustand, Verkäufer, Versand sowie die Tabelle mit Artikeldetails, deren Zeilen jeweils ein Schlüssel-Wert-Paar enthalten. Das ist der Kern des eBay-Daten-Scrapings auf Produktebene.
def parse_product(url, proxies=None):
"""Scrape a single eBay listing page."""
html = requests.get(url, headers=HEADERS, proxies=proxies, timeout=30)
soup = BeautifulSoup(html.text, "lxml")
def text(sel):
el = soup.select_one(sel)
return el.get_text(strip=True) if el else None
# item specifics live in a label/value table
specifics = {}
for row in soup.select(".ux-labels-values"):
label = row.select_one(".ux-labels-values__labels")
value = row.select_one(".ux-labels-values__values")
if label and value:
specifics[label.get_text(strip=True)] = value.get_text(strip=True)
return {
"title": text("h1 span"),
"price": text(".x-price-primary"),
"condition": text(".x-item-condition-text .ux-textspans"),
"seller": text(".x-sellercard-atf__info__about-seller"),
"shipping": text(".ux-labels-values--shipping .ux-textspans"),
"item_specifics": specifics,
}
Produktvarianten extrahieren (MSKU-Daten)
eBay speichert Produktvarianten wie Farbe, Größe und Speicher nicht im sichtbaren HTML, sondern in einem Inline-JSON-Objekt (MSKU) innerhalb eines <script>-Tags. Sie finden dieses JSON und parsen es mit json.loads(). Sein genauer Schlüssel und Aufbau ändern sich im Laufe der Zeit. Betrachten Sie den folgenden Code daher als Ausgangspunkt und passen Sie ihn an das an, was Sie in den DevTools sehen. Er gibt die Variantenoptionen (Name/Wert) zurück, also den Teil, den die meisten Mitbewerber auslassen.
import re, json
def parse_variants(url, proxies=None):
"""eBay keeps multi-SKU variant options (size, colour, storage) in an inline
JSON blob rather than visible HTML. The exact key and shape change over time,
so treat the pattern below as a starting point and adjust it to the page you
inspect in DevTools. This returns the option name/value pairs, not full
price-per-combination data."""
html = requests.get(url, headers=HEADERS, proxies=proxies, timeout=30).text
# find the inline state object, then load it with a balanced-brace slice
start = html.find('"MSKU"')
if start == -1:
return []
brace = html.find("{", start)
depth, end = 0, brace
for i in range(brace, len(html)):
depth += (html[i] == "{") - (html[i] == "}")
if depth == 0:
end = i + 1
break
try:
data = json.loads(html[brace:end])
except json.JSONDecodeError:
return []
return [{"name": v.get("displayName"), "value": v.get("valueName")}
for v in data.get("menuItemMap", {}).values()]
Schritt 5: eBay-Produktbewertungen scrapen
Beim Scrapen von eBay-Bewertungen sollten Sie beachten, dass es sich um Produkt- bzw. Katalogbewertungen auf einer separaten URL handelt, nicht um Bewertungen auf jeder Angebotsseite. Außerdem hat nicht jedes Angebot solche Bewertungen. Leiten Sie die Bewertungs-URL aus der im Angebot enthaltenen Produkt-/Katalog-ID ab und rufen Sie dann Bewertung, Text, Datum und Autor ab. Betrachten Sie den folgenden Endpunkt als Beispiel und prüfen Sie den aktuellen Pfad in den DevTools.
def scrape_reviews(item_id, proxies=None):
"""Reviews live on a separate URL keyed by the item ID."""
url = f"https://www.ebay.com/urw/{item_id}/product-reviews"
html = requests.get(url, headers=HEADERS, proxies=proxies, timeout=30)
soup = BeautifulSoup(html.text, "lxml")
reviews = []
for r in soup.select(".ebay-review-section"):
rating = r.select_one(".star-rating")
body = r.select_one(".review-item-content")
date = r.select_one(".review-item-date")
author = r.select_one(".review-item-author")
reviews.append({
"rating": rating.get("aria-label") if rating else None,
"text": body.get_text(strip=True) if body else None,
"date": date.get_text(strip=True) if date else None,
"author": author.get_text(strip=True) if author else None,
})
return reviews
Schritt 6: Daten nach JSON und CSV exportieren
Speichern Sie Ihre Ergebnisse parallel in beiden Formaten: JSON bewahrt die verschachtelte Struktur, was für Varianten und Details nützlich ist; CSV ist flach und lässt sich direkt in Excel oder Google Sheets öffnen.
import json, csv
results = scrape_search("smartphone")
# Option A - JSON (keeps nested structure)
with open("ebay.json", "w", encoding="utf-8") as f:
json.dump(results, f, indent=2, ensure_ascii=False)
# Option B - CSV (flat, opens in Excel/Sheets)
if results:
with open("ebay.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=results[0].keys())
writer.writeheader()
writer.writerows(results)
Schritt 7: Die Anti-Bot-Maßnahmen von eBay umgehen
eBay schützt Angebote mit mehreren Ebenen: Bewertung der IP-Reputation, Ratenlimits (HTTP 429), weiche Sperren (eine 200-Antwort mit leerem Ergebnis) und CAPTCHAs. Mit einem einzigen Trick lässt sich nicht alles umgehen, aber die richtigen Header und IPs bewältigen die häufigsten Fälle beim eBay-Web-Scraping in einem angemessenen Umfang.
Passende Header setzen
Senden Sie einen vollständigen, realistischen Header-Satz, nicht nur einen User-Agent. Jeder Header senkt das Risiko einer Sperre: Ein fehlender Accept-Language oder Referer ist ein häufiges Bot-Signal. Bei größeren Aufträgen sollten Sie den User-Agent aus einer Liste rotieren.
HEADERS = {
# identify as a real desktop browser - eBay returns 403/empty without this
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9", # match the locale you target
"Accept-Encoding": "gzip, deflate, br", # accept compressed responses
"Referer": "https://www.ebay.com/", # look like in-site navigation
"Connection": "keep-alive",
}
# rotate the User-Agent across a list for larger jobs
import random
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Version/17.0 Safari/605.1.15",
]
HEADERS["User-Agent"] = random.choice(USER_AGENTS)
Rotierende Residential Proxys verwenden
Bei hohem Volumen reichen Header nicht aus: eBay bewertet die IP-Reputation, und Datacenter Proxys werden wesentlich schneller erkannt als Residential Proxys. Nutzen Sie rotierende Residential IPs für Such-Scraping mit hohem Volumen, also eine frische IP pro Anfrage, und sitzungsgebundene Sitzungen für Angebots- oder Auktionsabläufe, bei denen eine stabile Sitzung wichtig ist. DataImpulse Residential Proxys kosten $1/GB, werden nach Verbrauch abgerechnet und lassen sich direkt in den requests-Aufruf einbinden.
# Route requests through DataImpulse rotating residential proxies
proxies = {
"http": "http://LOGIN:[email protected]:823",
"https": "http://LOGIN:[email protected]:823",
}
html = requests.get(url, headers=HEADERS, proxies=proxies, timeout=30)
Geotargeting: Regionsspezifische eBay-Daten scrapen
eBay-Angebote unterscheiden sich je nach Land: eBay.com, eBay.co.uk und eBay.de liefern für dasselbe Produkt unterschiedliche Preise, Verfügbarkeiten und Versandoptionen. Um die Daten zu sehen, die ein Käufer in einem bestimmten Land sieht, leiten Sie den Datenverkehr über einen dort ansässigen Proxy. DataImpulse bietet Residential IPs in 195 Ländern, einschließlich Targeting auf Ebene von US-Bundesstaaten. So bildet Ihr eBay-Daten-Scraping den richtigen Markt ab. Derselbe Ansatz ermöglicht Preisvergleiche über verschiedene Regionen hinweg.
Schritt 8: Ihren eBay-Scraper skalieren
Drei Stufen verwandeln das Basisskript in eine produktionsreife Methode, eBay mit Python im großen Maßstab zu scrapen. Nach zunehmender Komplexität sind das: eine zufällige Verzögerung zwischen Anfragen, um unter den Ratenlimits zu bleiben; Wiederholungslogik mit exponentiellem Backoff, um 429/403-Antworten abzufangen; und asynchrone Erfassung mit httpx + asyncio für paralleles Volumen.
import time, random, asyncio, httpx
# 1) Basic pacing - a random delay between requests
def polite_get(url, **kw):
time.sleep(random.uniform(1, 3))
return requests.get(url, headers=HEADERS, timeout=30, **kw)
# 2) Retry with exponential backoff on 429/403
def get_with_retry(url, retries=4, **kw):
for attempt in range(retries):
r = requests.get(url, headers=HEADERS, timeout=30, **kw)
if r.status_code not in (429, 403):
return r
time.sleep(2 ** attempt + random.random()) # 1s, 2s, 4s, 8s ...
return r
# 3) Async collection for high volume (httpx >=0.28 uses proxy=, not proxies=)
async def scrape_many(urls, proxy=None):
async with httpx.AsyncClient(headers=HEADERS, proxy=proxy, timeout=30) as client:
tasks = [client.get(u) for u in urls]
return await asyncio.gather(*tasks)
Häufig gestellte Fragen
Ist es legal, eBay zu scrapen?
Das kommt darauf an. Das Scrapen öffentlich verfügbarer Daten kann in manchen Kontexten rechtmäßig sein. Die eBay-Nutzungsvereinbarung beschränkt jedoch automatisierten Zugriff durch Bots, Scraper und Data-Mining-Tools ohne vorherige Genehmigung. Scraping kann daher gegen die Bedingungen verstoßen und rechtliche Risiken bergen. Die Nutzung von Proxys an sich ist legal. Beachten Sie Ratenlimits, scrapen Sie nicht hinter Logins, vermeiden Sie personenbezogene Daten und holen Sie für die kommerzielle Nutzung Rechtsberatung ein. Dies sind allgemeine Informationen und keine Rechtsberatung. Weitere Informationen finden Sie in unserem Leitfaden zur Rechtmäßigkeit von Web-Scraping.
Benötige ich Proxys, um eBay zu scrapen?
Für eine Handvoll Anfragen nein. Für jedes ernsthafte Volumen ja: eBay bewertet die IP-Reputation und setzt strenge Ratenlimits, sodass eine einzelne IP schnell gesperrt wird. Rotierende Residential Proxys verteilen Anfragen auf viele IPs und ermöglichen das Targeting bestimmter Länder für regionsgerechte Preise.
Wie scrape ich eBay-Produktvarianten?
Varianten wie Größe und Farbe befinden sich nicht im sichtbaren HTML. eBay speichert sie in einem Inline-JSON-Objekt (MSKU) innerhalb eines Script-Tags. Suchen Sie dieses Objekt mit re.search() und parsen Sie es mit json.loads(), wie in Schritt 4 gezeigt.
Warum liefert mein eBay-Scraper leere Ergebnisse zurück?
Meistens liegt es an den Headern. Ohne einen echten Browser-User-Agent und idealerweise Accept-Language sowie Referer liefert eBay häufig 403 oder 200 mit einem leeren Body zurück. Fügen Sie den vollständigen Header-Satz aus Schritt 7 hinzu. Falls das Problem weiter besteht, wurden Sie wahrscheinlich durch ein Ratenlimit eingeschränkt oder Ihre IP wurde markiert. Verringern Sie dann die Geschwindigkeit und leiten Sie die Anfragen über einen Residential Proxy.
Wie verarbeite ich die eBay-Paginierung in Python?
Erhöhen Sie den URL-Parameter _pgn (&_pgn=2, 3, …) in einer Schleife und stoppen Sie, wenn der Ergebnis-Container (li.s-item) leer ist oder Sie ein Seitenlimit erreichen, wie in der Paginierungsfunktion in Schritt 3.
Fazit
So scrapen Sie eBay mit Python von Anfang bis Ende: Scraper für Suchergebnisse und Angebote, Paginierung, Extraktion versteckter Varianten, Bewertungen, JSON/CSV-Export sowie Header und rotierende Residential Proxys, die Ihr eBay-Scraper-Python-Setup am Laufen halten. Beginnen Sie mit dem Such-Scraper und ergänzen Sie dann Paginierung, Anti-Bot-Header und Skalierung, wenn Ihr Volumen wächst. Die passenden IPs finden Sie in unserem Leitfaden zu den besten Proxys für eBay-Scraping.
Zuletzt aktualisiert: 24. Juni 2026.
