La page de résultats de recherche d'Amazon est l'un des jeux de données publics les plus riches du e-commerce : chaque requête renvoie une grille classée de produits avec des titres, des prix, des notes, des compteurs d'avis et un lien vers chaque annonce. Suivre l'évolution de cette grille dans le temps vous indique ce qui se vend, où un concurrent se positionne sur un mot-clé et comment les prix évoluent dans une catégorie. Les données sont publiques, mais les extraire de manière fiable depuis un script est la partie difficile, car Amazon rend une grande partie de la page avec JavaScript et met en défi le trafic automatisé très rapidement.

Ce guide vous montre comment scraper les SERP Amazon avec Next.js, la façon full-stack. Vous construisez une petite application Next.js fonctionnelle dont la server action appelle la Crawling API pour récupérer une page de recherche Amazon rendue, parse chaque produit avec Cheerio et affiche les résultats dans une grille React. Le token Crawlbase reste côté serveur tout au long, jamais exposé au navigateur. Nous limitons le guide aux données de recherche publiques, et la section sur la légalité vers la fin n'est pas un remplissage de formulaire, lisez-la avant de pointer ce scraper sur un volume réel. Si vous préférez la version script simple, voir comment scraper les pages de recherche Amazon avec la Crawling API.

Ce que vous allez construire

Une application Next.js (App Router) avec une server action qui prend un mot-clé de recherche, récupère le SERP Amazon rendu via la Crawling API, le parse avec Cheerio et renvoie un enregistrement structuré par produit à un composant client qui affiche la grille. Nous extrayons ces champs par élément :

  • Nom le titre du produit tel qu'affiché sur la carte, par exemple "Apple iPhone 15 Pro Max 256GB".
  • Prix le prix affiché, comme "$1,199.00".
  • Image l'URL de la miniature du produit pour afficher la carte.
  • Note le texte de la note en étoiles quand il est présent, tel que "4.7 out of 5 stars".
  • Avis le compteur d'avis clients affiché à côté de la note.
  • URL le lien absolu vers la page du produit individuel.

Pourquoi une requête simple échoue sur Amazon

Si vous demandez une URL de recherche Amazon avec un client HTTP basique, vous obtenez rarement la grille de produits propre que vous voyez dans un navigateur. Deux choses jouent contre vous. Premièrement, Amazon rend les prix, les notes et des parties de chaque carte de résultat dans le navigateur avec JavaScript, de sorte que le HTML brut peut revenir incomplet. Deuxièmement, Amazon signale rapidement le trafic automatisé : les IP de datacenter et les schémas de requêtes qui ne ressemblent pas à un vrai navigateur reçoivent un CAPTCHA, un interstitiel "robot check" ou un blocage pur avant même d'atteindre les produits.

Un scraper de SERP Amazon 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 lit comme un vrai visiteur. Vous pouvez assembler cela vous-même avec un navigateur headless plus un pool de proxies résidentiels rotatifs, mais les relier et les maintenir en bonne santé représente l'essentiel du travail. La Crawling API combine les deux en un seul appel : vous lui envoyez l'URL avec un token JavaScript, elle rend la page derrière une IP de confiance, et vous renvoie le HTML final à parser. Faire cela depuis une server action Next.js garde votre token hors du client et votre fetch côté serveur, ce qui est exactement où il doit être.

Pourquoi le token JS

Crawlbase propose deux types de tokens. Le token normal récupère le HTML statique ; le token JavaScript (JS) rend d'abord la page dans un vrai navigateur. Amazon charge des champs de résultats clés côté client, donc le token JS vous donne la page la plus complète ici. Utiliser le token normal peut renvoyer une grille partielle avec des prix ou des notes manquants, ne vous laissant rien de fiable à parser.

Prérequis

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

Node.js 18.17 ou version ultérieure. Next.js nécessite un runtime Node récent. Confirmez votre version avec node --version. Si vous ne l'avez pas, installez-le depuis le site Node.js ou via un gestionnaire de versions comme nvm.

React et Next.js de base. Vous devez être à l'aise avec les composants React, les hooks et l'exécution d'une application Next.js. Si l'App Router et les server actions sont nouveaux pour vous, la documentation officielle Next.js couvre les deux, et notre guide sur la façon de construire un web scraper avec Node.js est un bon complément pour la partie scraping.

Un compte Crawlbase et un token JS. Inscrivez-vous, ouvrez votre tableau de bord et copiez votre token JavaScript (JS) depuis la page de docs du compte. Traitez le token comme un mot de passe : il authentifie vos requêtes, gardez-le côté serveur et hors du contrôle de version. Nous le lirons depuis une variable d'environnement, ne le codez jamais en dur dans un composant client.

