SEO Strategy

Automatiser l’API Google Search Console avec Python

Automatisez Google Search Console avec Python : authentification, extractions quotidiennes, quotas, inspection d’URL et alertes de baisse de trafic.

Photo de profil de Long Nguyen

Long Nguyen

Développeur fullstack · Ingénieur IA · Chercheur

• • 5 min de lecture •

Ce que l’API Search Console peut et ne peut pas automatiser

L’API Search Console est principalement une interface de lecture pour quatre types de données : les performances, l’inspection des URL, les sitemaps et la liste des propriétés que vous possédez. Elle ne permet pas de forcer l’indexation des pages ordinaires et n’expose pas tous les rapports disponibles dans l’interface web. Avant d’écrire du code, associez chaque tâche à automatiser à l’endpoint qui la prend réellement en charge.

Tâche À utiliser Limite à anticiper
Clics, impressions, CTR et position quotidiens par page ou requête searchAnalytics.query 25 000 lignes par requête ; 50 000 lignes par jour et par type de recherche
Vérifier si une URL est indexée, connaître sa canonique et son dernier crawl urlInspection.index.inspect 2 000 requêtes par jour et par site
Envoyer ou lister des sitemaps sitemaps.submit / sitemaps.list Nécessite le périmètre d’accès en lecture/écriture
Conserver l’historique complet des performances dans un entrepôt de données Export groupé vers BigQuery Toutes les données, à l’exception des requêtes anonymisées
Demander à Google d’explorer immédiatement une page ordinaire Non disponible L’Indexing API couvre uniquement les pages d’offres d’emploi et de diffusions en direct

C’est précisément avec la dernière ligne que commencent la plupart des projets d’automatisation qui échouent : ils prévoient un script nocturne envoyant chaque nouvel article à Google, puis découvrent qu’aucun endpoint pris en charge ne permet de le faire pour les pages ordinaires. La section 7 revient sur ce point.

S’authentifier : compte de service ou OAuth pour les tâches automatisées

Chaque requête doit contenir un jeton OAuth 2.0 ; les clés API ne donnent pas accès aux données privées d’une propriété. Google définit deux périmètres d’accès : webmasters.readonly pour la lecture seule et webmasters pour les opérations en lecture/écriture. Utilisez le périmètre en lecture seule pour les rapports et ajoutez les droits d’écriture uniquement au script qui envoie les sitemaps.

Pour une tâche planifiée qui s’exécute sans supervision, un compte de service est le choix le plus pratique. Un flux OAuth avec consentement utilisateur nécessite un navigateur et un jeton d’actualisation. De plus, les jetons d’actualisation délivrés alors que votre écran de consentement est encore en mode test expirent au bout d’environ une semaine : la tâche finit donc par s’arrêter discrètement.

  1. Dans Google Cloud, créez un projet et activez l’API Search Console.
  2. Créez un compte de service et téléchargez sa clé JSON. Traitez cette clé comme un mot de passe.
  3. Dans Search Console, ouvrez Paramètres, puis Utilisateurs et autorisations, et ajoutez l’adresse e-mail du compte de service comme utilisateur sur chaque propriété nécessaire à la tâche. Accordez le niveau d’autorisation minimal requis.
  4. Utilisez l’identifiant de propriété exactement comme il apparaît dans Search Console : https://www.example.com/ pour une propriété avec préfixe d’URL, ou sc-domain:example.com pour une propriété de domaine.
from google.oauth2 import service_account
from googleapiclient.discovery import build

SCOPES = ['https://www.googleapis.com/auth/webmasters.readonly']
creds = service_account.Credentials.from_service_account_file(
    'service-account.json', scopes=SCOPES)
gsc = build('searchconsole', 'v1', credentials=creds)

print(gsc.sites().list().execute())  # properties this account can see

Si sites().list() renvoie une liste vide, l’authentification a fonctionné, mais le compte de service n’a jamais été ajouté à une propriété. Activer l’API dans le projet cloud ne suffit pas : l’accès est accordé propriété par propriété dans Search Console. C’est la cause la plus fréquente des erreurs 403 dans les nouvelles configurations.

Extraire les données Search Console avec Python au-delà de la limite de 25 000 lignes

