eBay est l'une des plus grandes places de marché du web, et chaque annonce publique contient exactement le type de données structurées qui alimentent le suivi des prix, la veille concurrentielle et l'analyse de marché : un titre, un prix, l'état de l'article, le coût de livraison, le vendeur et un lien vers l'annonce. Le problème est qu'eBay affiche les prix et une grande partie des détails avec JavaScript et bloque agressivement le trafic automatisé, si bien qu'une simple requête HTTP vous renvoie une page presque vide au lieu des données recherchées.

Ce guide vous montre comment scraper eBay avec JavaScript et Node.js de manière fiable. Vous construirez un petit scraper fonctionnel qui récupère une page de recherche ou d'annonce eBay rendue via la Crawling API, analyse chaque résultat avec cheerio et affiche un enregistrement structuré propre par article. L'ensemble du tutoriel se limite aux données d'annonces publiques, et la section sur la légalité à la fin n'est pas un simple formulaire, alors lisez-la avant de l'utiliser à grande échelle.

Ce que vous allez construire

Un script Node.js qui prend une URL de recherche eBay publique, récupère le HTML rendu via la Crawling API, et extrait un enregistrement structuré pour chaque annonce sur la page de résultats. Nous utiliserons une recherche par catégorie comme exemple fil rouge et extrairons ces champs par article :

  • Titre le nom de l'annonce, par exemple "Apple iPhone 14 Pro Max 128 Go Débloqué".
  • Prix le prix affiché, comme "1 429,49 $".
  • État l'état de l'article, par exemple "Neuf" ou "Occasion".
  • Livraison le coût de livraison ou "Livraison gratuite" quand c'est indiqué.
  • Vendeur le nom du vendeur ou de la boutique si présent sur la carte.
  • URL de l'article le lien vers la page d'annonce individuelle.

Pourquoi une simple requête échoue sur eBay

Si vous demandez une URL de recherche eBay avec un client HTTP basique, vous obtenez une réponse avec le statut 200 et seulement une partie des données d'annonce dans le corps. Deux facteurs jouent contre vous. D'abord, eBay affiche les prix, la livraison et d'autres détails dans le navigateur avec JavaScript, donc le HTML initial est incomplet tant que les scripts de la page ne s'exécutent pas. Ensuite, eBay repère rapidement le trafic automatisé : les IP de datacenter et les patterns de requêtes qui ne ressemblent pas à un vrai navigateur sont challengés, limités ou bloqués avant même d'atteindre le contenu rendu.

Un scraper eBay fonctionnel a donc besoin de deux choses en une seule requête : un navigateur qui rend réellement la page, et une IP que la plateforme considère comme un vrai visiteur. Vous pouvez assembler cela vous-même avec un navigateur headless et un pool de proxies résidentiels rotatifs, mais les assembler et les maintenir en bonne santé représente l'essentiel du travail. La Crawling API regroupe les deux en un seul appel : envoyez-lui l'URL avec un token JavaScript, elle rend la page derrière une IP de confiance, et elle vous renvoie le HTML finalisé à analyser.

Pourquoi le token JS

Crawlbase propose deux types de token. Le token normal récupère le HTML statique ; le token JavaScript (JS) rend d'abord la page dans un vrai navigateur. eBay charge les champs clés des annonces côté client, donc le token JS vous donne la page la plus complète ici. Utiliser le token normal peut renvoyer un résultat partiel sans prix ni livraison, ne vous laissant rien de fiable à analyser.

Prérequis

Vous avez besoin de quelques éléments en place avant d'écrire du code. Aucun ne prend longtemps.

JavaScript et Node.js de base. Vous devez être à l'aise pour écrire et exécuter un script Node et installer des paquets avec npm. Si vous débutez avec Node, la documentation officielle et n'importe quel cours débutant vous amèneront au niveau qu'assume ce tutoriel. Pour un tutoriel plus complet, consultez notre guide sur comment construire un scraper web avec Node.js.

Node.js 16 ou version ultérieure. Confirmez votre version avec node --version. Si vous ne l'avez pas, installez-le depuis le site Node.js ou via un gestionnaire de version comme nvm.

