G2 est l'endroit où les acheteurs de logiciels vont lire ce que de vraies personnes pensent avant de s'engager. Ses pages d'avis contiennent le type de signal que les équipes produit, commerciales et d'intelligence concurrentielle veulent à grande échelle : les notes par étoiles, les titres d'avis, le texte brut de chaque avis, le rôle ou le segment d'entreprise du rédacteur et la date de publication. Le problème est que G2 rend ces pages dynamiquement et se place derrière des défenses anti-bot de style Cloudflare, de sorte qu'une requête HTTP simple depuis Node est challengée bien avant d'atteindre un seul avis.
Ce guide vous montre comment extraire les avis G2 avec JavaScript de façon fiable. Vous construirez un petit script Node.js qui récupère une page d'avis rendue via la Crawling API, l'analyse avec cheerio et extrait un enregistrement propre par avis. Nous limitons l'ensemble du tutoriel aux données d'avis publiques, et la section sur la légalité près de la fin n'est pas du remplissage, lisez-la avant de pointer ceci sur un volume réel.
Ce que vous allez construire
Un script Node.js qui prend une URL publique de page d'avis d'un produit G2, récupère le HTML rendu via la Crawling API, et extrait une liste structurée d'avis. Nous utiliserons la page d'avis d'un produit public comme exemple fil rouge et extrairons ces champs par avis :
- Review title le court titre qu'un rédacteur donne à son avis.
- Star rating le score numérique, par exemple "4.5".
- Review text le corps de l'avis.
- Reviewer role or segment le rôle professionnel public ou l'étiquette de taille d'entreprise affiché sur l'avis.
- Date quand l'avis a été publié.
En parallèle, nous récupérerons aussi un peu de contexte au niveau de la page : le nom du produit et la moyenne des étoiles en titre. Cela donne à chaque lot d'avis un ancrage.
Pourquoi une requête simple échoue sur G2
Si vous demandez une URL d'avis G2 avec un client HTTP brut comme fetch ou axios, vous n'obtenez pas de données d'avis en retour. Deux éléments jouent contre vous. Premièrement, G2 rend une grande partie de son contenu d'avis dans le navigateur, donc le HTML brut que vous recevez est incomplet jusqu'à l'exécution des scripts de la page. Deuxièmement, et plus important, G2 utilise une protection anti-bot agressive : les IP de centres de données, les empreintes de navigateur manquantes et les schémas de requêtes ressemblant à un scraper reçoivent une page de défi ou un blocage pur et simple au lieu du contenu. Vous verrez un 403, une page interstitielle CAPTCHA ou une page d'attente "vérification de votre navigateur" plutôt que des avis.
Un scraper G2 fonctionnel a donc besoin de deux choses en une seule requête : une IP que la plateforme considère comme un vrai visiteur, et un rendu lorsque la page en a besoin. Vous pouvez essayer d'assembler cela vous-même avec un navigateur sans interface graphique et un pool de proxies résidentiels rotatifs, mais maintenir cette infrastructure en bon état contre une cible qui combat activement les bots représente l'essentiel du travail. La Crawling API regroupe les deux en un seul appel : vous lui envoyez l'URL, elle récupère la page derrière une IP résidentielle de confiance avec le traitement approprié pour la cible, et vous retourne du HTML exploitable à analyser.
Les défenses anti-bot de G2 sont plus fortes que celles d'un site typique, donc la Crawling API utilise un chemin adapté plutôt qu'une récupération générique. Si vous vous inscrivez et que vos requêtes vers G2 reviennent toujours comme des défis, contactez le support pour activer le traitement spécifique à G2 sur votre compte. Une fois activé, le code ci-dessous fonctionne sans modification.
Prérequis
Quelques éléments doivent être en place avant d'écrire du code. Aucun ne prend longtemps.
Notions de base en JavaScript et Node. Vous devez être à l'aise pour écrire et exécuter un script Node.js et installer des paquets avec npm. Si vous débutez avec la construction de scrapers dans cette pile, notre tutoriel sur la construction d'un scraper web avec Node.js est un bon point de départ.
Node.js installé. Vérifiez avec node --version. Si vous ne l'avez pas, téléchargez la version LTS depuis nodejs.org et exécutez l'installateur pour votre système d'exploitation.
Un compte Crawlbase et un token. Inscrivez-vous, ouvrez votre tableau de bord et copiez votre token de requête depuis la page de documentation du compte. Traitez le token comme un mot de passe : il authentifie vos requêtes, donc ne le committez pas dans votre système de contrôle de version ni dans aucun fichier commité.
Configurer le projet
Créez un dossier de projet vierge, initialisez-le et installez les deux bibliothèques dont le scraper a besoin : le client Crawlbase officiel et cheerio pour l'analyse.
mkdir g2-reviews-scraper cd g2-reviews-scraper npm init --yes npm install crawlbase cheerio
Deux dépendances font le travail : crawlbase est le client officiel pour la Crawling API, et cheerio vous donne une API de style jQuery pour interroger le HTML renvoyé afin d'extraire les champs individuels par sélecteur CSS. Vous n'avez pas besoin d'Express, d'une base de données ou d'un serveur web pour extraire les données ; ceux-ci appartiennent à ce que vous construisez autour du scraper, pas dans le scraper lui-même.
Étape 1 : Récupérer la page d'avis rendue
Commencez par récupérer la page. Importez la classe CrawlingAPI, initialisez-la avec votre token et demandez l'URL d'avis du produit. Vérifier le code de statut avant d'analyser permet de rendre les échecs visibles plutôt que silencieux, ce qui importe beaucoup sur une cible qui renvoie des pages de défi avec un corps 200 si vous n'êtes pas vigilant.
const { CrawlingAPI } = require("crawlbase"); const api = new CrawlingAPI({ token: "YOUR_CRAWLBASE_TOKEN" }); async function crawl(pageUrl) { const response = await api.get(pageUrl); if (response.statusCode === 200) { return response.body; } console.error(`Request failed: ${response.statusCode}`); return null; } (async () => { const pageUrl = "https://www.g2.com/products/xcode/reviews"; const html = await crawl(pageUrl); console.log(html ? html.slice(0, 500) : "No HTML returned"); })();
Sauvegardez ceci sous scraper.js et exécutez avec node scraper.js. Si tout est bien configuré, vous voyez le vrai balisage d'avis dans les 500 premiers caractères, pas une page de défi. Cette seule vérification confirme que la partie difficile, passer les défenses de G2, fonctionne avant d'écrire un seul sélecteur. Si G2 sert jamais une page qui nécessite un rendu côté client pour se remplir, ajoutez un token JavaScript et les options ajax_wait et page_wait à la requête ; pour la page d'avis standard, la récupération par défaut via l'API est généralement suffisante.
G2 combat les bots activement, donc la valeur n'est pas dans l'analyse du HTML, c'est dans l'obtention d'un HTML propre du tout. La Crawling API récupère la page derrière des IP résidentielles rotatives avec un traitement spécifique à G2, absorbe les défis et les CAPTCHA, et vous remet le balisage, pour que vous évitiez de gérer une flotte sans interface et un pool de proxies. Testez-la sur une page d'avis publique avec le niveau gratuit.
Étape 2 : Analyser les avis avec cheerio
Le HTML exploitable en main, chargez-le dans cheerio et parcourez la liste d'avis. G2 présente chaque avis sous forme de carte répétitive, donc le schéma est : sélectionnez le contexte au niveau de la page une fois, puis itérez les éléments d'avis et extrayez les mêmes champs de chacun. Enveloppez l'extraction dans un try/catch pour qu'une carte malformée n'interrompe pas toute l'exécution.
const cheerio = require("cheerio"); function parseReviews(html) { try { const $ = cheerio.load(html); const data = { productName: $(".product-head [itemprop=name]").text().trim(), averageStars: $("#products-dropdown .fw-semibold").first().text().trim(), reviews: [], }; $(".nested-ajax-loading > div.paper").each((_, el) => { const card = $(el); const title = card.find("[itemprop=name]").first().text().trim(); const stars = card.find("[itemprop='ratingValue']").attr("content"); const text = card.find(".pjax").text().trim(); const role = card.find("[ue=tooltip]") .map((_, label) => $(label).text().trim()) .get() .join(", "); const date = card.find(".x-current-review-date").text().trim(); data.reviews.push({ title, stars, text, role, date }); }); return data; } catch (error) { console.error("Parse error:", error.message); return null; } }
Quelques points méritent d'être soulignés. La note par étoiles est lue depuis l'attribut content de l'élément ratingValue plutôt que depuis son texte visible, car G2 y expose proprement le score numérique. Le rôle ou segment du rédacteur est extrait des étiquettes tooltip que G2 attache à chaque carte, joints en une seule chaîne, puisqu'un avis peut porter plus d'une étiquette publique, par exemple un rôle professionnel plus une tranche de taille d'entreprise. Tout est supprimé des espaces pour ne pas stocker des avis rembourrés de blancs.
Les noms de classes et le balisage de G2 changent sans préavis. Traitez les sélecteurs ci-dessus comme un modèle de départ, non comme un contrat. Quand un champ revient vide sur tous les avis, 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 : Assembler le tout
Reliez maintenant la récupération et l'analyse en un seul script exécutable. Récupérez le HTML rendu, transmettez-le à l'analyseur et affichez le résultat structuré. Voici le scraper complet en un seul fichier.
const { CrawlingAPI } = require("crawlbase"); const cheerio = require("cheerio"); const api = new CrawlingAPI({ token: "YOUR_CRAWLBASE_TOKEN" }); async function crawl(pageUrl) { const response = await api.get(pageUrl); if (response.statusCode === 200) { return response.body; } console.error(`Request failed: ${response.statusCode}`); return null; } function parseReviews(html) { const $ = cheerio.load(html); const data = { productName: $(".product-head [itemprop=name]").text().trim(), averageStars: $("#products-dropdown .fw-semibold").first().text().trim(), reviews: [], }; $(".nested-ajax-loading > div.paper").each((_, el) => { const card = $(el); data.reviews.push({ title: card.find("[itemprop=name]").first().text().trim(), stars: card.find("[itemprop='ratingValue']").attr("content"), text: card.find(".pjax").text().trim(), role: card.find("[ue=tooltip]") .map((_, label) => $(label).text().trim()).get().join(", "), date: card.find(".x-current-review-date").text().trim(), }); }); return data; } (async () => { const pageUrl = "https://www.g2.com/products/xcode/reviews"; const html = await crawl(pageUrl); if (!html) return; const data = parseReviews(html); console.log(JSON.stringify(data, null, 2)); })();
À quoi ressemble la sortie
Exécutez le script complet avec node scraper.js et vous obtenez un objet structuré propre : le produit, sa note moyenne et un tableau d'avis, chacun prêt à écrire en JSON, CSV ou dans une base de données.
{ "productName": "Xcode", "averageStars": "4.5", "reviews": [ { "title": "Solid IDE for native Apple development", "stars": "5", "text": "The integration with the Apple toolchain is seamless...", "role": "Software Engineer, Small-Business", "date": "Aug 12, 2025" } ] }
Mise à l'échelle sur plusieurs pages d'avis
Une page est une démonstration ; un vrai travail s'exécute sur chaque page d'avis d'un produit, et souvent sur plusieurs produits. G2 pagine ses avis, donc la page souhaitée est accessible en ajoutant un numéro de page à l'URL des avis. La forme reste la même : construisez l'URL de la page, récupérez-la via la Crawling API, analysez-la avec la même fonction et collectez les lignes jusqu'à ce qu'une page revienne vide.
function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } async function scrapeAllPages(productSlug, maxPages) { const base = `https://www.g2.com/products/${productSlug}/reviews`; const all = []; for (let page = 1; page <= maxPages; page++) { const url = page === 1 ? base : `${base}?page=${page}`; const html = await crawl(url); if (!html) break; const { reviews } = parseReviews(html); if (!reviews.length) break; all.push(...reviews); await sleep(2000); } return all; }
Deux détails maintiennent cela sain. La boucle s'arrête dès qu'une page ne retourne aucun avis, vous n'envoyez donc pas de requêtes au-delà de la fin de la liste. Et l'appel sleep entre les requêtes pace l'exécution ; bombarder G2 dans une boucle serrée est le moyen le plus rapide d'être limité même avec une API gérée devant vous. Deux secondes est un plancher raisonnable. Si vous extrayez de nombreux produits, le Crawler asynchrone vous permet d'envoyer des URL et de collecter les résultats via webhook plutôt que de bloquer sur chaque récupération.
Rester non bloqué
Même avec la Crawling API absorbant la plupart des défenses de G2, quelques habitudes maintiennent une longue exécution saine, et elles s'appliquent à toute cible commerciale difficile.
- Pacez vos requêtes. Répartissez les requêtes avec un délai entre les pages plutôt que de les envoyer aussi vite que la boucle le permet. Régulier et lent réussit ; rapide et gourmand se fait challenger.
- 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 gère cela pour vous ; si vous construisez jamais votre propre infrastructure, c'est la partie à bien faire.
- Lisez les codes de statut. Une exécution qui commence à renvoyer des 403 ou des pages de défi vous indique que le taux actuel est trop élevé. Reculez et ralentissez plutôt que de réessayer plus fort.
Pour le guide plus complet, voir comment contourner Cloudflare et éviter la détection de bots et la plongée en profondeur sur comment contourner les CAPTCHA lors du scraping web. Si vous préférez router votre propre trafic Node via un pool rotatif plutôt qu'utiliser l'API gérée, le Smart AI Proxy vous offre la même rotation d'IP résidentielles comme endpoint proxy transparent. Et si les avis sur d'autres sites sont votre prochaine étape, notre guide sur l'extraction d'avis clients couvre le schéma général.
Est-il légal de scraper G2 ?
La légalité du scraping de G2 dépend des conditions d'utilisation de G2, de votre juridiction et de ce que vous faites des données. Les conditions de G2 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 ne fait que rendre la partie technique fonctionnelle. Lisez les Conditions d'utilisation de G2 et son robots.txt, et traitez les deux comme la frontière de ce que vous collectez.
Quelques lignes à respecter. Collectez uniquement les données d'avis affichées publiquement : le titre de l'avis, la note par étoiles, le corps de l'avis, l'étiquette de rôle ou de segment public et la date que tout le monde peut voir sur une page d'avis publique sans se connecter. Respectez les attentes déclarées de G2 et gardez votre volume de requêtes assez bas pour ne pas surcharger ses serveurs. Ne collectez pas les données personnelles ou de contact des rédacteurs au-delà de ce qui est affiché publiquement, et n'essayez pas d'enrichir un avis public avec une identité privée.
Ce guide est délibérément limité aux pages d'avis publiques sans connexion parce que c'est la ligne qui rend le travail défendable. Il ne couvre rien derrière une connexion, ni les données protégées par un compte G2 ou un niveau payant, ni les informations personnelles ou de contact des rédacteurs au-delà de ce qui est public, ni toute tentative de contourner l'authentification ou les protections de G2 pour atteindre du contenu payant. G2 utilise des défenses anti-bot robustes pour une raison ; la bonne posture est de ne lire que ce qu'il montre au public, à un rythme poli. Si votre projet nécessite plus que des données d'avis publiques, un accord de données officiel est le chemin correct, pas un scraper plus ingénieux.
Points clés
- G2 bloque les requêtes simples. Ses défenses de style Cloudflare servent des défis et des 403 aux clients HTTP bruts, donc obtenir un HTML propre en retour est la partie difficile, pas l'analyse.
- La Crawling API fait le gros du travail. Elle récupère la page derrière des IP résidentielles rotatives avec un traitement spécifique à G2 en un seul appel, pour que vous évitiez de gérer une flotte sans interface et un pool de proxies.
- cheerio effectue l'extraction. Itérez les cartes d'avis et associez le titre, les étoiles, le texte, le rôle ou segment public et la date aux sélecteurs actuels, en anticipant leur dérive.
- Mise à l'échelle par boucle sur les pages. Ajoutez un numéro de page, récupérez, analysez et pacez chaque requête avec un délai pour qu'une longue exécution ne déclenche pas de limitation.
- Restez sur des données publiques. Respectez les CGU et le robots.txt de G2, collectez uniquement les champs d'avis affichés publiquement, et ne touchez jamais aux connexions, aux données payantes ni aux informations personnelles des rédacteurs.
Foire aux questions
Pourquoi une requête simple ne retourne-t-elle aucun avis depuis G2 ?
Parce que G2 utilise une protection anti-bot agressive et rend une partie de son contenu d'avis côté client. Une requête HTTP brute depuis Node atteint une page de défi, un CAPTCHA ou un 403 bien avant d'atteindre le moindre balisage d'avis. Pour obtenir de vraies données, vous devez récupérer la page derrière une IP que G2 considère comme un vrai visiteur, avec un rendu quand la page en a besoin, ce que la Crawling API gère pour vous.
Ai-je besoin d'une configuration spéciale pour G2 spécifiquement ?
Oui. Les défenses de G2 sont plus fortes que celles d'un site typique, donc la Crawling API utilise un chemin adapté pour lui. Si vous vous inscrivez et que vos requêtes G2 reviennent toujours comme des défis, contactez le support pour activer le traitement spécifique à G2 sur votre compte. Une fois activé, le code de ce guide fonctionne sans modification.
Comment gérer la pagination sur les pages d'avis G2 ?
G2 pagine les avis, donc la page suivante est accessible en ajoutant un numéro de page à l'URL des avis, par exemple ?page=2. Bouclez depuis la page un vers le haut, récupérez et analysez chaque page avec la même fonction, et arrêtez dès qu'une page ne retourne aucun avis. Mettez un délai entre les requêtes pour que l'exécution ne soit pas limitée.
Mes sélecteurs retournent des chaînes vides. Qu'est-ce qui a changé ?
Presque certainement le balisage de G2. Ses noms de classes et sa structure de cartes changent sans préavis, donc des sélecteurs qui fonctionnaient le mois dernier peuvent se casser. Ré-inspectez une page d'avis 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, pas le signe que l'approche est mauvaise.
Puis-je scraper les noms, emails ou autres données personnelles des rédacteurs depuis G2 ?
Non, et ce guide ne le couvre pas. Limitez votre collecte aux champs d'avis affichés publiquement : le titre, la note par étoiles, le texte de l'avis, l'étiquette de rôle ou de segment public et la date. Les données personnelles ou de contact des rédacteurs au-delà de ce qui est affiché publiquement, tout ce qui se trouve derrière une connexion, et toute tentative de contourner l'authentification sont hors du périmètre de ce guide et vont à l'encontre des conditions de G2. Pour plus que des données d'avis publiques, le bon chemin est un accord de données officiel.
Dans quelle base de données dois-je stocker les avis ?
Celle qui convient à votre pile. Le scraper retourne des objets JSON simples, donc ils s'insèrent proprement dans PostgreSQL, MySQL, MongoDB, un store cloud ou même un fichier JSON ou CSV plat pour une petite exécution. L'extraction est délibérément découplée du stockage pour que vous puissiez choisir plus tard sans toucher à l'analyseur.
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.
