← Tous les articles

Comment Trouver l'API JSON Cachée Derrière un Site Web en JavaScript

Vous téléchargez une page produit avec requests, vous affichez le HTML, et le prix n’y est pas. Ni le titre, ni la note, ni le stock. La page s’affichait pourtant très bien dans votre navigateur il y a une seconde. Alors, où sont passées les données ?

Elles sont parties dans une seconde requête. Les sites modernes envoient une coquille HTML presque vide, puis récupèrent le vrai contenu au format JSON depuis une API interne et le dessinent avec JavaScript. Votre client HTTP s’arrête après la première étape. Le navigateur, lui, continue.

Bonne nouvelle : cette API interne est généralement accessible directement. Si vous la trouvez, vous contournez tout le problème du rendu. Pas de navigateur headless, pas d’attente du DOM, pas d’analyse de HTML fragile. Vous obtenez un JSON propre, souvent mieux structuré que n’importe quoi sur la page. Ce guide vous montre comment la trouver, comment reproduire la requête, et quoi faire quand le site résiste.

Pourquoi les Données ne Sont Pas dans le HTML

La plupart des sites interactifs sont des applications monopages construites avec React, Vue, Angular ou un framework comme Next.js ou Nuxt. Quand vous chargez la page, le serveur renvoie un squelette. Ensuite, le code côté client s’exécute dans le navigateur et appelle un ou plusieurs endpoints du backend pour obtenir les vraies données.

Vous pouvez le confirmer en deux secondes. Clic droit sur la page et choisissez « Afficher le code source de la page » (pas « Inspecter »). Cela montre le HTML brut que recevrait votre client HTTP. Si vous voyez un <div id="root"></div> vide, un mur de balises <script> ou un message vous demandant d’activer JavaScript, le contenu est chargé après. Les données voulues vivent derrière un appel d’API, pas dans ce document.

Ces données proviennent de trois endroits courants :

  • Des appels XHR/Fetch vers un endpoint JSON ou GraphQL une fois la page chargée.
  • Du JSON intégré dans le HTML initial, souvent dans un bloc <script id="__NEXT_DATA__" type="application/json"> ou une affectation window.__INITIAL_STATE__ = {...}.
  • Un mélange : une partie des données intégrée, le reste récupéré au fil du défilement ou des clics.

Votre travail consiste à déterminer à quel cas vous avez affaire, puis à prendre les données à la source plutôt que sur la page rendue.

Étape 1 : Ouvrez l’Onglet Network et Filtrez par Fetch/XHR

Ouvrez la page dans Chrome ou Firefox, ouvrez les DevTools (F12) et allez dans l’onglet Network (Réseau). Rechargez la page avec l’onglet ouvert pour tout capturer depuis le début.

Vous verrez des dizaines d’entrées : images, polices, CSS, pixels de suivi. Ignorez-les. Cliquez sur le filtre Fetch/XHR pour n’afficher que les requêtes que JavaScript a faites en arrière-plan. C’est là que vivent les appels d’API.

Maintenant, interagissez avec la page comme le ferait un utilisateur. Faites défiler, cliquez sur « charger plus », ouvrez un produit, changez un filtre. Regardez de nouvelles lignes apparaître dans l’onglet Network pendant que vous le faites. Chaque ligne est une requête que le site a faite pour vous. L’une d’elles transporte vos données.

Pour trouver la bonne, cliquez sur une requête et regardez l’onglet Response (Réponse) ou Preview (Aperçu). Vous cherchez une réponse contenant les valeurs vues sur la page : le prix, la liste des articles, le texte des avis. Quand vous voyez du JSON avec vos champs dedans, vous avez trouvé l’endpoint.

Quelques astuces qui font gagner du temps :

  • Triez par taille de réponse. Les endpoints de données sont généralement plus gros que les pings et les appels de configuration.
  • Tapez une valeur connue dans le champ de filtre de Network (un nom de produit, un prix). Chrome peut chercher dans les corps de réponse avec le panneau de recherche (Ctrl+Maj+F dans les DevTools).
  • Regardez le nom et le chemin de la requête. Des endpoints comme /api/v2/products, /graphql ou /_next/data/...json sont des signaux forts.

Étape 2 : Lisez la Requête Avant de la Copier

Une fois l’endpoint trouvé, cliquez dessus et étudiez la requête elle-même, pas seulement la réponse. Vous devez la reproduire assez fidèlement pour obtenir la même réponse.

