Scraping

Trouver l'API derrière la page : collecter depuis des points de terminaison JSON plutôt que le HTML

De nombreuses pages chargent leurs données sous forme de JSON. Comment trouver le point de terminaison qui les transporte, pourquoi il est souvent lié à la session de la page, et comment le collecter de manière responsable.

Chris Collins

Chris Collins

30 septembre 2026 · 9 min de lecture

Ouvrez une page web moderne, observez l’activité réseau, et vous verrez souvent que les données recherchées arrivent en JSON avant que la page ne les affiche. Les prix, listes ou résultats qu’un scraper extrairait laborieusement du HTML se trouvent dans une réponse propre et structurée que la page a récupérée pour elle-même.

Collecter à partir de cette réponse plutôt que de la page rendue peut être plus léger, plus stable et bien plus facile à analyser. Mais ce n’est pas aussi simple que de copier une URL, et deux choses surprennent la plupart des équipes : à quel point le JSON d’une page contient rarement les données, et à quelle fréquence l’endpoint de données refuse de fonctionner en dehors de la page qui l’a appelé. Ce guide montre comment trouver le bon endpoint, ce que nous avons mesuré sur des pages réelles, et comment collecter à partir de celui-ci sans dépasser les limites.

Points clés à retenir

  • La plupart du JSON chargé par une page ne sont pas des données. Sur la page de recherche de vols d’une compagnie aérienne, les tarifs sont arrivés dans une seule réponse de 44,9 KB, soit environ 8% du JSON de la page et environ 1,2% de son transfert total de 3,6 MB.
  • Certaines pages n’ont aucune API de données. Sur la page de prévisions d’un service météorologique national, chaque réponse JSON appartenait à l’outil de consentement aux cookies, et les prévisions se trouvaient dans le HTML.
  • Trouvez l’endpoint en recherchant dans les corps de réponse une valeur visible sur la page, et non en devinant à partir des URLs.
  • Les API de page sont souvent liées à la session de la page. L’endpoint de tarifs de la compagnie aérienne fonctionnait à l’intérieur de la page et renvoyait un HTTP 409 lorsqu’il était appelé directement.
  • N’utilisez que des endpoints publics que la page appelle pour des visiteurs anonymes, au rythme d’une personne qui navigue, et privilégiez une API officielle chaque fois qu’elle existe.

Ce que nous avons mesuré

Nous avons chargé deux pages publiques dans un vrai navigateur le 30 septembre 2026 et enregistré chaque réponse.

Recherche de vols compagnie aériennePrévisions météo
Requêtes6146
Total transféré3,62 MB2,57 MB
Réponses JSON15, 534 KB3, 1,04 MB
Réponses JSON contenant les données1, 44,9 KB0
Où se trouvaient les donnéesUn endpoint de tarifsLe HTML rendu côté serveur

Sur la page de la compagnie aérienne, les plus grosses réponses JSON n’étaient pas du tout des tarifs. Un service tiers de feature-flag a renvoyé la même réponse de 97 KB quatre fois, et un pack de traduction a ajouté 92 KB supplémentaires. Les tarifs sont arrivés dans une seule réponse provenant de la propre API de réservation de la compagnie aérienne.

Sur la page météo, les trois réponses JSON provenaient toutes de l’outil de gestion du consentement, dont une liste de fournisseurs de 860 KB, tandis que les prévisions elles-mêmes étaient rendues dans le HTML côté serveur. « Collecter à partir du JSON » n’aurait rien récupéré d’utile.

Trouver l’endpoint qui porte les données

La méthode fiable consiste à chercher, pas à deviner. Choisissez une valeur visible sur la page, comme un prix, un nom de produit ou un identifiant, chargez la page dans un vrai navigateur, et trouvez quelle réponse JSON la contient.

À la main, il s’agit des outils de développement du navigateur : ouvrez l’onglet Network, filtrez sur Fetch/XHR, rechargez, et recherchez la valeur dans les corps de réponse. En automatisé, c’est un court script :

import { chromium } from 'playwright';

// Load a page once and report which JSON responses contain a value you can see on it.
export async function findEndpoint(url, needle, waitMs = 20000) {
  const browser = await chromium.launch({ headless: true });
  const page = await browser.newPage();
  const hits = [];
  page.on('response', async (response) => {
    const type = response.request().resourceType();
    const contentType = response.headers()['content-type'] || '';
    if (!['xhr', 'fetch'].includes(type) || !contentType.includes('json')) return;
    try {
      const body = await response.text();
      if (body.includes(needle)) {
        hits.push({
          method: response.request().method(),
          status: response.status(),
          bytes: Buffer.byteLength(body),
          url: response.url(),
        });
      }
    } catch {
      // Some responses (redirects, aborted requests) have no readable body.
    }
  });
  // Analytics beacons keep many pages from ever going network-idle,
  // so wait for the DOM, then until a match appears or the time runs out.
  await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 90000 });
  for (let waited = 0; waited < waitMs && hits.length === 0; waited += 500) {
    await page.waitForTimeout(500);
  }
  await page.waitForTimeout(1000);
  await browser.close();
  return hits;
}

