eBay ist einer der größten Marktplätze im Web, und jedes öffentliche Inserat enthält genau die Art strukturierter Daten, die Preisverfolgung, Wettbewerbsforschung und Marktanalysen antreiben: einen Titel, einen Preis, den Artikelzustand, die Versandkosten, den Verkäufer und einen Link zum Inserat. Das Problem: eBay rendert Preise und viele Inseratsdetails per JavaScript und sperrt automatisierten Traffic konsequent, sodass eine einfache HTTP-Anfrage statt echter Daten nur eine fast leere Hülle zurückliefert.

Dieser Leitfaden zeigt Ihnen, wie Sie eBay scrapen mit JavaScript und Node.js auf zuverlässige Weise. Sie bauen einen kleinen, lauffähigen Scraper, der eine gerenderte eBay-Such- oder Angebotsseite über die Crawling API abruft, jedes Ergebnis mit cheerio analysiert und pro Artikel einen sauberen strukturierten Datensatz ausgibt. Die gesamte Anleitung beschränkt sich auf öffentliche Inseratsdaten, und der Abschnitt zur Rechtslage am Ende ist kein Boilerplate, also lesen Sie ihn, bevor Sie das auf ein echtes Datenvolumen ansetzen.

Was Sie bauen werden

Ein Node.js-Skript, das eine öffentliche eBay-Such-URL entgegennimmt, das gerenderte HTML über die Crawling API abruft und für jedes Inserat auf der Ergebnisseite einen strukturierten Datensatz extrahiert. Als laufendes Beispiel verwenden wir eine Kategoriesuche und ziehen folgende Felder pro Artikel:

  • Titel der Name des Inserats, zum Beispiel "Apple iPhone 14 Pro Max 128GB Unlocked".
  • Preis der angezeigte Listenpreis, etwa "$1.429,49".
  • Zustand der Artikelzustand, zum Beispiel "Brand New" oder "Pre-Owned".
  • Versand die Versandkosten oder "Free shipping", wenn angegeben.
  • Verkäufer der Verkäufername oder Shopname, wenn auf der Karte vorhanden.
  • Artikel-URL der Link zur einzelnen Angebotsseite.

Warum ein einfacher Fetch bei eBay scheitert

Wenn Sie eine eBay-Such-URL mit einem einfachen HTTP-Client abrufen, erhalten Sie eine Antwort mit Status 200 und nur einem Teil der Inseratsdaten im Body. Zwei Faktoren arbeiten gegen Sie. Erstens rendert eBay Preise, Versandkosten und andere Inseratsdetails im Browser per JavaScript, sodass das initiale HTML unvollständig ist, bis die Skripte der Seite ausgeführt wurden. Zweitens erkennt eBay automatisierten Traffic schnell: Datacenter-IPs und Anfragemuster, die nicht wie ein echter Browser aussehen, werden herausgefordert, gedrosselt oder blockiert, bevor sie jemals den gerenderten Inhalt erreichen.

Ein funktionierender eBay-Scraper benötigt also zwei Dinge in einer Anfrage: einen Browser, der die Seite tatsächlich rendert, und eine IP, die die Plattform als echten Besucher einliest. Sie können das selbst mit einem Headless-Browser plus einem Pool von rotierenden Residential Proxies zusammenbauen, aber diese Infrastruktur zusammenzuhalten und funktionstüchtig zu halten ist der Großteil der Arbeit. Die Crawling API bündelt beides in einem einzigen Aufruf: Sie senden ihr die URL mit einem JavaScript-Token, sie rendert die Seite hinter einer vertrauenswürdigen IP und gibt fertiges HTML zurück, das Sie parsen können.

Warum das JS-Token

Crawlbase bietet zwei Token-Typen. Das normale Token ruft statisches HTML ab; das JavaScript-Token (JS-Token) rendert die Seite zuerst in einem echten Browser. eBay lädt wichtige Inseratsfelder clientseitig, daher liefert das JS-Token hier die vollständigste Seite. Die Verwendung des normalen Tokens kann ein unvollständiges Ergebnis zurückgeben, bei dem Preise oder Versandangaben fehlen, sodass nichts Verlässliches zum Parsen übrig bleibt.