Configurer le projet

Scaffoldez une application Next.js, puis installez les deux bibliothèques dont le scraper a besoin. Quand l'assistant de création vous pose des questions, choisissez l'App Router ; le reste des valeurs par défaut convient.

bash
node --version

npx create-next-app@latest amazon-serp-scraper
cd amazon-serp-scraper

npm install crawlbase cheerio

Deux dépendances font le travail : crawlbase est le client Node officiel de la Crawling API, et cheerio parse le HTML renvoyé avec une API de style jQuery pour extraire les champs individuels par sélecteur CSS. Si les sélecteurs sont nouveaux pour vous, le guide sur les XPath et sélecteurs CSS est un bon complément. Placez maintenant votre token dans un fichier env à la racine du projet pour qu'il reste côté serveur :

bash
# .env.local (never commit this file)
CRAWLBASE_JS_TOKEN=YOUR_CRAWLBASE_TOKEN

Comme CRAWLBASE_JS_TOKEN n'a pas de préfixe NEXT_PUBLIC_, Next.js le garde sur le serveur et ne l'intègre jamais dans le JavaScript client. C'est tout l'intérêt de faire le fetch dans une server action.

Étape 1 : récupérer le SERP rendu dans une server action

Créez app/actions.js. La directive 'use server' en haut marque tout dans le fichier comme une server action, donc ce code ne s'exécute que sur le serveur, où le token est en sécurité. Importez le client CrawlingAPI, lisez le token depuis l'environnement et demandez l'URL de recherche Amazon construite à partir du mot-clé. Vérifier le code de statut avant de parser rend les échecs visibles plutôt que silencieux.

javascript
'use server';

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

const api = new CrawlingAPI({ token: process.env.CRAWLBASE_JS_TOKEN });

async function fetchSerpHtml(keyword) {
  const query = encodeURIComponent(keyword.trim());
  const pageUrl = `https://www.amazon.com/s?k=${query}`;
  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;
}

Les deux options d'attente ont leur importance pour une cible rendue côté client comme celle-ci. ajax_wait demande à l'API d'attendre la fin du chargement du contenu asynchrone, et page_wait maintient un délai fixe en millisecondes après le chargement pour que les éléments à rendu tardif apparaissent avant la capture. Cinq secondes est un bon point de départ ; augmentez si les prix ou les notes reviennent vides. À ce stade vous avez du HTML Amazon rendu en main, récupéré côté serveur avec le token tenu à l'écart du navigateur. Cela confirme que le rendu fonctionne avant d'écrire le moindre sélecteur.

Crawlbase Amazon Scraper

Cet appel api.get accomplit la partie difficile qu'Amazon vous impose : il prend votre token JS, exécute la page de recherche dans un vrai navigateur pour que les prix et notes se rendent, fait tourner des IP résidentielles côté serveur pour que la requête ressemble à un vrai visiteur, et remet à votre server action le HTML final. Vous évitez de faire tourner vous-même une flotte de navigateurs headless et un pool de proxies. Pointez-la sur une page de recherche publique sur le niveau gratuit d'abord.

Étape 2 : parser chaque produit avec Cheerio

Une fois le HTML rendu en main, chargez-le dans Cheerio et parcourez les cartes de résultats. Amazon dispose chaque résultat de recherche dans un bloc répétitif tagué div[data-component-type="s-search-result"], vous sélectionnez donc chaque carte, puis lisez le nom, le prix, l'image, la note, le compteur d'avis et le lien produit à l'intérieur. Lire chaque champ défensivement évite qu'une valeur manquante ne fasse planter l'exécution. Ajoutez cette fonction au même fichier app/actions.js.

javascript
const cheerio = require('cheerio');

function parseProducts(html) {
  const $ = cheerio.load(html);
  const products = [];

  $('div[data-component-type="s-search-result"]').each((_, el) => {
    const card = $(el);
    const name = card.find('h2 span').first().text().trim();
    if (!name) return;

    const path = card.find('h2 a').attr('href');

    products.push({
      name,
      price: card.find('.a-price .a-offscreen').first().text().trim() || null,
      image: card.find('img.s-image').attr('src') || null,
      rating: card.find('.a-icon-alt').first().text().trim() || null,
      reviews: card.find('.a-size-base.s-underline-text').first().text().trim() || null,
      url: path ? `https://www.amazon.com${path}` : null,
    });
  });

  return products;
}