Le paramètre rowLimit accepte une valeur comprise entre 1 et 25 000 et vaut 1 000 par défaut. Une requête qui l’omet renvoie donc une fraction de vos données sans vous l’indiquer clairement. Parcourez les résultats en augmentant startRow jusqu’à ce qu’une réponse vide soit renvoyée. Dans son guide pour récupérer toutes vos données de performances, Google recommande d’exécuter une requête par jour pour une seule journée de données. Vous restez ainsi dans les limites de quota et disposez d’une unité facile à relancer.

import time, random
from googleapiclient.errors import HttpError

PAGE = 25000

def execute(request, tries=5):
    for attempt in range(tries):
        try:
            return request.execute()
        except HttpError as err:
            quota = 'quota' in str(err).lower()
            if attempt == tries - 1:
                raise
            if quota:
                time.sleep(15 * 60)   # short-term load quota: wait 15 minutes
            elif err.resp.status in (429, 500, 503):
                time.sleep(2 ** attempt + random.random())
            else:
                raise

def pull_day(site, day, search_type='web',
             dims=('date', 'page', 'query', 'device', 'country')):
    rows, start = [], 0
    while True:
        body = {
            'startDate': day, 'endDate': day,
            'dimensions': list(dims), 'type': search_type,
            'rowLimit': PAGE, 'startRow': start,
        }
        resp = execute(gsc.searchanalytics().query(siteUrl=site, body=body))
        batch = resp.get('rows', [])
        if not batch:
            return rows
        rows.extend(batch)
        start += PAGE

Pourquoi cibler une date située trois jours auparavant

Google précise que les données sont généralement disponibles après deux ou trois jours et que les dates des requêtes sont interprétées selon l’heure du Pacifique, pas selon votre heure locale. Une tâche exécutée à Hanoï ou à Berlin qui demande les données de la veille selon l’heure locale peut donc interroger une date du Pacifique qui n’est pas encore finalisée. Calculez la date cible dans le fuseau horaire du Pacifique, puis soustrayez trois jours. Si vous avez besoin de chiffres plus récents, transmettez dataState: 'all' ; lorsque vous regroupez les données par date, les métadonnées de la réponse incluent first_incomplete_date et toutes les valeurs postérieures peuvent encore évoluer.

Totaux exacts et lignes détaillées : deux requêtes différentes

Lorsque vous regroupez les données par page ou par requête, Search Console peut supprimer des lignes pour maintenir le coût du calcul à un niveau raisonnable. La somme d’une extraction par page et par requête ne correspond donc pas nécessairement à vos totaux réels. La méthode fiable consiste à exécuter deux requêtes par jour et à les stocker séparément.

Objectif Dimensions Compromis
Totaux exacts Aucune, ou uniquement le pays et l’appareil Pas de détail par page ou par requête
Détails pour l’analyse Page, requête, avec éventuellement le pays et l’appareil Certaines lignes sont supprimées

Même l’extraction détaillée est soumise à une limite : l’API expose au maximum 50 000 lignes par jour et par type de recherche, triées par nombre de clics. Sur un site important, la longue traîne au-delà de cette limite est invisible pour cet endpoint. C’est précisément ce que permet de résoudre l’export BigQuery présenté plus bas.

Quotas et limites de l’API Search Console

Ces chiffres proviennent de la page consacrée aux limites d’utilisation de l’API Search Console de Google, consultée en . Les quotas évoluent : vérifiez-les avant de dimensionner une tâche.

Ressource Périmètre Limite
Search Analytics Par site 1 200 requêtes par minute
Search Analytics Par utilisateur 1 200 requêtes par minute
Search Analytics Par projet 40 000 par minute ; 30 000 000 par jour
Inspection d’URL Par site 600 par minute ; 2 000 par jour
Inspection d’URL Par projet 15 000 par minute ; 10 000 000 par jour
Toutes les autres ressources Par utilisateur 20 par seconde ; 200 par minute

Les limites par minute posent rarement problème. Search Analytics applique également un quota de charge, mesuré sur des fenêtres de 10 minutes et d’une journée, et c’est lui qui fait généralement échouer les pipelines réels. La charge augmente avec la période interrogée ; les regroupements ou filtres par page ou par requête sont coûteux, et le regroupement selon les deux dimensions est la combinaison la plus coûteuse. Le message d’erreur est identique pour tous les dépassements de quota. Il faut donc observer le comportement : si une seule requête échoue encore pendant une fenêtre de 10 minutes peu sollicitée, vous avez probablement dépassé le quota de charge quotidien.

  • Interrogez une journée à la fois plutôt qu’une période étendue.
  • Ne demandez pas à nouveau des données déjà stockées. Conservez les lignes brutes.
  • Si vous atteignez le quota à court terme, attendez 15 minutes ; si le problème persiste, supprimez le regroupement page-requête ou réduisez la période.