Voraussetzungen

Sie benötigen ein paar Dinge, bevor Sie mit dem Programmieren beginnen. Nichts davon dauert lange.

Grundlegende JavaScript- und Node.js-Kenntnisse. Sie sollten in der Lage sein, ein Node-Skript zu schreiben und auszuführen sowie Pakete mit npm zu installieren. Wenn Sie neu bei Node sind, helfen Ihnen die offiziellen Dokumentationen und jeder Einsteigerkurs auf das Niveau, das dieses Tutorial voraussetzt. Eine ausführlichere Anleitung finden Sie in unserem Leitfaden zum Aufbau eines Web-Scrapers mit Node.js.

Node.js 16 oder neuer. Überprüfen Sie Ihre Version mit node --version. Falls Sie es nicht haben, installieren Sie es von der Node.js-Website oder über einen Versionsmanager wie nvm.

Ein Crawlbase-Konto und ein JS-Token. Registrieren Sie sich, öffnen Sie Ihr Dashboard und kopieren Sie Ihr JavaScript-Token (JS-Token) von der Kontodokumentationsseite. Behandeln Sie das Token wie ein Passwort: Es authentifiziert Ihre Anfragen, halten Sie es also aus der Versionskontrolle heraus.

Projekt einrichten

Erstellen Sie einen Projektordner, initialisieren Sie ihn und installieren Sie die beiden Bibliotheken, die der Scraper benötigt.

bash
node --version

mkdir ebay-scraper && cd ebay-scraper
npm init -y

npm install crawlbase cheerio

Zwei Abhängigkeiten erledigen die Arbeit: crawlbase ist der offizielle Node-Client für die Crawling API, und cheerio analysiert das zurückgegebene HTML mit einer jQuery-ähnlichen API, sodass Sie einzelne Felder per CSS-Selektor extrahieren können. Falls Selektoren neu für Sie sind, ist der Leitfaden zu XPath und CSS-Selektoren eine gute Ergänzung.

Schritt 1: Die gerenderte Suchergebnisseite abrufen

Beginnen Sie damit, die fertige Seite zu laden. Importieren Sie die CrawlingAPI-Klasse, initialisieren Sie sie mit Ihrem JS-Token und fordern Sie die Such-URL an. Den Statuscode zu prüfen, bevor Sie parsen, sorgt dafür, dass Fehler laut statt still auftreten.

javascript
const { CrawlingAPI } = require('crawlbase');

const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_JS_TOKEN' });

async function crawl(pageUrl) {
  const options = { ajax_wait: 'true', page_wait: 5000 };
  const response = await api.get(pageUrl, options);
  if (response.statusCode === 200) {
    return response.body;
  }
  console.error(`Request failed: ${response.statusCode}`);
  return null;
}

const searchUrl = 'https://www.ebay.com/sch/i.html?_nkw=smartphone';
crawl(searchUrl).then((html) => {
  console.log(html ? html.slice(0, 500) : 'No HTML returned');
});

Die beiden Wait-Optionen sind wichtig für ein clientseitig gerendertes Ziel wie dieses. ajax_wait weist die API an, auf das Laden asynchroner Inhalte zu warten, und page_wait hält eine feste Anzahl von Millisekunden nach dem Laden an, damit spät gerenderte Elemente erscheinen, bevor die Seite erfasst wird. Fünf Sekunden sind ein vernünftiger Ausgangspunkt; erhöhen Sie den Wert, wenn Preise oder Versandangaben leer zurückkommen. Führen Sie das Skript mit node scraper.js aus, und Sie sollten echtes Inserats-Markup sehen, keine abgespeckte Hülle. Das bestätigt, dass das Rendering funktioniert, bevor Sie einen einzigen Selektor schreiben.

Crawlbase eBay Scraper

eBay benötigt eine gerenderte Seite hinter einer vertrauenswürdigen IP, in einem einzigen Aufruf. Die Crawling API nimmt ein JS-Token, führt die Seite in einem echten Browser aus, rotiert serverseitig durch Residential IPs und gibt Ihnen fertiges HTML zurück, sodass Sie keinen eigenen Headless-Browser-Pool und keinen Proxy-Pool betreiben müssen. Testen Sie es zunächst auf einer öffentlichen Suchseite im kostenlosen Kontingent.