Quelques détails rendent ceci robuste. Le prix se trouve dans un span .a-offscreen caché à l'intérieur du bloc .a-price, qui est la source unique la plus propre pour le montant affiché, nous le lisons donc plutôt que d'assembler le symbole et les chiffres. Chaque champ revient à null quand l'élément est absent, ce qui est courant car les cartes sponsorisées et certaines annonces omettent une note ou un compteur d'avis. Le lien produit est un chemin relatif, nous le préfixons donc avec l'origine Amazon pour obtenir une URL absolue et cliquable.

Les sélecteurs dérivent

Les noms de classes et la mise en page d'Amazon (s-search-result, a-price, a-offscreen, s-image, et les autres) changent sans préavis, et varient selon la région et le type de requête. Traitez les sélecteurs ci-dessus comme un modèle de départ, non comme un contrat. Quand un champ revient comme 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, ce n'est pas le signe que quelque chose est cassé.

Étape 3 : exposer une server action et la forme des données

Reliez maintenant la récupération et le parsing dans une seule server action exportée que votre interface peut appeler. Elle prend un mot-clé, renvoie les produits parsés et ne laisse jamais le token fuir vers le client car tout cela reste dans le fichier 'use server'. Ajoutez ceci au bas de app/actions.js.

javascript
export async function scrapeAmazonProducts(keyword) {
  if (!keyword || !keyword.trim()) return { products: [], error: 'Empty search' };
  try {
    const html = await fetchSerpHtml(keyword);
    if (!html) return { products: [], error: 'Fetch failed' };
    const products = parseProducts(html);
    return { products, error: null };
  } catch (err) {
    console.error(err);
    return { products: [], error: 'Something went wrong' };
  }
}

Renvoyer un objet { products, error } simple au lieu de lancer une exception garde le composant client simple : il peut afficher la grille quand products a des lignes et afficher un message quand error est défini, sans try/catch disséminé dans l'interface. Tout ce qui précède s'exécute sur le serveur, donc le token, l'appel à la Crawling API et le parsing Cheerio restent tous hors du bundle navigateur.

Étape 4 : afficher les résultats dans une grille React

Le côté client est petit. Un seul composant client détient l'état de recherche, appelle la server action à la soumission et mappe les produits renvoyés en cartes. Créez app/page.jsx avec la directive 'use client' pour pouvoir utiliser les hooks React, puis importez et appelez l'action directement ; Next.js gère l'aller-retour serveur pour vous.

javascript
'use client';

import { useState } from 'react';
import { scrapeAmazonProducts } from './actions';

export default function Home() {
  const [keyword, setKeyword] = useState('');
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  async function handleSubmit(event) {
    event.preventDefault();
    setLoading(true);
    setError(null);
    const result = await scrapeAmazonProducts(keyword);
    setProducts(result.products);
    setError(result.error);
    setLoading(false);
  }

  return (
    <main className="container">
      <form onSubmit={handleSubmit}>
        <input
          value={keyword}
          onChange={(e) => setKeyword(e.target.value)}
          placeholder="Search Amazon (iPhone, laptop, headphones...)"
        />
        <button type="submit" disabled={loading}>
          {loading ? 'Searching...' : 'Search'}
        </button>
      </form>

      {error && <p className="error">{error}</p>}

      <div className="grid">
        {products.map((product, i) => (
          <a key={i} href={product.url} target="_blank" className="card">
            {product.image && <img src={product.image} alt={product.name} />}
            <h3>{product.name}</h3>
            <p className="price">{product.price}</p>
            <p className="rating">{product.rating} ({product.reviews || 0})</p>
          </a>
        ))}
      </div>
    </main>
  );
}

C'est toute l'interface. Le formulaire met à jour keyword à chaque frappe ; à la soumission il active un indicateur de chargement, attend la server action et stocke les produits et l'erreur renvoyés. La grille mappe chaque produit en une carte qui pointe vers l'annonce Amazon dans un nouvel onglet. Stylisez avec Tailwind ou du CSS simple selon votre goût ; c'est le flux de données qui compte ici. Démarrez l'application avec npm run dev, ouvrez localhost:3000, cherchez quelque chose comme "iPhone 15 Pro Max", et les produits rendus et parsés apparaissent dans la grille.

À quoi ressemble la sortie

La server action renvoie un tableau propre d'enregistrements, un par produit, avant qu'il n'atteigne jamais la grille. Loguez result.products et vous obtenez une structure comme celle-ci, prête à afficher, écrire en JSON ou persister dans une base de données.