Un compte Crawlbase et un token JS. Inscrivez-vous, ouvrez votre tableau de bord, et copiez votre token JavaScript (JS) depuis la page de documentation du compte. Traitez le token comme un mot de passe : il authentifie vos requêtes, donc ne le mettez pas dans le contrôle de version.

Configurer le projet

Créez un dossier de projet, initialisez-le et installez les deux bibliothèques dont le scraper a besoin.

bash
node --version

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

npm install crawlbase cheerio

Deux dépendances font le travail : crawlbase est le client Node officiel pour la Crawling API, et cheerio analyse le HTML renvoyé avec une API de style jQuery vous permettant d'extraire des champs individuels par sélecteur CSS. Si les sélecteurs sont nouveaux pour vous, l'introduction sur XPath et les sélecteurs CSS est un bon complément.

Étape 1 : Récupérer la page de recherche rendue

Commencez par obtenir la page finalisée. Importez la classe CrawlingAPI, initialisez-la avec votre token JS, et demandez l'URL de recherche. Vérifier le code de statut avant d'analyser permet de détecter les échecs rapidement plutôt que silencieusement.

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');
});

Les deux options d'attente sont importantes pour une cible rendue côté client comme celle-ci. ajax_wait indique à l'API d'attendre que le contenu asynchrone ait fini de se charger, et page_wait maintient un nombre fixe de millisecondes après le chargement pour que les éléments à rendu tardif apparaissent avant la capture de la page. Cinq secondes est un bon point de départ ; augmentez si les prix ou la livraison reviennent vides. Exécutez le script avec node scraper.js et vous devriez voir le vrai balisage d'annonce, pas une coquille vidée. Cela confirme que le rendu fonctionne avant d'écrire un seul sélecteur.

Crawlbase eBay Scraper

eBay nécessite une page rendue derrière une IP de confiance, en un seul appel. La Crawling API prend un token JS, exécute la page dans un vrai navigateur, effectue une rotation des IP résidentielles côté serveur, et vous remet le HTML finalisé, vous évitant de gérer vous-même une flotte headless et un pool de proxies. Pointez-la sur une page de recherche publique avec le niveau gratuit d'abord.

Étape 2 : Analyser chaque annonce avec cheerio

Avec le HTML rendu en main, chargez-le dans cheerio et parcourez les cartes de résultats. eBay dispose chaque résultat de recherche dans un bloc répétitif, vous sélectionnez donc chaque carte, puis lisez le titre, le prix, l'état, la livraison, le vendeur et le lien de l'article depuis l'intérieur. Lire chaque champ de manière défensive évite qu'une valeur manquante ne fasse planter l'exécution.

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;
}

Quelques détails rendent ce code robuste. La première carte de chaque page de résultats eBay est un espace promotionnel intitulé "Shop on eBay", donc le return anticipé le saute. Chaque champ revient à null quand l'élément est absent, ce qui est courant car toutes les annonces n'affichent pas un nom de vendeur ou une ligne de livraison séparée. L'URL de l'article est lue depuis l'attribut href de l'ancre plutôt que depuis son texte, elle est donc gérée avec attr plutôt que text.

Les sélecteurs dérivent

Les noms de classes d'eBay (s-item, s-item__price, SECONDARY_INFO, et les autres) changent sans préavis, et ils diffèrent entre les pages de recherche et les pages d'annonces individuelles. Traitez les sélecteurs ci-dessus comme un modèle de départ, pas comme un contrat. Quand un champ revient à null, réinspectez la page en direct dans les outils de développement de votre navigateur et mettez à jour le sélecteur. La maintenance périodique des sélecteurs est normale pour tout scraper en production, pas le signe que quelque chose est cassé.

Étape 3 : Tout assembler

Maintenant, reliez la récupération et l'analyse en un seul script fonctionnel. Récupérez le HTML rendu, passez-le au parseur et affichez les enregistrements structurés.

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();

À quoi ressemble la sortie

Exécutez le script complet avec node scraper.js et vous obtenez un tableau propre d'enregistrements, un par annonce, prêts à être écrits en JSON, CSV ou dans une base de données.

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"
  }
]

Parcourir les pages de résultats

