← Tous les articles

Comment Extraire les Données d'Engagement TikTok et Instagram en JSON

Si tu as déjà essayé d’extraire une vidéo TikTok ou une publication Instagram avec une simple requête HTTP, tu connais déjà les deux problèmes. La page revient presque vide, et les chiffres que tu vois sont arrondis à des valeurs comme “1,2 M de vues”. Pour l’écoute sociale, la vérification d’influenceurs ou le reporting de campagne, “1,2 M” ne suffit pas. Il te faut le nombre entier exact.

Ce guide explique pourquoi ces deux sites sont difficiles à scraper, où vivent réellement les chiffres au sein de la page et comment extraire des données d’engagement exactes en JSON structuré. Tout ce qui suit est reproductible avec des outils open source, et à la fin nous abordons le raccourci pour les équipes qui préféreraient ne pas entretenir toute cette plomberie.

Pourquoi TikTok et Instagram Résistent

Les deux plateformes sont des applications monopages. Le HTML que reçoit ta première requête est une coquille : quelques balises meta, un titre et un paquet de JavaScript. Le contenu que tu vois dans un vrai navigateur est construit après le chargement de la page, quand ce JavaScript s’exécute et hydrate le DOM avec les données.

Cela a deux conséquences pour le scraping :

  • Une requête simple ne renvoie presque rien. Des outils comme requests ou un fetch nu n’exécutent jamais le JavaScript, donc le texte visible - descriptions, compteurs, noms d’utilisateur - n’est tout simplement pas dans le corps de la réponse. Tu obtiens un titre de page et guère plus.
  • Les chiffres visibles sont pour les humains, pas pour les machines. Quand la page se rend enfin, elle peint des compteurs abrégés : “1,2 M”, “34,5 k”, “980”. Ces chaînes sont avec perte. Tu ne peux pas retrouver la valeur exacte à partir de “1,2 M”, et les seuils d’arrondi bougent avec le temps.

En plus, les deux sites appliquent des contrôles anti-bot, des limites de débit et des murs de connexion, si bien qu’un scraping naïf est vite ralenti ou bloqué.

Où les Vrais Chiffres Vivent Réellement

Voici la bonne nouvelle. Même si le texte visible est arrondi, les entiers exacts sont presque toujours présents dans la page, simplement pas là où tu regardes. Les SPA modernes livrent une charge utile JSON intégrée pour que l’application s’hydrate instantanément. Cette charge utile porte les données précises.

  • TikTok intègre un gros bloc JSON dans une balise script, historiquement SIGI_STATE et plus récemment __UNIVERSAL_DATA_FOR_REHYDRATION__. À l’intérieur, tu trouveras des champs comme playCount, diggCount (likes), commentCount, shareCount et collectCount (enregistrements) sous forme de nombres réels.
  • Instagram expose les données de publication via du JSON intégré et ses réponses GraphQL internes. Un objet de publication inclut généralement edge_media_preview_like.count, edge_media_to_comment.count, le username du propriétaire et taken_at_timestamp.

L’astuce est d’arrêter de scraper le texte rendu et de commencer à lire la charge utile intégrée. C’est là que “1,2 M” devient 1203481.

Extraire le JSON Intégré Toi-Même

Tu dois quand même rendre la page, ou au moins franchir la couche anti-bot, avant de pouvoir lire cette balise script. Un navigateur headless gère les deux. Playwright est un bon choix par défaut car il pilote un vrai build Chromium et te laisse attendre que la charge utile apparaisse.

import json
from playwright.sync_api import sync_playwright

def scrape_tiktok(url: str) -> dict:
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        page.goto(url, wait_until="networkidle")

        # Lis la charge d'hydratation intégrée plutôt que le texte rendu
        raw = page.locator(
            "script#__UNIVERSAL_DATA_FOR_REHYDRATION__"
        ).inner_text()
        browser.close()

    data = json.loads(raw)
    scope = data["__DEFAULT_SCOPE__"]["webapp.video-detail"]
    stats = scope["itemInfo"]["itemStruct"]["stats"]
    return {
        "plays": int(stats["playCount"]),
        "likes": int(stats["diggCount"]),
        "comments": int(stats["commentCount"]),
        "shares": int(stats["shareCount"]),
        "saves": int(stats["collectCount"]),
    }

Le chemin de clés exact se déplace avec le temps, traite-le donc comme quelque chose que tu devras entretenir. Un motif plus résistant consiste à charger le JSON et à le parcourir à la recherche de l’objet stats au lieu de coder en dur le chemin complet.

Pour Instagram, la même idée s’applique, mais tu obtiens souvent les données les plus propres en interceptant la réponse GraphQL que fait l’application, plutôt qu’en analysant une balise script statique :

from playwright.sync_api import sync_playwright

def scrape_instagram(url: str) -> dict:
    result = {}

    def on_response(response):
        if "graphql/query" in response.url and response.status == 200:
            try:
                media = response.json()["data"]["xdt_shortcode_media"]
            except Exception:
                return
            result.update({
                "likes": media["edge_media_preview_like"]["count"],
                "comments": media["edge_media_to_comment"]["count"],
                "author_username": media["owner"]["username"],
                "posted_at": media["taken_at_timestamp"],
            })

    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        page.on("response", on_response)
        page.goto(url, wait_until="networkidle")
        browser.close()

    return result