json
[
  {
    "name": "Apple iPhone 15 Pro Max 256GB Natural Titanium",
    "price": "$1,199.00",
    "image": "https://m.media-amazon.com/images/I/81fxjeu8fdL._AC_UL320_.jpg",
    "rating": "4.7 out of 5 stars",
    "reviews": "1,284",
    "url": "https://www.amazon.com/dp/B0CHX1W1XY"
  },
  {
    "name": "Samsung Galaxy S24 Ultra 256GB Unlocked",
    "price": "$1,099.99",
    "image": "https://m.media-amazon.com/images/I/71CXi9gZ4mL._AC_UL320_.jpg",
    "rating": "4.5 out of 5 stars",
    "reviews": "912",
    "url": "https://www.amazon.com/dp/B0CMDRCZBP"
  }
]

Passer à l'échelle sur plusieurs pages de résultats

Une page de résultats est une démonstration ; un vrai travail parcourt la pagination. Amazon expose le numéro de page via le paramètre de requête page, vous pouvez donc récupérer chaque page via la même server action, la parser avec la même fonction et collecter les lignes. Comme chaque page de résultats partage la même structure de carte, le parser que vous avez déjà écrit fonctionne sur toutes sans modification. Ajoutez une variante paginée à app/actions.js.

javascript
export async function scrapeAmazonPages(keyword, totalPages) {
  const all = [];
  const query = encodeURIComponent(keyword.trim());
  for (let page = 1; page <= totalPages; page++) {
    const url = `https://www.amazon.com/s?k=${query}&page=${page}`;
    const response = await api.get(url, { ajax_wait: 'true', page_wait: 5000 });
    if (response.statusCode === 200) {
      all.push(...parseProducts(response.body));
    }
  }
  return all;
}

