Le rendu JavaScript dans le web scraping : quand vous en avez besoin et ce que ça coûte
Comment savoir si une page a besoin d'un vrai navigateur plutôt qu'un fetch, pourquoi le rendu coûte plus cher partout, et les multiplicateurs de crédits.

Un simple fetch HTTP vous donne le HTML que le serveur a envoyé. De plus en plus, ce n’est pas la page qu’un visiteur voit. L’écart entre les deux, c’est le rendu JavaScript, et c’est la principale raison pour laquelle un scraper qui fonctionne sur un site échoue silencieusement sur le suivant.
Comment savoir si une page a besoin d’être rendue ?
Deux vérifications, rapides toutes les deux, avant d’écrire le moindre code de scraping :
Comparer le view-source au DOM. Dans un navigateur, le view-source (Ctrl+U ou Cmd+Option+U) montre exactement ce qu’un simple fetch recevrait : le HTML brut du serveur, avant qu’aucun script ne s’exécute. Maintenant, ouvrez les outils de développement et regardez le panneau Elements, qui montre le DOM après l’exécution du JavaScript. Si le contenu que vous voulez, prix, annonces, avis, est présent dans Elements mais absent ou remplacé par un squelette de chargement dans le view-source, la page construit ce contenu côté client.
Le récupérer vous-même sans navigateur. La même vérification depuis du code, sans outils de développement :
import requests
resp = requests.get("https://example.com/products", timeout=30)
print(len(resp.text))
print("add-to-cart" in resp.text) # remplacez par une chaîne que vous savez présente dans le vrai contenu
Si une chaîne repère que vous voyez sur la page en direct est absente de resp.text, un simple fetch ne vous donne pas le contenu, et vous avez besoin de quelque chose qui exécute le JavaScript avant de lire la page.
Une raison rapide pour laquelle ça arrive plus qu’avant : les frameworks modernes (React, Vue, Svelte et compagnie) livrent une coquille HTML quasi vide et construisent la page réelle dans le navigateur. C’est un choix d’architecture délibéré pour le site, pas une mesure anti-scraping, mais ça produit le même résultat pour vous dans les deux cas.
Pourquoi le rendu coûte-t-il plus cher, partout ?
Un simple fetch, c’est un socket, une requête, une réponse. Le rendu signifie faire tourner quelque chose de proche d’un navigateur complet : charger le DOM, exécuter les scripts, attendre que les appels réseau se stabilisent, parfois faire défiler pour déclencher du contenu en chargement paresseux. C’est du vrai CPU et de la vraie mémoire par page, maintenus ouverts pendant la durée du rendu, pas les microsecondes que prend un fetch statique.
Cette structure de coût n’est spécifique à aucun fournisseur en particulier. Chaque fournisseur qui propose à la fois un fetch statique et un fetch rendu facture le rendu plus cher, parce que c’est une infrastructure réellement plus coûteuse à faire tourner à l’échelle : un pool de vrais processus navigateur au lieu d’un pool de connexions. Si un devis pour du scraping rendu semble au même prix que du statique, regardez de près ce que « rendu » signifie dans leur documentation.
Ce que coûte le rendu sur FastAF
/scrape a quatre niveaux de tarification, et le multiplicateur suit le coût de ce qui tourne réellement derrière la requête :
| Mode | Paramètre | Crédits |
|---|---|---|
| Fetch statique | (par défaut) | 1 |
| Rendu JS | dynamic=true |
5 |
| Proxies premium, sans rendu | premium=true |
10 |
| Rendu JS + proxies premium | dynamic=true&premium=true |
25 |
Le statique fait un bond de 5x pour ajouter le rendu, et un bond de 25x pour ajouter à la fois le rendu et le routage proxy premium. C’est le coût réel de l’infrastructure supplémentaire, pas une majoration arbitraire, ce qui explique pourquoi ça vaut la peine de vérifier si vous avez réellement besoin du rendu avant d’y recourir par défaut.
La stratégie : essayer le statique d’abord, escalader seulement en cas d’échec
La plupart des jobs de scraping mélangent des pages qui ont besoin de rendu et d’autres non, même au sein du même site. Payer dynamic=true sur chaque requête alors que seules certaines pages en ont besoin est la façon la plus courante de surpayer sur cet endpoint :
import requests
API_KEY = "faf_live_..." # votre clé FastAF
def scrape(url, dynamic=False, premium=False, wait=None):
params = {"url": url}
if dynamic:
params["dynamic"] = "true"
if premium:
params["premium"] = "true"
if wait:
params["wait"] = wait
resp = requests.get(
"https://api.fastaf.co/v1/scrape",
params=params,
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=90,
)
resp.raise_for_status()
return resp.text
def scrape_smart(url, marker):
html = scrape(url)
if marker in html:
return html # le statique a suffi, 1 crédit dépensé
html = scrape(url, dynamic=True) # escalade, 5 crédits dépensés
return html
marker est une chaîne dont vous savez qu’elle apparaît dans le vrai contenu, un titre de produit, un format de prix, n’importe quoi qui serait absent d’une page coquille. Si le fetch statique l’a déjà, vous avez économisé 4 crédits sur cette URL. Sinon, vous escaladez une fois, pas sur un pari.
Réservez premium=true séparément : c’est une question de qualité de proxy et de contournement des blocages basés sur l’IP, pas de JavaScript. Un site peut avoir besoin de l’un, des deux, ou d’aucun. wait (en millisecondes) vaut la peine d’être réglé explicitement sur les requêtes dynamic=true pour les pages qui chargent du contenu après qu’un appel API se termine, plutôt que de supposer que l’attente par défaut suffit.
En bref
Comparez le view-source au DOM rendu, ou récupérez la page vous-même, avant de supposer que vous avez besoin d’un navigateur. Le statique coûte 1 crédit, le rendu 5, les proxies premium 10, les deux ensemble 25 : les multiplicateurs existent parce que la vraie infrastructure navigateur coûte réellement plus cher à faire tourner. Essayez le statique d’abord et escaladez vers dynamic=true seulement sur les URL où le contenu repère est réellement absent, et vous ne paierez la prime du rendu que là où elle est méritée.