Automatiser l’inspection des URL et l’envoi des sitemaps

L’endpoint d’inspection d’URL renvoie le même état d’indexation que celui visible dans l’interface web : l’URL est-elle présente dans Google, quelle URL canonique Google a-t-il choisie et quand a-t-elle été explorée pour la dernière fois ? Il indique un état, mais ne demande pas l’indexation.

def inspect(site, url):
    body = {'inspectionUrl': url, 'siteUrl': site}
    res = execute(gsc.urlInspection().index().inspect(body=body))
    s = res['inspectionResult']['indexStatusResult']
    return {
        'url': url,
        'state': s.get('coverageState'),
        'last_crawl': s.get('lastCrawlTime'),
        'google_canonical': s.get('googleCanonical'),
        'user_canonical': s.get('userCanonical'),
    }

Avec 2 000 inspections par jour et par site, vous ne pouvez pas vérifier quotidiennement un catalogue de 50 000 URL. Utilisez ce budget là où un changement compte : les URL publiées au cours de la dernière semaine, vos pages les plus performantes en clics et les pages dont les clics viennent de baisser. Faites tourner le reste sur le mois. Stockez chaque résultat afin de pouvoir déclencher une alerte lors d’un changement de coverageState ou d’une incohérence canonique, ce qui est plus utile qu’un instantané isolé. Le quota s’applique à chaque propriété : diviser un grand site en propriétés avec préfixe d’URL pour ses principales sections est donc un moyen légitime d’augmenter le budget.

L’envoi d’un sitemap nécessite le périmètre de lecture/écriture et un seul appel, gsc.sitemaps().submit(siteUrl=site, feedpath=sitemap_url). Celui-ci indique à Google où se trouve le fichier ; renvoyer un fichier inchangé après chaque mise en production n’apporte rien. Ce qui facilite l’exploration, c’est une valeur lastmod exacte directement dans le sitemap.

Les équipes qui préfèrent ne pas maintenir cette infrastructure peuvent en déléguer la mise en place : Netalith conçoit ce type de reporting et de monitoring dans le cadre de son activité d’automatisation SEO.

Quand l’API ne suffit plus : l’export groupé vers BigQuery

Si la limite quotidienne de 50 000 lignes ou la suppression de lignes lors du regroupement par page et par requête nuit à vos analyses, cessez de contourner l’API. Search Console peut planifier un export quotidien de vos données de performances vers BigQuery. Celui-ci inclut toutes les données de performance disponibles pour la propriété, à l’exception des requêtes anonymisées. L’export arrive dans deux tables principales, searchdata_site_impression et searchdata_url_impression.

Besoin Solution la plus adaptée
Site de petite ou moyenne taille, tableaux de bord, alertes Extraction via l’API vers votre propre base de données
Requêtes de longue traîne au-delà de 50 000 lignes par jour Export groupé BigQuery
Associer Search Console au chiffre d’affaires ou aux données de logs Export groupé BigQuery
État d’indexation des URL et sitemaps API (l’export ne les contient pas)

Une précaution importante en pratique : l’export commence le jour où vous le configurez ; l’historique antérieur n’est pas ajouté rétroactivement. Activez-le tôt et maintenez votre extraction via l’API pour la période précédente. Les deux solutions sont complémentaires, pas concurrentes.

L’Indexing API peut-elle demander l’indexation de pages ordinaires ?

Non. Google présente l’Indexing API comme un moyen de le prévenir lorsque des pages d’offres d’emploi ou de vidéos de diffusion en direct sont ajoutées ou supprimées. Elle ne fonctionne que pour les pages contenant les données structurées JobPosting ou BroadcastEvent intégrées dans un VideoObject. Elle dispose d’un quota par défaut de 200 pour l’intégration et les tests, nécessite une approbation pour aller au-delà, et Google avertit qu’un usage abusif, notamment le recours à plusieurs comptes pour dépasser les quotas, peut entraîner la révocation de l’accès.