Schritt 2: Jedes Inserat mit cheerio parsen

Mit gerendered HTML in der Hand laden Sie es in cheerio und durchlaufen die Ergebniskarten. eBay legt jedes Suchergebnis in einem sich wiederholenden Block an, sodass Sie jede Karte auswählen und dann Titel, Preis, Zustand, Versand, Verkäufer und den Artikel-Link aus dem Inneren lesen. Jedes Feld defensiv zu lesen verhindert, dass ein einzelner fehlender Wert den gesamten Lauf zum Absturz bringt.

javascript
const cheerio = require('cheerio');

function parseSearch(html) {
  const $ = cheerio.load(html);
  const items = [];

  $('li.s-item').each((_, el) => {
    const card = $(el);
    const title = card.find('.s-item__title').text().trim();
    if (!title || title === 'Shop on eBay') return;

    items.push({
      title,
      price: card.find('.s-item__price').text().trim() || null,
      condition: card.find('.SECONDARY_INFO').text().trim() || null,
      shipping: card.find('.s-item__shipping').text().trim() || null,
      seller: card.find('.s-item__seller-info-text').text().trim() || null,
      itemUrl: card.find('a.s-item__link').attr('href') || null,
    });
  });

  return items;
}

Ein paar Details machen dies robust. Die erste Karte auf jeder eBay-Ergebnisseite ist ein Werbeplatzhalter mit dem Titel "Shop on eBay", daher überspringt das frühe return sie. Jedes Feld fällt auf null zurück, wenn das Element fehlt, was häufig vorkommt, da nicht jedes Inserat einen Verkäufernamen oder eine separate Versandzeile anzeigt. Die Artikel-URL wird aus dem href des Ankers gelesen statt aus seinem Text, weshalb sie mit attr statt text behandelt wird.

Selektoren verändern sich

eBays Klassennamen (s-item, s-item__price, SECONDARY_INFO und der Rest) ändern sich ohne Vorankündigung, und sie unterscheiden sich zwischen Such- und einzelnen Angebotsseiten. Behandeln Sie die obigen Selektoren als Ausgangspunkt, nicht als Vertrag. Wenn ein Feld als null zurückkommt, überprüfen Sie die Live-Seite in den Entwicklertools Ihres Browsers und aktualisieren Sie den Selektor. Regelmäßige Selektor-Wartung ist für jeden Produktions-Scraper normal, kein Zeichen dafür, dass etwas kaputt ist.

Schritt 3: Alles zusammenführen

Verbinden Sie nun den Abruf und das Parsing in einem lauffähigen Skript. Holen Sie das gerenderte HTML, übergeben Sie es an den Parser und geben Sie die strukturierten Datensätze aus.

javascript
const { CrawlingAPI } = require('crawlbase');
const cheerio = require('cheerio');

const api = new CrawlingAPI({ token: 'YOUR_CRAWLBASE_JS_TOKEN' });

async function crawl(pageUrl) {
  const options = { ajax_wait: 'true', page_wait: 5000 };
  const response = await api.get(pageUrl, options);
  if (response.statusCode === 200) return response.body;
  console.error(`Request failed: ${response.statusCode}`);
  return null;
}

function parseSearch(html) {
  const $ = cheerio.load(html);
  const items = [];
  $('li.s-item').each((_, el) => {
    const card = $(el);
    const title = card.find('.s-item__title').text().trim();
    if (!title || title === 'Shop on eBay') return;
    items.push({
      title,
      price: card.find('.s-item__price').text().trim() || null,
      condition: card.find('.SECONDARY_INFO').text().trim() || null,
      shipping: card.find('.s-item__shipping').text().trim() || null,
      seller: card.find('.s-item__seller-info-text').text().trim() || null,
      itemUrl: card.find('a.s-item__link').attr('href') || null,
    });
  });
  return items;
}