Pour enrichir chaque ligne avec le détail complet du produit (la description complète, chaque image, le buy box, les données d'avis complètes), prenez l'url de chaque carte et récupérez cette page de produit individuel via le même client API, puis écrivez un petit parser pour la mise en page du produit. Le schéma est identique : rendre, puis parser. Pour plus d'informations sur les cibles à rendu intensif, voir comment crawler des sites JavaScript.

Rester non bloqué

Même avec le rendu géré, Amazon surveille le trafic aux allures de scraper. Quelques habitudes maintiennent une exécution en bonne santé, et elles s'appliquent à toute cible commerciale difficile.

  • Cadencez vos requêtes. Marteler les pages en boucle serrée est le moyen le plus rapide de recevoir un CAPTCHA. Répartissez les requêtes et variez vos mots-clés plutôt que de crawler un seul chemin à pleine vitesse.
  • Appuyez-vous sur la rotation. Un pool d'IP résidentielles répartit les requêtes sur de nombreuses adresses de vrais utilisateurs pour qu'aucune ne déclenche de limite de débit. La Crawling API s'en charge pour vous ; si vous construisez votre propre stack, c'est le point à bien régler.
  • Lisez les codes de statut. Une exécution qui commence à renvoyer des défis ou des réponses non-200 vous indique que le débit ou le niveau IP actuel n'est plus suffisant. Traitez ça comme un signal pour ralentir, pas comme du bruit à ignorer.

Pour le cadre plus large, voir comment scraper des sites sans se faire bloquer. Si vous préférez router votre propre trafic via un pool rotatif plutôt qu'utiliser l'API gérée, le Smart AI Proxy vous donne la même rotation d'IP résidentielles comme point d'accès proxy drop-in.

Est-il légal de scraper Amazon ?

Que le scraping d'Amazon soit autorisé dépend des conditions d'utilisation d'Amazon, de votre juridiction et de ce que vous faites des données. Les conditions d'Amazon 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 seulement fonctionner la partie technique. Lisez les conditions d'utilisation d'Amazon et son fichier robots.txt, et traitez les deux comme la frontière de ce que vous collectez.

Quelques lignes à tenir. Collectez uniquement les données de recherche publiques : noms de produits, prix, notes, compteurs d'avis, la miniature et le lien produit que n'importe qui peut voir sans compte. Respectez les attentes de débit d'Amazon et maintenez votre volume de requêtes assez bas pour ne pas surcharger ses serveurs. Évitez les données personnelles, y compris tout ce qui est lié à des évaluateurs identifiables au-delà du texte et des compteurs d'avis publics affichés sur une page de résultats. Ne redistribuez pas les images ou descriptions de produits protégées par le droit d'auteur en gros ; référencez-les, ne les republiez pas comme vôtres. Si vous prévoyez de réutiliser les données commercialement, obtenez une permission ou un accord officiel plutôt que de supposer que le silence vaut consentement.

Pour le volume ou l'usage commercial, Amazon propose des canaux officiels, notamment le Product Advertising API pour les affiliés et les API vendeur et publicitaire d'Amazon pour les entreprises enregistrées, et ce sont les bons outils quand vous avez besoin de grands volumes, d'une structure garantie ou de droits commerciaux. Ce guide se limite délibérément aux pages de recherche et d'annonce publiques parce que c'est la ligne qui rend le travail défendable. Il ne couvre pas ce qui se trouve derrière une connexion, les données de compte acheteur ou vendeur, l'historique des commandes, les messages privés, ou toute tentative de contourner l'authentification ou un défi CAPTCHA comme moyen d'accès. Si votre projet nécessite plus que les données de recherche publiques, les API officielles d'Amazon ou un accord de données sont la voie correcte, pas un scraper plus ingénieux.

Récapitulatif

Points clés

  • Amazon rend le SERP côté client. Une requête simple renvoie une page incomplète ou mise en défi, vous devez donc la rendre avant de la parser.
  • Faites le fetch dans une server action. Un fichier 'use server' garde le token Crawlbase dans process.env sur le serveur et hors du bundle navigateur entièrement.
  • Un seul appel gère le rendu et une IP de confiance. La Crawling API avec un token JS fait les deux ; ajax_wait et page_wait contrôlent le temps d'attente du contenu.
  • Cheerio fait l'extraction. Sélectionnez chaque carte s-search-result, puis mappez le nom, le prix, l'image, la note, les avis et l'URL vers les sélecteurs actuels, et attendez-vous à ce que ces sélecteurs dérivent.
  • Restez sur les données publiques. Respectez les conditions et le robots.txt d'Amazon, préférez les API officielles pour le volume ou l'usage commercial, et ne touchez jamais aux connexions, aux données personnelles ou à l'historique des commandes.

Foire aux questions

Pourquoi utiliser une server action Next.js plutôt qu'un fetch côté client ?

Parce que le token Crawlbase ne doit jamais atteindre le navigateur. Une server action ne s'exécute que sur le serveur, vous pouvez donc lire le token depuis process.env.CRAWLBASE_JS_TOKEN, faire l'appel à la Crawling API et parser avec Cheerio sans que rien ne soit intégré dans le JavaScript client. Le composant client appelle simplement l'action et affiche ce qui revient. Cela garde aussi Cheerio, qui est une bibliothèque Node, hors du navigateur où elle ne peut pas s'exécuter.

Pourquoi une requête simple renvoie-t-elle des données incomplètes depuis Amazon ?

Parce qu'Amazon rend les prix, les notes et des parties de chaque carte de résultat côté client avec JavaScript, et il met en défi le trafic automatisé avec des CAPTCHA et des vérifications de robot. Une requête HTTP brute peut revenir avec des champs clés manquants ou être bloquée purement et simplement. Pour obtenir une page complète vous devez la rendre derrière une IP de confiance, ce que le token JS de la Crawling API gère pour vous.

Ai-je besoin du token normal ou du token JS pour Amazon ?

Utilisez le token JS. Le token normal récupère du HTML statique, qui sur Amazon peut revenir avec des prix ou des notes manquants. Le token JS rend la page dans un vrai navigateur avant de restituer le HTML, de sorte que les champs de résultats sont présents quand Cheerio les parse.

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

Très probablement le balisage d'Amazon. Ses cartes s-search-result, blocs a-price et spans a-offscreen changent sans préavis et varient selon la région et le type de requête, 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.

En quoi cela diffère-t-il de l'approche script Python ou Node simple ?

Les données et l'appel à la Crawling API sont les mêmes ; le cadre est full-stack. Ici le fetch et le parsing se trouvent dans une server action Next.js, et une grille React affiche les résultats dans une interface navigateur avec le token sécurisé côté serveur. Si vous n'avez besoin que d'un script qui affiche du JSON, la route plus simple est de scraper les pages de recherche Amazon avec la Crawling API directement, ou de construire un web scraper avec Node.js sans le framework autour.

Puis-je scraper les données personnelles des acheteurs ou vendeurs depuis Amazon ?

Non, et ce guide ne couvre pas ça. Les données de compte, l'historique des commandes et les messages privés se trouvent derrière une connexion, ce ne sont donc pas des données publiques. Scraper du contenu derrière une connexion, des données personnelles ou contourner l'authentification ou un CAPTCHA pour y accéder est hors du périmètre de ce guide et va à l'encontre des conditions d'Amazon. Pour un accès sanctionné la voie correcte est les API officielles d'Amazon ou un accord de licence.

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