Les tutoriels qui l’utilisent pour envoyer des articles de blog ou des pages produits fonctionnent aujourd’hui par hasard, et non parce que cette pratique est prévue. Construire un workflow de production sur un comportement non pris en charge est un risque que vous assumez seul. Pour les pages ordinaires, les leviers pris en charge sont un sitemap propre avec des valeurs lastmod honnêtes, des liens internes solides depuis des pages explorées et les données d’inspection ci-dessus pour repérer les blocages.

Planifier le pipeline et déclencher des alertes en cas de baisse de trafic

Une tâche quotidienne doit respecter quatre principes : cibler une date située trois jours auparavant dans le fuseau horaire du Pacifique, être idempotente afin qu’une nouvelle exécution ne duplique jamais les lignes, stocker les lignes brutes et ne déclencher une alerte que pour des variations suffisamment importantes. Search Console conserve environ 16 mois de données ; votre propre stockage est donc aussi le seul moyen de comparer plusieurs années.

Stockez les lignes avec une clé unique sur (date, page, query, device, country) et utilisez un upsert. Une seule requête peut ensuite comparer les sept derniers jours aux sept jours précédents et signaler les pages ayant réellement perdu du trafic.

WITH w AS (
  SELECT page,
    SUM(CASE WHEN date >= date('now', '-10 day') THEN clicks ELSE 0 END) AS last7,
    SUM(CASE WHEN date < date('now', '-10 day') THEN clicks ELSE 0 END) AS prev7
  FROM gsc
  WHERE date >= date('now', '-17 day')
  GROUP BY page
)
SELECT page, prev7, last7
FROM w
WHERE prev7 >= 50 AND last7 < prev7 * 0.7
ORDER BY prev7 - last7 DESC;

Les deux seuils relèvent de votre jugement, pas de chiffres fournis par Google. Le seuil minimal de 50 clics évite que les petites pages ne vous alertent pour de simples fluctuations ; la baisse de 30 % permet de détecter de vraies pertes sans réagir aux variations hebdomadaires normales. Ajustez ces deux valeurs à partir d’un mois de votre propre historique avant d’envoyer les alertes dans un canal réellement consulté. Exécutez la tâche avec cron, un planificateur CI ou une tâche de conteneur ; le choix de l’outil importe moins que la sécurité du mécanisme de stockage en cas de nouvelle exécution.

Si vous souhaitez déployer ce pipeline sur vos propres propriétés sans le concevoir ni le maintenir, demandez un devis gratuit en indiquant les rapports dont vous avez besoin.

FAQ

Questions fréquentes

Combien de lignes l’API Search Console peut-elle renvoyer ?

Une seule requête renvoie au maximum 25 000 lignes ; vous parcourez les résultats avec startRow. Par ailleurs, l’API expose au maximum 50 000 lignes de données par jour et par type de recherche, triées par nombre de clics. Pour aller au-delà, utilisez l’export groupé BigQuery.

Puis-je utiliser un compte de service avec l’API Search Console ?

Oui. Créez un compte de service, activez l’API Search Console dans son projet cloud, puis ajoutez l’adresse e-mail du compte de service comme utilisateur sur chaque propriété dans Search Console. Sans cette étape d’autorisation pour chaque propriété, les appels renvoient des listes vides ou des erreurs 403, même si l’authentification a réussi.

À quelle fréquence dois-je extraire les données Search Console ?

Une fois par jour, pour une seule journée de données. Google recommande cette méthode, car elle reste dans les limites de quota. Les données étant généralement disponibles après deux ou trois jours, ciblez une date située environ trois jours auparavant dans le fuseau horaire du Pacifique.

L’API Search Console peut-elle demander l’indexation d’une URL ?

Non. L’endpoint d’inspection d’URL indique uniquement l’état d’indexation. L’Indexing API peut avertir Google de l’existence de certaines pages, mais Google la documente uniquement pour les pages d’offres d’emploi et les vidéos de diffusion en direct. Elle ne constitue donc pas une solution prise en charge pour envoyer des pages ordinaires.

Dois-je utiliser l’API ou l’export groupé BigQuery ?

Utilisez l’API pour l’inspection des URL, les sitemaps et les extractions quotidiennes légères vers votre propre base de données. Utilisez l’export BigQuery lorsque vous avez besoin de la longue traîne au-delà de 50 000 lignes par jour ou lorsque vous souhaitez associer Search Console à d’autres données. L’export n’est pas rétroactif : activez-le tôt.

Restez informé avec Netalith

Recevez des ressources de développement, des mises à jour produit et des offres spéciales directement dans votre boîte mail.