async function main() {
  const searchUrl = 'https://www.ebay.com/sch/i.html?_nkw=smartphone';
  const html = await crawl(searchUrl);
  if (!html) return;
  const items = parseSearch(html);
  console.log(JSON.stringify(items.slice(0, 3), null, 2));
}

main();

Wie die Ausgabe aussieht

Führen Sie das vollständige Skript mit node scraper.js aus und erhalten Sie ein sauberes Array von Datensätzen, einen pro Inserat, bereit zum Schreiben in JSON, CSV oder eine Datenbank.

json
[
  {
    "title": "Apple iPhone 14 Pro Max 128GB Unlocked New Sealed",
    "price": "$1,429.49",
    "condition": "Brand New",
    "shipping": "Free shipping",
    "seller": "beyond_theworld (4,512)",
    "itemUrl": "https://www.ebay.com/itm/354586733872"
  },
  {
    "title": "Apple iPhone X 64GB Unlocked Good Refurbished",
    "price": "$249.99",
    "condition": "Pre-Owned",
    "shipping": "+$12.50 shipping",
    "seller": "thetechout (1,685)",
    "itemUrl": "https://www.ebay.com/itm/393541114176"
  }
]

Durch Ergebnisseiten blättern

Eine Ergebnisseite ist eine Demo; ein echter Auftrag durchläuft die Paginierung. eBay stellt die Seitenzahl über den Query-Parameter _pgn bereit, sodass Sie jede Seiten-URL in einer Schleife aufbauen, sie über die Crawling API abrufen, mit der gleichen Funktion parsen und die Zeilen sammeln können. Da jede Ergebnisseite dieselbe Kartenstruktur hat, funktioniert der bereits geschriebene Parser ohne Änderungen auf allen Seiten.

javascript
async function scrapePages(keyword, totalPages) {
  const all = [];
  for (let page = 1; page <= totalPages; page++) {
    const url =
      `https://www.ebay.com/sch/i.html?_nkw=${encodeURIComponent(keyword)}&_pgn=${page}`;
    const html = await crawl(url);
    if (html) all.push(...parseSearch(html));
  }
  return all;
}

scrapePages('smartphone', 3).then((rows) => {
  console.log(`Collected ${rows.length} listings`);
});

Um jede Zeile mit vollständigen Details anzureichern (Beschreibung, alle Bilder, die vollständige Versandtabelle, Verkäuferbewertung), nehmen Sie die itemUrl aus jeder Karte und rufen Sie die einzelne Angebotsseite mit der gleichen crawl-Funktion ab, dann schreiben Sie einen kleinen Parser für das Angebotslayout. Das Muster ist identisch: rendern, dann parsen. Mehr zu renderintensiven Zielen finden Sie in unserem Leitfaden zum Crawlen von JavaScript-Websites.

Nicht geblockt werden

Auch wenn das Rendering erledigt ist, beobachtet eBay scraperartigen Traffic. Ein paar Gewohnheiten halten einen Lauf gesund, und sie gelten für jedes schwierige kommerzielle Ziel.

  • Anfragen verlangsamen. Seiten in einer engen Schleife zu bombardieren ist der schnellste Weg, gedrosselt zu werden. Verteilen Sie Anfragen und variieren Sie Ihre Suchbegriffe, statt einen einzigen Pfad mit voller Geschwindigkeit zu crawlen.
  • Auf Rotation setzen. Ein Pool von Residential IPs verteilt Anfragen auf viele echte Nutzeradressen, sodass keine einzelne eine Ratenbegrenzung auslöst. Die Crawling API übernimmt das für Sie; wenn Sie Ihren eigenen Stack betreiben, ist das der Teil, den Sie richtig hinbekommen müssen.
  • Statuscodes lesen. Ein Lauf, der beginnt, Herausforderungen oder Fehler zurückzugeben, signalisiert Ihnen, dass die aktuelle Rate oder IP-Stufe nicht mehr ausreicht. Behandeln Sie das als Signal zum Zurückrudern, nicht als Lärm, den Sie ignorieren können.