Sur la page de vols de la compagnie aérienne et un tarif visible dessus, le script a renvoyé exactement une correspondance parmi 61 requêtes : la réponse de disponibilité de l’API de réservation. Notez la stratégie d’attente. Notre première version attendait que la page atteigne l’état network-idle, ce qui n’arrivait jamais, car des balises analytiques continuaient de se déclencher ; elle a expiré après 90 secondes. Attendre le DOM puis une correspondance est plus fiable.

Peut-on l’appeler directement ?

Souvent non. Lorsque nous avons interrogé directement le même endpoint de disponibilité de la compagnie aérienne, sans passer par la page, il a renvoyé HTTP 409 pour des requêtes provenant de six pays différents, alors que la page elle-même le chargeait sans problème. Les API de page dépendent souvent d’éléments que la page met en place au préalable : cookies de session, jetons intégrés dans le HTML, en-têtes de requête, ou une séquence d’appels antérieurs.

Cela laisse deux approches :

  • Laisser la page effectuer l’appel. Chargez la page dans un navigateur et lisez la réponse JSON dès son arrivée, comme le fait le script ci-dessus. Vous obtenez les données propres sans reconstruire la session, au prix de l’exécution d’un navigateur.
  • Rejouer uniquement des endpoints simples et publics. Certains endpoints n’ont besoin que d’une URL. La même compagnie aérienne publie également un endpoint de tarifs public qui répond à des requêtes simples, que nous avons utilisé dans un test séparé sur si les prix varient selon le pays de sortie. Là où un endpoint fonctionne aussi simplement, c’est de loin l’option la moins coûteuse.

Ce qu’il ne faut pas faire, c’est contourner la session : récupérer des jetons, forger des en-têtes ou rejouer des appels authentifiés pour atteindre des données que le site n’a pas mises à disposition des visiteurs anonymes. C’est là que la collecte cesse d’être de l’observation.

Pourquoi le JSON en vaut la peine quand il est disponible

Quand les données arrivent effectivement en JSON, les gains sont réels :

  • Taille. La réponse des tarifs faisait 44,9 KB contre 3,6 MB pour la page complète. Sur une collecte facturée à la bande passante, cette différence représente l’essentiel de la facture, comme le montre le coût par enregistrement propre.
  • Structure. Les champs arrivent nommés et typés, sans sélecteurs à écrire ni à maintenir.
  • Exhaustivité. Les réponses contiennent souvent plus que ce qu’affiche la page, comme des identifiants, toutes les classes tarifaires ou des indicateurs de stock.

Les compromis sont tout aussi réels. Les endpoints non documentés changent sans préavis, et une réponse qui change de forme casse silencieusement votre parseur, ce qui est exactement le problème auquel répond la surveillance de la dérive de schéma. Un numéro de version dans le chemin, comme le v4 dans l’API de réservation de la compagnie aérienne, est un léger signal de stabilité, pas une promesse.

Où cela se situe parmi les alternatives

SourceStabilitéEffortÀ utiliser quand
API officielle et documentéeLa plus élevéeLe plus faibleÀ vérifier en premier, toujours
JSON-LD ou état de page intégréÉlevéeFaibleLa page le publie, voir arrêtez d’analyser le HTML
Les propres endpoints JSON de la pageMoyenneMoyenLes données se chargent après la page, et l’endpoint est public
HTML rendu et sélecteursLa plus faibleLe plus élevéRien d’autre ne porte les données
Un modèle lisant la pageVariableFaible par site, élevé par pageDe nombreux templates, comme dans extraction par LLM contre sélecteurs

Collecter de manière responsable

Les endpoints qu’une page appelle font partie du site, et les règles du site s’appliquent toujours. N’utilisez que des endpoints que la page appelle pour des visiteurs anonymes, rythmez les requêtes comme le ferait une personne qui navigue, respectez le robots.txt et les conditions d’utilisation du site, et laissez tranquille tout ce qui se trouve derrière une connexion ou un jeton sauf si vous avez la permission. Là où un site propose une API officielle, utilisez-la ; elle est plus stable, et c’est ce que le site a accepté de prendre en charge. Les principes plus larges se trouvent dans robots.txt, opt-outs IA et signaux de réservation.

En résumé

Les données derrière une page moderne arrivent souvent en JSON, et quand c’est le cas, les collecter à cet endroit est plus léger, plus propre et plus facile à maintenir que d’analyser le HTML. Mais les trouver demande une recherche, pas une supposition : sur les pages que nous avons mesurées, le JSON utile était une réponse parmi beaucoup d’autres, et sur une page, il n’existait tout simplement pas.

Recherchez dans les corps de réponse une valeur visible, vérifiez si l’endpoint fonctionne seul, laissez la page effectuer l’appel quand ce n’est pas le cas, et restez dans les limites de ce que le site offre à tout visiteur anonyme.

Sources et références

Prêt à commencer ?

Essayez les proxies résidentiels de Shifter, 205M+ IPs, 195+ pays, à partir de 0,75 $/GB.

Commencer