Vérifiez ces éléments dans l’onglet Headers (En-têtes) :

  • Méthode et URL. Est-ce GET ou POST ? Notez chaque paramètre de requête. Des paramètres comme page, limit, offset, cursor et sort sont vos commandes pour la pagination et le tri.
  • En-têtes de requête. Beaucoup d’API vérifient des en-têtes que le navigateur envoie automatiquement. Les plus courants qui comptent : Accept: application/json, un Referer, un X-Requested-With, et parfois un en-tête personnalisé comme X-Api-Key ou X-Client-Version.
  • Corps de la requête. Pour les appels POST et GraphQL, le corps contient la requête et les variables. Copiez-le tel quel pour commencer.
  • Cookies et jetons. Certains endpoints ont besoin d’un cookie de session ou d’un jeton bearer que le site a émis au chargement de la page.

Le moyen le plus rapide d’obtenir une base fonctionnelle est « Copier comme cURL ». Clic droit sur la requête, choisissez Copier > Copier comme cURL, et collez-la dans votre terminal. Si elle renvoie le même JSON, vous avez une reproduction fidèle. À partir de là, vous pouvez la réduire.

Étape 3 : Reproduisez-la en Code et Élaguez le Superflu

Partez de la requête complète copiée, vérifiez qu’elle fonctionne, puis retirez les en-têtes un par un jusqu’à ce que ça casse. Ce qui reste est le minimum dont vous avez vraiment besoin. Cela garde votre scraper simple et moins fragile.

Voici un exemple minimal en Python appelant un endpoint JSON typique :

import requests

url = "https://example.com/api/v2/products"
params = {"category": "shoes", "page": 1, "limit": 48}
headers = {
    "Accept": "application/json",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
    "Referer": "https://example.com/category/shoes",
}

resp = requests.get(url, params=params, headers=headers, timeout=20)
data = resp.json()

for item in data["products"]:
    print(item["title"], item["price"])

Pour un endpoint GraphQL, envoyez un POST avec la requête et les variables copiées :

import requests

payload = {
    "query": "query Products($page:Int!){ products(page:$page){ title price } }",
    "variables": {"page": 1},
}
resp = requests.post("https://example.com/graphql", json=payload, timeout=20)
print(resp.json()["data"]["products"])

En Node avec fetch, cela paraît presque identique :

const res = await fetch("https://example.com/api/v2/products?page=1&limit=48", {
  headers: { Accept: "application/json", Referer: "https://example.com/category/shoes" },
});
const data = await res.json();
data.products.forEach((p) => console.log(p.title, p.price));

Étape 4 : Gérez la Pagination Depuis l’API, Pas Depuis la Page

C’est là que l’accès direct à l’API paie. La page peut afficher un bouton « Charger plus » ou un défilement infini, mais l’API expose presque toujours une commande de pagination propre. Regardez comment les paramètres changent entre la première et la deuxième requête dans l’onglet Network.

Vous verrez généralement l’un de ces trois schémas :

  • Numéros de page : ?page=1, ?page=2. Itérez jusqu’à obtenir une liste vide.
  • Offset et limit : ?offset=0&limit=48, puis ?offset=48. Incrémentez de la valeur de la limite.
  • Basé sur un curseur : chaque réponse inclut un jeton nextCursor ou endCursor que vous passez à la requête suivante. Suivez-le jusqu’à ce qu’il soit nul.

La pagination par curseur est fréquente sur les grands flux et la plus fiable des trois. Elle contourne aussi souvent les limites de pagination profonde qui cassent les crawlers basés sur les numéros de page sur les gros catalogues.

Étape 5 : Quand le JSON Intégré Suffit

Parfois, vous n’avez même pas besoin d’une seconde requête. Les sites à framework intègrent souvent le jeu de données complet dans la première réponse HTML. Regardez le code source de la page et cherchez __NEXT_DATA__, __NUXT__, __INITIAL_STATE__ ou application/ld+json. Si vos données y sont, analysez le HTML une fois, extrayez le JSON de cette balise script, et c’est terminé. Aucun rejeu d’API nécessaire.

import json, re, requests

html = requests.get("https://example.com/product/123").text
match = re.search(r'<script id="__NEXT_DATA__"[^>]*>(.*?)</script>', html, re.S)
state = json.loads(match.group(1))
print(state["props"]["pageProps"]["product"]["price"])