Für das umfassendere Playbook lesen Sie, wie Sie Websites scrapen, ohne geblockt zu werden, und den ausführlicheren Leitfaden zum Umgehen von CAPTCHAs beim Web-Scraping. Wenn Sie Ihren eigenen Traffic lieber über einen rotierenden Pool leiten statt die verwaltete API zu nutzen, bietet der Smart AI Proxy die gleiche Residential-IP-Rotation als Drop-in-Proxy-Endpunkt. eBay ist auch ein häufiges Ziel für breitere E-Commerce-Web-Scraping-Projekte, bei denen das gleiche Fetch-dann-Parse-Muster seitenübergreifend funktioniert.

Ob das Scrapen von eBay erlaubt ist, hängt von eBays Nutzungsbedingungen, Ihrer Rechtsordnung und dem ab, was Sie mit den Daten machen. eBays Bedingungen schränken automatisierten Zugriff ein, sodass Scraping gegen diese Bedingungen verstoßen kann, unabhängig davon, wie sorgfältig Ihr Tooling ist. Kein Code hier ändert das; er lässt nur den technischen Teil funktionieren. Lesen Sie eBays Nutzungsvertrag und die robots.txt und behandeln Sie beides als Grenze für das, was Sie erfassen.

Einige Grundsätze, die es zu beachten gilt. Erfassen Sie nur öffentliche Inseratsdaten: Titel, Preis, Zustand, Versand, den Verkäufernamen wie auf der Karte angezeigt und den Artikel-Link, den jeder ohne Konto sehen kann. Respektieren Sie eBays erklärte Ratenerwartungen und halten Sie Ihr Anfragevolumen niedrig genug, dass Sie deren Server nicht belasten. Vermeiden Sie persönliche Daten, einschließlich aller Daten, die identifizierbaren Käufern oder Verkäufern zugeordnet sind, über das hinaus, was öffentlich auf einer Ergebnisseite aufgeführt ist. Wenn Sie beabsichtigen, die Daten kommerziell weiterzuverwenden, holen Sie sich eine Genehmigung oder eine offizielle Vereinbarung, statt anzunehmen, dass Schweigen Zustimmung bedeutet.

Für Volumen oder kommerzielle Nutzung bietet eBay offizielle APIs an, darunter die Browse API und die Finding API, und das sind die richtigen Werkzeuge, wenn Sie große Mengen, garantierte Struktur oder kommerzielle Rechte benötigen. Dieser Leitfaden ist bewusst auf öffentliche Inserat- und Suchseiten beschränkt, weil das die Linie ist, die die Arbeit vertretbar hält. Er deckt nichts hinter einem Login, keine persönlichen Daten von Käufern oder Verkäufern, keine privaten Nachrichten zwischen Nutzern, keine durch Anmeldung gesperrten Konto- oder Bestelldaten und keinen Versuch, die Authentifizierung zu umgehen, ab. Wenn Ihr Projekt mehr als öffentliche Inserate benötigt, sind eBays offizielle APIs oder eine Datenvereinbarung der richtige Weg, kein clevererer Scraper.

Zusammenfassung

Wichtigste Erkenntnisse

  • eBay rendert Inserate clientseitig. Ein einfacher Fetch gibt eine unvollständige Seite zurück, daher müssen Sie sie rendern, bevor Sie sie parsen.
  • Sie benötigen Rendering und eine vertrauenswürdige IP gemeinsam. Die Crawling API mit einem JS-Token erledigt beides in einem Aufruf; ajax_wait und page_wait steuern, wie lange auf Inhalte gewartet wird.
  • cheerio übernimmt die Extraktion. Wählen Sie jede s-item-Karte aus und ordnen Sie dann Titel, Preis, Zustand, Versand, Verkäufer und die Artikel-URL den aktuellen Selektoren zu, und rechnen Sie damit, dass diese Selektoren sich verändern.
  • Skalierung durch Seiteniterationen. Der Parameter _pgn durchläuft die Ergebnisseiten, und der gleiche Parser funktioniert auf jeder Seite mit sinnvoller Drosselung.
  • Auf öffentlichen Daten bleiben. Respektieren Sie eBays AGB und robots.txt, bevorzugen Sie die offizielle Browse- oder Finding API für Volumen oder kommerzielle Nutzung und berühren Sie niemals Logins, persönliche Daten oder private Nachrichten.