L’interception des réponses est puissante car elle capture la charge utile exacte que l’application elle-même utilise. Tu lis les mêmes chiffres que l’interface lit avant de les arrondir pour l’affichage.

Rester Débloqué à Grande Échelle

Une vidéo fonctionne bien depuis ton ordinateur portable. Mille vidéos par heure depuis une seule IP, non. Si tu prévois de collecter à gros volume, budgétise le problème anti-bot dès le départ :

  • Fais tourner des IP résidentielles. Les IP de centre de données sont vite signalées sur les deux plateformes. Achemine les requêtes via des proxys résidentiels rotatifs pour que chaque requête ressemble à un utilisateur ordinaire différent.
  • Régule et ajoute de la variation. Ajoute des délais aléatoires entre les requêtes. Un trafic prévisible et cadencé par la machine est l’un des signaux les plus faciles à détecter.
  • Réutilise des empreintes de navigateur réalistes. Les builds de navigateur indétectables et des en-têtes cohérents réduisent les signaux de client automatisé. Ne mélange pas un user agent mobile avec une fenêtre de bureau.
  • Gère le cas de la coquille vide. Si ton extracteur reçoit une page sans charge utile, traite cela comme un blocage doux et réessaie plus tard, au lieu d’enregistrer un zéro.

Rien de tout cela n’est exotique, mais c’est un travail continu. Les sélecteurs se déplacent, les formes GraphQL changent et le blocage s’ajuste. Cet entretien est le vrai coût du fait maison.

Le Raccourci : Demander du JSON Déjà Analysé

Si tu préfères éviter la flotte de navigateurs et l’archéologie des charges utiles, tu peux demander les données déjà analysées directement. ScrapeUnblocker gère le rendu et la couche anti-bot pour toi, et son mode de données analysées lit la charge utile intégrée à ta place afin que tu obtiennes des entiers exacts au lieu du texte arrondi que la page peint.

Avec parsed_data=true, l’URL d’une vidéo TikTok renvoie plays, likes, comments, shares et saves, et une publication Instagram renvoie des likes et comments exacts, le vrai author.username et un vrai posted_at. Tu envoies une URL, tu obtiens du JSON propre, et ce n’est pas toi qui entretiens les sélecteurs quand le balisage change.

import requests

resp = requests.get(
    "https://api.scrapeunblocker.com/getPageSource",
    params={
        "url": "https://www.tiktok.com/@user/video/1234567890",
        "parsed_data": "true",
    },
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = resp.json()
print(data["plays"], data["likes"], data["comments"])

Consulte le guide des données analysées pour la liste complète des champs et des paramètres.

FAQ

Pourquoi les compteurs que j’extrais semblent-ils arrondis ? Parce que tu lis le texte que l’interface rend pour les humains, qui est abrégé (“1,2 M”). L’entier exact vit dans la charge utile JSON intégrée ou dans la réponse GraphQL, pas dans le texte visible du DOM. Analyse la charge utile et tu obtiendras le vrai nombre.

Puis-je le faire sans navigateur headless ? Parfois. Si tu peux atteindre le JSON intégré ou un point d’accès JSON directement, une requête HTTP bien formée peut fonctionner. En pratique, les deux plateformes protègent ces réponses derrière des contrôles anti-bot, donc un vrai navigateur ou une API de scraping qui rend la page est la voie fiable.

Est-il légal de scraper TikTok et Instagram ? Le scraping de données publiquement visibles est généralement traité différemment de l’accès à du contenu privé ou protégé par connexion, mais les règles dépendent de ta juridiction, des conditions de la plateforme et de l’usage que tu fais des données. Ne collecte que des données publiques, évite les données personnelles dont tu n’as pas besoin et prends un conseil juridique pour tout usage commercial.

Comment éviter de me faire bloquer ? Fais tourner des IP résidentielles, ajoute des délais aléatoires, utilise des empreintes de navigateur réalistes et réessaie les blocages doux au lieu d’enregistrer des zéros. À gros volume, une API de déblocage supprime l’essentiel de ce travail car elle gère le rendu et la rotation pour toi.

Pour Conclure

La raison pour laquelle les données d’engagement social semblent difficiles à scraper est un décalage : tu lis du texte arrondi, alors que les chiffres exacts se trouvent une couche plus bas, dans une charge utile JSON intégrée. Une fois que tu lis cette charge utile plutôt que le DOM, TikTok et Instagram deviennent une source structurée de plus - vues, likes, commentaires, partages, enregistrements, noms d’utilisateur et horodatages, le tout en entiers propres.

Construis-le toi-même avec Playwright quand tu veux un contrôle total, ou laisse ScrapeUnblocker renvoyer le JSON analysé directement quand tu préfères consacrer ton temps à l’analyse plutôt qu’à la plomberie.

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