C’est rapide et stable, car vous lisez les mêmes données que le framework a utilisées pour construire la page. Les données structurées en application/ld+json sont particulièrement pratiques pour les produits, les articles et les avis.

Quand l’API Résiste

Tous les endpoints ne livrent pas leurs données à un simple script. Les mêmes couches anti-bot qui protègent la page HTML se placent souvent aussi devant l’API. Les signes que vous en avez rencontré une :

  • Un 403 ou 429 alors que votre navigateur charge l’endpoint sans souci.
  • Un corps HTML avec un défi ou un CAPTCHA au lieu de JSON.
  • Un jeton à courte durée de vie, un paramètre signé ou un horodatage qui expire en quelques secondes.
  • Une réponse 200 qui renvoie une charge utile vide ou leurre. Vérifiez toujours la forme du JSON, pas seulement le code de statut.

Vous pouvez résoudre une partie de cela vous-même. Faites tourner un User-Agent réaliste, envoyez les en-têtes que le navigateur envoie, et réutilisez un cookie de session capturé une fois plutôt que d’en chauffer un nouveau à chaque appel. Une bibliothèque comme curl_cffi aide quand le blocage repose sur votre handshake TLS et non sur vos en-têtes, car elle imite l’empreinte d’un vrai navigateur.

Mais quand un endpoint exige un jeton signé généré par du JavaScript côté client obfusqué, ou que tout le domaine est derrière un fournisseur anti-bot agressif, reproduire la requête à la main devient un jeu perdu de rétro-ingénierie qui casse à chaque nouvelle version du site. C’est le moment où une API de scraping gagne sa place : vous envoyez l’URL cible, elle gère le rendu du navigateur, l’empreinte et la rotation des proxys, et vous recevez la réponse. ScrapeUnblocker est conçu exactement pour ce cas, et ses endpoints analysés peuvent vous rendre du JSON structuré pour que vous évitiez aussi l’étape d’analyse du HTML.

FAQ

Comment savoir si un site utilise une API cachée ? Regardez le code source brut de la page. Si les valeurs voulues manquent et que vous voyez un conteneur vide ou un avis « activez JavaScript », les données sont récupérées séparément. Confirmez en observant l’onglet Fetch/XHR dans les DevTools pendant le chargement de la page.

Est-il légal d’appeler l’API interne d’un site ? Vous appelez le même endpoint que votre navigateur, c’est donc une requête publique. Cela dit, respectez les conditions d’utilisation du site, les consignes robots et les limites de débit, et ne collectez que des données publiquement visibles. Le cadre légal dépend de la juridiction et de l’usage, considérez donc ceci comme une réponse d’ingénierie, pas un conseil juridique.

Pourquoi utiliser l’API plutôt qu’un navigateur headless ? Vitesse et stabilité. Un appel d’API prend quelques millisecondes et renvoie des données propres et typées. Un navigateur headless lance un rendu complet de la page à chaque requête et vous donne du HTML qu’il faut encore analyser. Utilisez l’API quand vous le pouvez, et ne revenez au rendu que lorsque c’est indispensable.

L’API a besoin d’un jeton que je ne peux pas générer. Et maintenant ? Si le jeton provient de JavaScript obfusqué, capturez un chargement de page frais pour lire le jeton actuel, ou rendez la page une fois pour l’obtenir et réutilisez la session. Si c’est trop fragile à maintenir, faites passer la requête par une API de scraping qui rend la page et vous renvoie le résultat.

Pour Conclure

La page rendue est la surface lente et fragile d’un site web. En dessous se trouve un tuyau de données propre que le site a construit pour son propre frontend. Apprendre à lire l’onglet Network, à reproduire la requête et à suivre la pagination transforme la plupart des sites « chargés de JavaScript, impossibles à scraper » en un simple appel JSON.

Commencez par Afficher le code source et le filtre Fetch/XHR sur votre prochaine cible. Quand vous tombez sur un endpoint verrouillé derrière de sérieuses défenses anti-bot, c’est le moment de recourir à un outil comme ScrapeUnblocker plutôt que de lutter contre l’empreinte à la main.

Essayez ScrapeUnblocker gratuitement

Taux de réussite de plus de 95 % · à partir de 0,55 € pour 1 000 appels · 500 requêtes gratuites à l'inscription.

Essayer gratuitement → Voir les tarifs