Häufig gestellte Fragen

Warum gibt ein einfacher Fetch unvollständige Daten von eBay zurück?

Weil eBay Preise, Versand und einen Großteil der Inseratsdetails clientseitig mit JavaScript rendert. Das initiale HTML ist unvollständig, bis die Skripte der Seite in einem Browser ausgeführt werden, sodass eine rohe HTTP-Anfrage Status 200 zurückgibt, wobei Schlüsselfelder fehlen oder leer sind. Um eine vollständige Seite zu erhalten, müssen Sie sie zuerst rendern, was das JS-Token der Crawling API für Sie übernimmt.

Brauche ich das normale Token oder das JS-Token für eBay?

Verwenden Sie das JS-Token. Das normale Token ruft statisches HTML ab, das bei eBay mit fehlenden Preisen oder Versandangaben zurückkommen kann. Das JS-Token rendert die Seite in einem echten Browser, bevor es das HTML zurückgibt, sodass die Inseratsfelder vorhanden sind, wenn cheerio sie parst.

Meine Selektoren geben null zurück. Was hat sich geändert?

Höchstwahrscheinlich das Markup von eBay. Die s-item-Kartenklassen, SECONDARY_INFO-Marker und Abschnittswrapper ändern sich ohne Vorankündigung, und sie unterscheiden sich zwischen Such- und einzelnen Angebotsseiten, sodass Selektoren, die letzten Monat funktionierten, jetzt brechen können. Überprüfen Sie eine Live-Seite in den Entwicklertools Ihres Browsers und aktualisieren Sie die Selektoren. Regelmäßige Selektor-Wartung ist für jeden Produktions-Scraper normal.

Sollte ich eBays offizielle API nutzen oder die Website scrapen?

Wenn Sie Volumen, garantierte Struktur oder kommerzielle Wiederverwendungsrechte benötigen, verwenden Sie eBays offizielle Browse- oder Finding API. Diese sind dafür konzipiert und halten Sie auf der richtigen Seite von eBays Bedingungen. Das Scrapen öffentlicher Inserate mit dem in diesem Leitfaden beschriebenen Ansatz eignet sich für kleinere, auf öffentliche Daten ausgerichtete Forschung, bei der kein API-Zugang besteht, solange Sie AGB, robots.txt und Ratenlimits respektieren.

Kann ich persönliche Daten von Käufern oder Verkäufern von eBay scrapen?

Nein, und dieser Leitfaden behandelt das nicht. Käuferdetails, private Nachrichten und Kontodaten befinden sich hinter einem Login und sind daher keine öffentlichen Daten. Das Scrapen von login-gesperrten Inhalten, persönlichen Daten oder das Umgehen der Authentifizierung, um sie zu erreichen, liegt außerhalb des Rahmens dieses Leitfadens und verstößt gegen eBays Bedingungen. Für sanktionierten Zugriff ist eBays offizielle API oder eine Lizenzvereinbarung der richtige Weg.

Wie vermeide ich das Geblocktwerden beim Scrapen von eBay?

Halten Sie Ihre Pro-IP-Anfragerate niedrig, variieren Sie Ihre Suchbegriffe statt einen Pfad zu schleifen, und leiten Sie durch rotierende Residential IPs, sodass keine einzelne Adresse eine Ratenbegrenzung auslöst. Die Crawling API verwaltet die Rotation und einen vertrauenswürdigen IP-Pool für Sie; wenn Sie Ihren eigenen Stack aufbauen, ist das der Teil, in den Sie investieren sollten. Beobachten Sie die Statuscodes und rudern Sie zurück, wenn Sie beginnen, Herausforderungen zu sehen.

Jetzt loslegen

Crawlen Sie jede Website im großen Maßstab, ohne gegen die Infrastruktur zu kämpfen.

Crawlbase übernimmt Proxys, Fingerprints und CAPTCHAs, damit Ihr Team Datenpipelines ausliefert, statt Crawl-Infrastruktur zu pflegen. 1.000 Anfragen kostenlos, keine Karte erforderlich.

Self-Service · Kein Verkaufsgespräch erforderlich · Enterprise-Crawl-Volumen verfügbar