Une seule page de résultats est une démonstration ; un vrai travail parcourt la pagination. eBay expose le numéro de page via le paramètre de requête _pgn, vous pouvez donc construire chaque URL de page dans une boucle, la récupérer via la Crawling API, l'analyser avec la même fonction et collecter les lignes. Comme toutes les pages de résultats partagent la même structure de carte, le parseur que vous avez déjà écrit fonctionne sur toutes sans modifications.

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`);
});

Pour enrichir chaque ligne avec tous les détails (description, toutes les images, le tableau de livraison complet, les évaluations du vendeur), prenez l'itemUrl de chaque carte et récupérez cette page d'annonce individuelle via la même fonction crawl, puis écrivez un petit parseur pour la mise en page d'annonce. Le pattern est identique : rendu, puis analyse. Pour en savoir plus sur les cibles à rendu intensif, consultez comment crawler les sites web JavaScript.

Rester non bloqué

Même avec le rendu géré, eBay surveille le trafic ressemblant à des scrapers. Quelques habitudes maintiennent une exécution saine, et elles s'appliquent à toute cible commerciale difficile.

  • Cadencez vos requêtes. Marteler les pages dans une boucle serrée est le moyen le plus rapide de se faire limiter. Espacez les requêtes et variez vos mots-clés plutôt que de crawler un seul chemin à pleine vitesse.
  • Misez sur la rotation. Un pool d'IP résidentielles répartit les requêtes sur de nombreuses adresses d'utilisateurs réels, de sorte qu'aucune ne déclenche une limite de débit. La Crawling API s'en charge pour vous ; si vous construisez votre propre stack, c'est la partie à bien faire.
  • Lisez les codes de statut. Une exécution qui commence à renvoyer des challenges ou des erreurs vous indique que le débit ou le niveau d'IP actuels ne sont plus suffisants. Traitez cela comme un signal pour ralentir, pas comme du bruit à ignorer.

Pour le guide complet, consultez comment scraper des sites web sans se faire bloquer et l'approfondissement sur comment contourner les captchas lors du scraping. Si vous préférez router votre propre trafic via un pool rotatif plutôt que d'utiliser l'API gérée, le Smart AI Proxy vous offre la même rotation d'IP résidentielles comme endpoint proxy drop-in. eBay est aussi une cible fréquente pour les travaux plus larges de scraping e-commerce, où le même pattern fetch-then-parse s'applique entre les sites.

Est-il légal de scraper eBay ?

La question de savoir si le scraping d'eBay est autorisé dépend des conditions d'utilisation d'eBay, de votre juridiction et de ce que vous faites avec les données. Les conditions d'eBay restreignent l'accès automatisé, donc le scraping peut aller à l'encontre de ces conditions quelle que soit la prudence de vos outils. Aucun code ici ne change cela ; il fait simplement fonctionner la partie technique. Lisez l'Accord Utilisateur d'eBay et son robots.txt, et traitez les deux comme la limite de ce que vous collectez.

Quelques lignes à respecter. Collectez uniquement les données d'annonces publiques : titre, prix, état, livraison, le nom du vendeur tel qu'affiché sur la carte, et le lien de l'article que tout le monde peut voir sans compte. Respectez les attentes de débit énoncées par eBay et maintenez votre volume de requêtes suffisamment bas pour ne pas surcharger ses serveurs. Évitez les données personnelles, y compris tout ce qui est lié à des acheteurs ou vendeurs identifiables au-delà de ce qui est listé publiquement sur une page de résultats. Si vous prévoyez de réutiliser les données commercialement, obtenez une autorisation ou un accord officiel plutôt que de supposer que le silence vaut consentement.

Pour le volume ou l'utilisation commerciale, eBay propose des API officielles, notamment la Browse API et la Finding API, et ce sont les bons outils quand vous avez besoin de grands volumes, d'une structure garantie ou de droits commerciaux. Ce guide est délibérément limité aux pages d'annonces publiques et de recherche car c'est la ligne qui rend le travail défendable. Il ne couvre rien derrière une connexion, les données personnelles des acheteurs ou vendeurs, les messages privés entre utilisateurs, les données de compte ou de commande protégées par une connexion, ni aucune tentative de contournement de l'authentification. Si votre projet nécessite plus que les annonces publiques, les API officielles d'eBay ou un accord de données sont la bonne voie, pas un scraper plus astucieux.

Récapitulatif

Points clés

  • eBay rend les annonces côté client. Une simple requête renvoie une page incomplète, vous devez donc la rendre avant de l'analyser.
  • Vous avez besoin du rendu et d'une IP de confiance ensemble. La Crawling API avec un token JS fait les deux en un seul appel ; ajax_wait et page_wait contrôlent le temps d'attente du contenu.
  • cheerio fait l'extraction. Sélectionnez chaque carte s-item, puis mappez titre, prix, état, livraison, vendeur et URL de l'article vers les sélecteurs actuels, et attendez-vous à ce que ces sélecteurs dérivent.
  • Passez à l'échelle en bouclant les pages. Le paramètre _pgn parcourt les pages de résultats, et le même parseur fonctionne sur toutes les pages avec un rythme sensé.
  • Restez sur les données publiques. Respectez les CGU et robots.txt d'eBay, préférez la Browse API ou la Finding API officielle pour le volume ou l'usage commercial, et ne touchez jamais aux connexions, données personnelles ou messages privés.

Foire aux questions

Pourquoi une simple requête renvoie-t-elle des données incomplètes d'eBay ?

Parce qu'eBay affiche les prix, la livraison et une grande partie des détails d'annonce côté client avec JavaScript. Le HTML initial est partiel tant que les scripts de la page ne s'exécutent pas dans un navigateur, donc une requête HTTP brute renvoie le statut 200 avec des champs clés manquants ou vides. Pour obtenir une page complète, vous devez d'abord la rendre, ce que gère le token JS de la Crawling API.

Dois-je utiliser le token normal ou le token JS pour eBay ?

Utilisez le token JS. Le token normal récupère le HTML statique, qui sur eBay peut revenir sans prix ni livraison. Le token JS rend la page dans un vrai navigateur avant de restituer le HTML, donc les champs d'annonce sont présents quand cheerio les analyse.

Mes sélecteurs retournent null. Qu'est-ce qui a changé ?

Presque certainement le balisage d'eBay. Ses classes de carte s-item, les marqueurs SECONDARY_INFO et les wrappers de section changent sans préavis, et diffèrent entre les pages de recherche et les pages d'annonces individuelles, donc les sélecteurs qui fonctionnaient le mois dernier peuvent casser. Réinspectez une page en direct dans les outils de développement de votre navigateur et mettez à jour les sélecteurs. La maintenance périodique des sélecteurs est normale pour tout scraper en production.

Dois-je utiliser l'API officielle d'eBay ou scraper le site ?

Si vous avez besoin de volume, d'une structure garantie ou de droits de réutilisation commerciale, utilisez la Browse API ou la Finding API officielle d'eBay. Elles sont conçues pour cela et vous maintiennent du bon côté des conditions d'eBay. Le scraping d'annonces publiques avec l'approche de ce guide convient aux petites recherches de données publiques sans accès API en place, tant que vous respectez les CGU, robots.txt et les limites de débit.

Puis-je scraper les données personnelles des acheteurs ou vendeurs sur eBay ?

Non, et ce guide ne le couvre pas. Les détails des acheteurs, les messages privés et les données de compte se trouvent derrière une connexion, donc ce ne sont pas des données publiques. Le scraping de contenu protégé par une connexion, des données personnelles ou le contournement de l'authentification pour y accéder est hors scope ici et va à l'encontre des conditions d'eBay. Pour un accès sanctionné, la bonne voie est l'API officielle d'eBay ou un accord de licence.

Comment éviter d'être bloqué lors du scraping d'eBay ?

Maintenez votre taux de requêtes par IP bas, variez vos mots-clés plutôt que de boucler sur un chemin, et routez via des IP résidentielles rotatives pour qu'aucune adresse unique ne déclenche une limite de débit. La Crawling API gère la rotation et un pool d'IP de confiance pour vous ; si vous construisez votre propre stack, c'est là que vous devez investir. Surveillez les codes de statut et reculez quand vous commencez à voir des challenges.

Commencer à construire

Crawlez n'importe quel site à grande échelle, sans combattre l'infrastructure.

Crawlbase gère les proxies, les empreintes et les CAPTCHA afin que votre équipe livre des pipelines de données au lieu de maintenir la plomberie de crawl. 1 000 requêtes gratuites, sans carte requise.

En libre-service · Sans appel commercial requis · Volumes de crawl entreprise disponibles