Aller au contenu
Retour au blog

Guide de l'API de scraping des SERP : Google, Bing, DuckDuckGo, Yandex

Suciu DanDernière mise à jour le 25 min read
Guide de l'API de scraping des SERP : Google, Bing, DuckDuckGo, Yandex
En bref : Pour utiliser la SERP Scraping API, envoyez une requête GET à https://serpapi.webscrapingapi.com/v2 avec api_key, engine et votre requête (q pour la plupart des moteurs, text pour Yandex). Google et Bing renvoient du JSON analysé, tandis que DuckDuckGo et Yandex renvoient le HTML de la page de résultats, que votre code doit extraire : prévoyez l'analyse et les tests en conséquence. Ce guide couvre aussi la localisation, les tâches asynchrones, les erreurs et les tarifs.

Vous avez besoin de résultats de recherche pour un ensemble de mots-clés, dans des pays et des langues spécifiques, sur des appareils précis, sous forme de données que votre code peut stocker et comparer d’une semaine à l’autre. Gérer votre propre outil de scraping de recherche implique de contourner les blocages et de réécrire les analyseurs syntaxiques à chaque fois qu’une page de résultats change ; c’est pourquoi ce guide utilise plutôt l’API SERP de WebScrapingAPI. À la fin de ce guide, vous serez en mesure d’envoyer une première requête avec votre clé définie dans une variable d’environnement, de choisir le moteur approprié, de définir le marché que vous souhaitez analyser, d’analyser de manière défensive les données JSON de Google et Bing, d’extraire vous-même le code HTML de DuckDuckGo et Yandex, d’effectuer des recherches Google de manière asynchrone, de réessayer en fonction du contrat d’erreur documenté, et de choisir un forfait adapté.

Démarrage rapide

  • Point de terminaison : https://serpapi.webscrapingapi.com/v2 (GET)
  • Obligatoire : api_key, engine, et la requête (q pour la plupart des moteurs de recherche, text pour Yandex)
  • Résultat : Google et Bing renvoient du JSON analysé. DuckDuckGo et Yandex renvoient le code HTML de la page de résultats dans une enveloppe JSON
  • Essai gratuit : 100 recherches Google

Qu'est-ce que l'API SERP Scraping, et que renvoie-t-elle ?

L'API SERP de WebScrapingAPI est un point de terminaison côté serveur qui prend en entrée une requête de recherche, un moteur de recherche et un contexte de marché, puis renvoie la page de résultats sous forme de données. Google et Bing renvoient des collections JSON analysées. DuckDuckGo et Yandex renvoient une enveloppe JSON dont le search_results champ contient le code HTML de la SERP que votre code pourra extraire.

Cette distinction est la chose la plus importante à comprendre avant d’écrire le moindre code. Avec Google et Bing, vous lisez des collections nommées telles que organic[] et related[]. Avec DuckDuckGo et Yandex, vous recevez la page brute et décidez vous-même ce que vous souhaitez en extraire. Votre modèle de stockage, vos tests et vos tâches de maintenance dépendent tous du côté de cette ligne où se situe le moteur de recherche.

L’API couvre quatre familles de moteurs : Google, Bing, DuckDuckGo et Yandex. Google dispose également de sept moteurs spécialisés en plus de la recherche standard : la recherche asynchrone, Maps, les avis Maps, les hôtels, les vols, les tendances et la recherche d’images par image. Les équipes les utilisent pour surveiller le classement et les fonctionnalités des SERP, la présence des marques et des éditeurs, les placements payants renvoyés, ainsi que pour réaliser des études de marché sur différents sujets et éditeurs.

  • WebScrapingAPI gère : la validation des requêtes et l’exécution des moteurs, l’infrastructure d’accès à la recherche, les collections de résultats analysés là où elles sont documentées, la fourniture de l’enveloppe JSON pour les moteurs HTML, ainsi que la maintenance du comportement des points de terminaison pris en charge.
  • Votre équipe gère : les groupes de requêtes, les marchés, les langues et les appareils, ainsi que la planification, les tentatives de connexion au niveau de l’API, l’extraction à partir des enveloppes HTML, le stockage, les calculs de classement, les alertes, ainsi que la politique d’utilisation et de conservation des données.

Une autre limite est importante pour l’analyse. L’API ne définit pas de classement universel. Chaque résultat correspond à une requête, sur un marché donné, sur un appareil donné, à un moment donné ; veillez donc à conserver ce contexte associé à chaque ligne que vous stockez. Vous souhaitez la comparer aux autres API basées sur le moment de la requête ? Découvrez comment l’API SERP s’intègre aux autres API d’accès Web.

Comment envoyer votre première requête à l’API SERP ?

Créez un compte, abonnez-vous à l’API SERP dans le tableau de bord, puis copiez votre clé API dans une variable d’environnement. Envoyez ensuite une requête GET à https://serpapi.webscrapingapi.com/v2 avec api_key, engine=google, en q en indiquant votre mot-clé. Laissez votre bibliothèque HTTP s'occuper de l'encodage des paramètres et conservez la clé sur le serveur.

  1. Créez un compte WebScrapingAPI.
  2. Abonnez-vous à l'API SERP dans le tableau de bord. La période d'essai comprend 100 recherches Google.
  3. Enregistrez la clé dans votre shell ou votre gestionnaire de secrets : export WSA_API_KEY=...
  4. Envoyez la requête à l’aide de l’un des extraits de code ci-dessous.

La requête a la même structure pour tous les moteurs de recherche. Seuls engine, le champ de requête et les paramètres de contexte changent ; ainsi, une fois que cet appel fonctionne, tous les autres moteurs ne sont plus qu'une question de paramètres.

curl. Les --data-urlencode indicateurs encodent chaque valeur, et --max-time 120 définit un délai d’expiration explicite pour le client :

# Google, parsed JSON, US English, mobile
EP="https://serpapi.webscrapingapi.com/v2"
curl --get --fail-with-body --max-time 120 "$EP" \
  --data-urlencode "api_key=$WSA_API_KEY" \
  --data-urlencode "engine=google" \
  --data-urlencode "q=running shoes" \
  --data-urlencode "gl=us" --data-urlencode "hl=en" --data-urlencode "device=mobile"

Python. Ce petit client lit la clé dans l’environnement, transmet chaque valeur via l’ params argument afin que Requests l’encode pour vous, effectue des tentatives de réessai conformément au contrat d’erreur et enregistre les en-têtes d’utilisation. Les sections consacrées à Bing et à la gestion des erreurs ci-dessous le réutilisent.

"""Minimal WebScrapingAPI SERP API client: env-var key, jittered retries, usage headers.

Usage:
  export WSA_API_KEY=...                       # never hardcode the key
  python wsa_serp.py google "running shoes" gl=us hl=en device=mobile
  python wsa_serp.py bing "coffee roasters" mkt=en-US cc=us lang=en
  python wsa_serp.py yandex "pizza" lr=213 p=0
  python wsa_serp.py google "running shoes" gl=us --dry-run   # print the request, no call
"""
import os
import random
import sys
import time

import requests

ENDPOINT = "https://serpapi.webscrapingapi.com/v2"
# Most engines take their main input in q. These don't (see the engine table).
QUERY_FIELD = {"yandex": "text", "google_maps_reviews": "fid", "google_reverse_image": "url"}
RETRYABLE = {429, 500, 502, 503}   # back off with jitter, then retry
FINAL = {400, 401}                 # fix the key, plan, or parameters; never retry


def build_params(engine, query, **extra):
    params = {"engine": engine, QUERY_FIELD.get(engine, "q"): query}
    params.update({k: str(v) for k, v in extra.items()})
    return params


def search(engine, query, api_key, max_attempts=4, **extra):
    params = {"api_key": api_key, **build_params(engine, query, **extra)}
    for attempt in range(1, max_attempts + 1):
        resp = requests.get(ENDPOINT, params=params, timeout=120)
        usage = {k: v for k, v in resp.headers.items() if k.lower().startswith("searchdata-")}
        if resp.ok:
            return resp.json(), usage
        if resp.status_code in FINAL:
            # 401: missing, invalid, or unentitled key. 400: "Parameter '<name>' not allowed." etc.
            raise SystemExit(f"{resp.status_code}: {resp.text[:300]}")
        retry_422 = resp.status_code == 422 and attempt == 1   # target-side failure: one retry only
        if resp.status_code in RETRYABLE or retry_422:
            time.sleep(random.uniform(0, min(2 ** attempt, 30)))   # full jitter
            continue
        raise SystemExit(f"Unexpected {resp.status_code}: {resp.text[:300]}")
    raise SystemExit(f"Gave up after {max_attempts} attempts")


def organic(data):
    """Product pages document organic[]; some docs pages show organic_results[]. Accept both."""
    return data.get("organic") or data.get("organic_results") or []


def main():
    args = [a for a in sys.argv[1:] if a != "--dry-run"]
    if len(args) < 2:
        sys.exit(__doc__)
    engine, query = args[0], args[1]
    extra = dict(a.split("=", 1) for a in args[2:])

    if "--dry-run" in sys.argv:
        prepared = requests.Request(
            "GET", ENDPOINT, params={"api_key": "REDACTED", **build_params(engine, query, **extra)}
        ).prepare()
        print(prepared.url)
        return

    api_key = os.environ.get("WSA_API_KEY")
    if not api_key:
        sys.exit("Set WSA_API_KEY first (dashboard -> SERP API).")

    data, usage = search(engine, query, api_key, **extra)
    print("usage headers:", usage)
    if "search_results" in data:          # DuckDuckGo and Yandex: SERP HTML inside a JSON envelope
        print("search_parameters:", data.get("search_parameters"))
        print("html chars:", len(data["search_results"]))
    else:                                  # Google and Bing: parsed JSON
        for row in organic(data)[:10]:
            print(row.get("rank") or row.get("position"), row.get("title"), row.get("link"))


if __name__ == "__main__":
    main()

Exécutez-le python wsa_serp.py google "running shoes" gl=us hl=en device=mobile --dry-run d'abord. Il affiche l'URL exacte de la requête avec la clé remplacée par REDACTED, ce qui vous permet de vérifier les paramètres avant de lancer une recherche.

Node.js (version 18 ou ultérieure). URLSearchParams se charge de l’encodage, et AbortSignal.timeout définit la même limite de 120 secondes :

// Build and (optionally) send a SERP API request in Node 18+.
// URLSearchParams handles encoding; the key comes from the environment.
const ENDPOINT = "https://serpapi.webscrapingapi.com/v2";
const QUERY_FIELD = { yandex: "text", google_maps_reviews: "fid", google_reverse_image: "url" };

export function buildSerpUrl(apiKey, engine, query, extra = {}) {
  const url = new URL(ENDPOINT);
  url.searchParams.set("api_key", apiKey);
  url.searchParams.set("engine", engine);
  url.searchParams.set(QUERY_FIELD[engine] ?? "q", query);
  for (const [k, v] of Object.entries(extra)) url.searchParams.set(k, String(v));
  return url;
}

export async function search(engine, query, extra = {}) {
  const apiKey = process.env.WSA_API_KEY;
  if (!apiKey) throw new Error("WSA_API_KEY is required");
  const res = await fetch(buildSerpUrl(apiKey, engine, query, extra), {
    signal: AbortSignal.timeout(120_000),
  });
  if (!res.ok) throw new Error(`SERP API ${res.status}: ${(await res.text()).slice(0, 300)}`);
  const data = await res.json();
  return { data, organic: data.organic ?? data.organic_results ?? [] };
}

// Dry run: show the encoded URL and prove the query survives the round trip.
if (process.argv[1]?.endsWith("build_serp_request.mjs")) {
  const q = 'site:example.com "running shoes" & socks?';
  const u = buildSerpUrl("REDACTED", "google", q, { gl: "us", hl: "en", device: "mobile" });
  console.log(u.toString());
  console.log("round trip ok:", new URL(u).searchParams.get("q") === q);
  const y = buildSerpUrl("REDACTED", "yandex", "pizza", { lr: 213, p: 0 });
  console.log(y.toString());
}

Le test sans exécution montre pourquoi l’encodage est important. La requête site:example.com "running shoes" & socks? devient q=site%3Aexample.com+%22running+shoes%22+%26+socks%3F et est décodée sans modification (round trip ok: true). Si vous insérez cette requête manuellement dans une URL, le simple & met fin à votre q et lance un nouveau paramètre nommé socks?. Le /v2 point de terminaison valide les paramètres par moteur et rejette les noms qu’il ne reconnaît pas ; une URL construite manuellement échouera donc de manière imprévisible. Laissez la bibliothèque appliquer l’encodage en pourcentage à chaque fois.

Traitez la clé comme un mot de passe. Conservez-la dans des variables d’environnement côté serveur ou dans un gestionnaire de secrets, et ne la mentionnez jamais dans le code front-end, les dépôts publics, les journaux ou les captures d’écran. Toute personne disposant de la clé peut effectuer vos recherches à votre place.

Documentation : Accéder à l’API

Quels moteurs de recherche et moteurs Google pouvez-vous interroger ?

La référence API actuelle répertorie onze moteurs : google, google_async, google_maps, google_maps_reviews, google_flights, google_hotels, google_trends, google_reverse_image, bing, duckduckgo, et yandex. Chacun dispose de ses propres paramètres d'entrée obligatoires et autorisés. Ne considérez que ceux-ci comme pris en charge, même si d'anciennes pages de documentation décrivent d'autres moteurs Google.

Moteur

Données d'entrée obligatoires

Vous obtenez en retour

Tarification

google

q

JSON analysé (general, input, navigation[], organic[], modules optionnels)

Plans Google

google_async

q

response_id, puis la charge utile SERP finale

Plans Google

google_maps

type=search + q, ou type=place + data

Résultats de lieux analysés

Plans Google

google_maps_reviews

fid

Avis analysés

Projets de Google

google_hotels

type=search + q, ou type=place + pid; dates d'arrivée et de départ

overview, organic[]

Plans Google

google_flights

q (jeton Google Flights encodé)

search_parameters, search_results[]

Plans Google

google_trends

q

widgets[] (TIMESERIES, GEO_MAP)

Plans Google

google_reverse_image

url

general, images[], exact_matches[]

Plans Google

bing

q

JSON analysé (general, organic[], related[])

Citation

duckduckgo

q

Enveloppe JSON : search_parameters + search_results (HTML)

Citation

yandex

text

Enveloppe JSON : search_parameters + search_results (HTML)

Citation

Trois moteurs ne prennent pas leur entrée principale en q. Yandex récupère la requête dans text, Google Maps Reviews utilise l' fid, et Google Reverse Image prend une image url. Les clients Python et Node ci-dessus effectuent déjà la mise en correspondance de ces champs pour vous. Google Maps et Google Hotels ont également besoin de type=search ou type=place, ce qui modifie l’autre champ obligatoire.

« Forfaits Google » désigne les forfaits mensuels publiés par Google et présentés dans la section « Tarifs ». Les tarifs de Bing, DuckDuckGo et Yandex sont établis sur devis.

Vous trouverez peut-être des pages de documentation concernant d’autres moteurs Google, tels que la saisie semi-automatique, les événements, la finance, les offres d’emploi, les services locaux, les photos de Maps, Play, les produits et Scholar. Ils ne figurent pas dans la liste des services pris en charge ; ne construisez donc pas de pipeline sur ces derniers.

Documentation : Référence des API SearchData et SERP

Comment localiser les résultats Google par pays, langue et appareil ?

Définissez gl le code pays à deux lettres, hl sur la langue de l'interface, et device sur desktop, mobile, ou tablet. Ajoutez domain pour un hôte Google spécifique et uule pour un emplacement codé lorsque le contexte au niveau de la ville est important. Enregistrez ces valeurs avec chaque résultat, car une même requête peut être classée différemment selon les marchés.

Google indique lui-même que les résultats dépendent de l'endroit d'où vous effectuez la recherche ; ainsi, un classement sans indication de marché n'est qu'une demi-vérité. Cette recherche canadienne, en anglais et sur ordinateur de bureau, portant sur le terme « history » sur google.ca, s'effectue via le client Python décrit dans la section « première requête » :

python wsa_serp.py google history gl=ca hl=en domain=google.ca device=desktop

Si vous avez besoin d’une ville spécifique, telle que London (Ontario), ajoutez sa uule valeur en tant qu’argument supplémentaire uule=... . N’utilisez que les paramètres documentés par votre moteur de recherche. Les anciens exemples qui trient par date ou filtrent par période ne s’appliquent pas à /v2 Google Search, et le point de terminaison rejette les paramètres qu’il n’autorise pas.

Le type de résultats et la pagination modifient également ce que vous obtenez :

  • Affichage : tbm permet de changer le type de résultats : isch pour les images, vid pour les vidéos, nws pour les actualités, et shop pour les achats. Pour les résultats Google Emploi, utilisez ibp=htl;jobs.
  • la pagination : start définit le nombre de résultats à ignorer, et num définit le nombre de résultats à afficher par page.

La meilleure pratique à adopter ici est la conception de marché. Avant de collecter quoi que ce soit, choisissez une petite grille fixe composée de requête × pays × langue × appareil, et ne la modifiez pas d'une exécution à l'autre. Si l'exécution d'une semaine utilise gl=us&device=mobile et que la suivante utilise gl=us&device=desktop, une « baisse de classement » peut simplement s’expliquer par un changement d’appareil. Chaque réponse correspond à une observation d’un marché donné, et non à une vérité universelle ; les comparaisons n’ont donc de sens qu’au sein d’une même cellule de la grille.

La liste complète des champs de requête et des blocs de réponse se trouve sur la page des commandes de l’API de recherche Google.

Moteur

Emplacement / marché

Langue

Appareil

Pagination / heure

Filtres et surfaces

Google

gl (pays), domain (hôte Google), uule (localisation codée)

hl

device = ordinateur de bureau, mobile, tablette

start (ignorer), num (par page)

tbm = isch, vid, nws, shop ; ibp=htl;jobs

Bing

mkt (par ex. en-US), cc, location, lat, lon

lang

—

first (décalage), count

safesearch = désactivé, modéré, strict

DuckDuckGo

kl (par ex., en_US)

kad (interface)

device

df = d, w, m, y

kp = 1, -1, -2

Yandex

lr (identifiant de région, par exemple 213), yandex_domain

lang

device

p (compté à partir de zéro), within = 77 (24 h), 1 (2 semaines)

—

Documentation : paramètres de l'API de recherche Google

Comment lire et stocker les résultats analysés de Google et Bing ?

Lisez le tableau « organic » pour les résultats classés, chacun comportant un titre, un lien, un lien d'affichage, une description et un classement. Considérez tous les autres modules, tels que les recherches associées, la navigation, les annonces ou les résultats locaux, comme facultatifs. Enregistrez chaque ligne avec la requête, le marché, l'appareil et l'heure de capture afin que les comparaisons de classement ultérieures restent pertinentes.

Une réponse Google comporte plusieurs blocs de premier niveau. general décrit la requête (moteur, langue, emplacement, indicateur mobile et type de recherche), input contient l’URL de recherche d’origine, navigation[] répertorie les autres interfaces Google pour la requête, et organic[] contient les résultats classés. Une réponse Bing contient general, organic[], et related[].

Tout le reste est conditionnel. Les annonces, les résultats locaux, les achats, les médias et les recherches associées n’apparaissent que lorsque la page de résultats les affiche, et les fonctionnalités de la page de résultats de recherche (SERP) présentées par Google varient en fonction de la requête, de la localisation et de l’appareil. Veillez donc à distinguer deux cas dans votre code : une requête qui a échoué (erreur HTTP) et une requête qui a abouti mais pour laquelle un module est absent. Le second cas est une observation normale, et non un bug.

Écrivez le parseur de manière défensive. Certaines pages de documentation présentent la liste classée sous la forme organic_results[] avec position au lieu de organic[] avec rank, lisez donc l’une ou l’autre. Ce script aplatit une réponse en lignes de classement. Le fichier d’entrée est un échantillon étiqueté, et non une sortie en temps réel :

"""Flatten a Google or Bing SERP API response into rank rows.

Organic results may arrive as organic[] (product pages) or organic_results[] (some docs pages),
and modules such as related[] or navigation[] are optional, so read them defensively.
"""
import json
import sys
from datetime import datetime, timezone


def rank_rows(data, query, market):
    rows = []
    captured = datetime.now(timezone.utc).isoformat(timespec="seconds")
    for item in data.get("organic") or data.get("organic_results") or []:
        rows.append({
            "captured_at": captured,
            "engine": data.get("general", {}).get("search_engine"),
            "query": query,
            "market": market,
            "rank": item.get("rank") or item.get("position"),
            "title": item.get("title"),
            "link": item.get("link"),
        })
    return rows


if __name__ == "__main__":
    data = json.load(open(sys.argv[1] if len(sys.argv) > 1 else "sample_google.json"))
    for row in rank_rows(data, "running shoes", "us/en/mobile"):
        print(row)
    print("optional modules present:", [k for k in ("navigation", "related", "related_questions") if k in data])

Sur le fichier d'exemple, il affiche une ligne par résultat naturel et répertorie les modules optionnels présents :

{'captured_at': '2026-10-29T12:03:56+00:00', 'engine': 'google', 'query': 'running shoes', 'market': 'us/en/mobile', 'rank': 1, 'title': 'Example result one', 'link': 'https://example.com/a'}
{'captured_at': '2026-10-29T12:03:56+00:00', 'engine': 'google', 'query': 'running shoes', 'market': 'us/en/mobile', 'rank': 2, 'title': 'Example result two', 'link': 'https://example.org/b'}
optional modules present: ['navigation']

Une ligne de classement doit comporter au moins captured_at: moteur, requête, marché, appareil, classement, titre et lien. Grâce à ces champs, vous pouvez comparer les exécutions, représenter graphiquement les évolutions et être alerté en cas de baisse. C’est là l’essence même du suivi des classements et des caractéristiques des SERP au fil du temps. Si vos liens stockés contiennent des redirections Google, renseignez-vous sur les liens de redirection Google /goto dans les URL de résultats avant de dédupliquer par URL.

Comment effectuer une recherche sur Bing avec l’API SERP ?

Définissez engine=bing et transmettez la requête dans q. Contrôlez le marché avec mkt, par exemple en-US, ainsi que cc pour le pays et lang pour la langue. Ajoutez location, ou lat et lon, pour préciser l’origine, safesearch pour le filtrage, et first avec count pour parcourir les résultats. Les réponses de Bing sont fournies sous forme de JSON analysé.

La version curl pour le marché américain, première page de 10 résultats :

curl --get --fail-with-body --max-time 120 "https://serpapi.webscrapingapi.com/v2" \
  --data-urlencode "api_key=$WSA_API_KEY" \
  --data-urlencode "engine=bing" \
  --data-urlencode "q=coffee roasters" \
  --data-urlencode "mkt=en-US" --data-urlencode "cc=us" --data-urlencode "lang=en" \
  --data-urlencode "first=0" --data-urlencode "count=10"

Avec le client Python de la section « première requête », le même appel tient en une seule ligne :

python wsa_serp.py bing "coffee roasters" mkt=en-US cc=us lang=en first=0 count=10

Bing renvoie general, organic[], et related[]. Les publicités et les images sont des modules optionnels ; les mêmes règles de sécurité s’appliquent donc : lisez organic[], considérez tout le reste comme présent ou absent, et stockez chaque ligne avec son marché. safesearch prend off, moderate, ou strict.

Conserver mkt, cc, et lang cohérente d’une exécution à l’autre, exactement comme vous le feriez avec le gl et hl. Les tarifs de Bing sont établis sur devis, et la version d’essai de 100 recherches couvre Google. Les champs de requête et les blocs de réponse se trouvent sur la page de l’API de recherche Bing.

Documentation : requêtes de l’API Bing de base

Comment gérez-vous les résultats HTML de DuckDuckGo et de Yandex ?

Ces deux moteurs renvoient des données JSON avec search_parameters, décrivant la requête, et search_results, une chaîne contenant le code HTML source de la page de résultats (SERP). WebScrapingAPI n’analyse pas ce code HTML ; c’est donc à votre application d’extraire les champs dont elle a besoin. Associez vos sélecteurs à une capture réelle, versionnez-les, stockez l’enveloppe brute et déclenchez une alerte lorsqu’un sélecteur ne correspond plus.


Google, Bing

DuckDuckGo, Yandex

Réponse

Métadonnées JSON + collections analysées

Métadonnées JSON + code HTML source de la SERP dans search_results

Analyse assurée par

WebScrapingAPI, où est documenté

Votre application

Votre code effectue

lit les collections de manière défensive ; stocke les lignes

Sélectionnez les sélecteurs et les versions ; extrayez les données ; signalez tout écart

Stockez

Lignes + contexte de la requête

Enveloppe brute + lignes extraites + version du sélecteur

Champs de requête DuckDuckGo : q pour la requête, kl pour la région et la langue (par exemple en_US), kad pour la langue de l'interface, kp pour la recherche sécurisée (1 activée, -1 modéré, -2 désactivé), df pour l'heure (d, w, m, y) et device.

champs de requête Yandex : text pour la requête, lr pour l’identifiant de la région (par exemple, 213), lang, device, yandex_domain, p pour la page (numérotation à partir de zéro, donc p=0 correspond à la première page), et within pour l'heure (77 pour les dernières 24 heures, 1 pour les deux dernières semaines).

# DuckDuckGo, SERP HTML in a JSON envelope
curl --get --fail-with-body --max-time 120 "https://serpapi.webscrapingapi.com/v2" \
  --data-urlencode "api_key=$WSA_API_KEY" \
  --data-urlencode "engine=duckduckgo" \
  --data-urlencode "q=privacy research" \
  --data-urlencode "kl=en_US" --data-urlencode "df=w"

# Yandex, SERP HTML in a JSON envelope (query parameter: text)
curl --get --fail-with-body --max-time 120 "https://serpapi.webscrapingapi.com/v2" \
  --data-urlencode "api_key=$WSA_API_KEY" \
  --data-urlencode "engine=yandex" \
  --data-urlencode "text=pizza" \
  --data-urlencode "lr=213" --data-urlencode "p=0"

Le schéma d’extraction est le même pour les deux moteurs : valider l’enveloppe, analyser le code HTML, sélectionner les liens vers les résultats, supprimer les liens de navigation propres au moteur, baliser chaque ligne avec une version de sélecteur, signaler clairement l’échec lorsqu’aucune correspondance n’est trouvée, et conserver le code HTML brut afin de pouvoir le retraiter ultérieurement. Ce script utilise Beautiful Soup avec des sélecteurs CSS :

"""Pull result links out of a DuckDuckGo or Yandex SERP API envelope.

These engines return {"search_parameters": {...}, "search_results": "<html>...</html>"}.
Your application owns extraction: pin the selector after inspecting a real capture,
version it, and alert when it stops matching. The selectors below fit the synthetic
fixtures only.
"""
import json
import sys
from urllib.parse import urlparse

from bs4 import BeautifulSoup

SELECTORS = {"duckduckgo": "div.result a.result-link", "yandex": "li.serp-item a.link"}
ENGINE_HOSTS = ("duckduckgo.com", "yandex.com", "yandex.ru")


def extract(envelope, selector_version="fixture-v1"):
    params = envelope.get("search_parameters", {})
    engine = params.get("search_engine")
    html = envelope.get("search_results")
    if not isinstance(html, str) or "<html" not in html.lower():
        raise ValueError("search_results is missing or is not HTML; store the raw envelope and alert")
    soup = BeautifulSoup(html, "html.parser")
    rows = []
    for pos, a in enumerate(soup.select(SELECTORS[engine]), start=1):
        host = urlparse(a.get("href", "")).hostname or ""
        if host.endswith(ENGINE_HOSTS):
            continue  # skip the engine's own navigation links
        rows.append({"engine": engine, "query": params.get("query"), "position": pos,
                     "title": a.get_text(strip=True), "link": a["href"],
                     "selector_version": selector_version})
    if not rows:
        raise ValueError(f"selector matched nothing for {engine}; markup may have changed")
    return rows


if __name__ == "__main__":
    for path in sys.argv[1:] or ["sample_ddg_envelope.json", "sample_yandex_envelope.json"]:
        for row in extract(json.load(open(path))):
            print(row)

Les sélecteurs indiqués SELECTORS ne s’appliquent qu’aux fichiers d’exemple synthétiques. Le balisage réel de DuckDuckGo et de Yandex est différent, et il évolue. Avant de l’exécuter en production, enregistrez une véritable « envelope », inspectez son code HTML, définissez vos propres sélecteurs et mettez à jour selector_version chaque fois que vous les modifiez. Lorsque le balisage change, les ValueError se déclenche au lieu que votre pipeline stocke silencieusement zéro résultat, et comme vous avez conservé le code HTML brut, vous pouvez réextraire les exécutions concernées une fois les sélecteurs corrigés.

Les champs spécifiques aux moteurs de recherche se trouvent sur les pages API de recherche DuckDuckGo et API de recherche Yandex.

Documentation : Paramètres de l’API DuckDuckGo · Paramètres de l’API Yandex

Utilisez les moteurs spécialisés de Google lorsque la réponse se trouve en dehors des résultats Web habituels. Google Maps localise des lieux, Maps Reviews affiche les avis sur un lieu par fid, Trends affiche des graphiques illustrant l’évolution de l’intérêt au fil du temps, Hotels et Flights fournissent des résultats de voyage, et Reverse Image recherche une image à partir d’une URL. Chaque moteur a ses propres données d’entrée et paramètres requis.

Ils utilisent tous le même point de terminaison, la même clé et les mêmes règles d’encodage que la recherche standard. Seule la engine valeur et les champs changent :

  • google_maps: envoyer type=search par q, ou type=place avec data. ll=@lat,lon,zoom définit la vue de la carte, et place_type limite la recherche aux hôtels ou aux locations de vacances. Aucune pagination n’est documentée.
  • google_maps_reviews: envoyez le fid, que vous extrayez du knowledge.fid champ d’une réponse de recherche Google. Triez avec sort (qualityScore, newestFirst, ratingHigh, ratingLow) et la pagination avec start et num.
  • google_trends: envoyer q avec geo, date (today 12-m, now 1-H, ou une YYYY-MM-DD YYYY-MM-DD intervalle), cat, et gprop (images, news, froogle, youtube). La réponse contient widgets[], telles que TIMESERIES et GEO_MAP.
  • google_hotels: envoyer type=search avec q, ou type=place avec pid, ainsi que check_in_date et check_out_date. Les filtres relatifs à la disponibilité, à la devise et à l'annulation gratuite sont facultatifs.
  • google_flights: q Il s’agit d’un jeton de requête Google Flights encodé, et non de texte brut. Ajoutez curr, hl, ainsi que gl pour la devise et le marché.
  • google_reverse_image: envoyez l’image url, puis utilisez lens (products, visual_matches, exact_matches, homework) pour choisir le type de correspondance.

Si vous hésitez entre la recherche d’images par image et tbm=isch les résultats d'images, consultez la comparaison des API de recherche d'images de Google.

Documentation : Moteurs de recherche Google

Comment effectuer des recherches Google de manière asynchrone ?

Envoyez la requête avec engine=google_async. L’API la met en file d’attente et renvoie un response_id immédiatement. Enregistrez cet identifiant avec votre tâche, puis interrogez le même /v2 point de terminaison en snapshot_id en indiquant cet identifiant et type=serp toutes les 10 à 30 secondes jusqu’à ce que la réponse SERP complète arrive. Limitez le temps d’attente total.

Async convient aux lots volumineux et aux workers qui ne peuvent pas maintenir une requête ouverte pendant 120 secondes. Il accepte les champs Google habituels ainsi que device et response=json. Il est réservé à Google : Bing, DuckDuckGo et Yandex ne disposent pas de moteur asynchrone, il ne faut donc pas concevoir de file d’attente asynchrone partagée autour d’eux.

"""Submit a google_async job, then poll for the finished SERP payload.

Usage:
  export WSA_API_KEY=...
  python google_async.py "events in new york city"
  python google_async.py "events in new york city" --dry-run
"""
import os
import random
import sys
import time

import requests

ENDPOINT = "https://serpapi.webscrapingapi.com/v2"


def submit(api_key, query, **extra):
    r = requests.get(ENDPOINT, params={"api_key": api_key, "engine": "google_async", "q": query, **extra}, timeout=60)
    r.raise_for_status()
    return r.json()["response_id"]          # store this id with your job record


def poll(api_key, response_id, max_wait=600):
    deadline = time.monotonic() + max_wait
    while time.monotonic() < deadline:
        r = requests.get(ENDPOINT, params={"api_key": api_key, "snapshot_id": response_id, "type": "serp"}, timeout=60)
        if r.ok:
            body = r.json()
            if body.get("status") in (None, "finished"):
                return body                  # persist it; don't re-poll old ids later
        elif r.status_code not in (429, 500, 502, 503):
            raise SystemExit(f"{r.status_code}: {r.text[:300]}")
        time.sleep(random.uniform(10, 30))   # docs: poll every 10 to 30 seconds
    raise SystemExit(f"No result for {response_id} after {max_wait} s")


if __name__ == "__main__":
    query = sys.argv[1] if len(sys.argv) > 1 else "events in new york city"
    if "--dry-run" in sys.argv:
        for p in ({"api_key": "REDACTED", "engine": "google_async", "q": query},
                  {"api_key": "REDACTED", "snapshot_id": "<response_id>", "type": "serp"}):
            print(requests.Request("GET", ENDPOINT, params=p).prepare().url)
        sys.exit(0)
    key = os.environ.get("WSA_API_KEY") or sys.exit("Set WSA_API_KEY first.")
    rid = submit(key, query)
    print("response_id:", rid)
    print(str(poll(key, rid))[:500])

Enregistrez chaque résultat final dès son arrivée et ne revenez pas plus tard pour interroger à nouveau d’anciens identifiants. La boucle a une échéance stricte et traite tout statut inattendu comme un arrêt ; ainsi, une tâche bloquée ne peut pas occuper un travailleur indéfiniment.

Documentation : API asynchrones

Comment votre code doit-il gérer les erreurs de l’API SERP et les nouvelles tentatives ?

Ne réessayez pas en cas d’erreurs 401 ou de validation. Corrigez la clé, le plan ou les paramètres. Réessayez plusieurs fois en cas de codes 429, 500, 502 et 503 avec un recul exponentiel et une variation de délai, et ralentissez les tentatives en cas de code 429. Un code 422 signifie que le moteur de recherche a renvoyé une erreur, un délai d’expiration ou un défi ; ne réessayez donc qu’une seule fois si l’échec semble temporaire.

Statut

Signification

Action

401

Pas de clé, clé invalide ou clé n'ayant pas accès à l'API SERP

Corrigez la clé ou le forfait. Ne réessayez pas.

Erreur de validation

Paramètre inconnu, manquant ou hors plage pour le moteur sélectionné

Corrigez la requête. Ne réessayez pas.

422 (error_type: "website")

Le moteur de recherche a renvoyé un corps non valide, un défi, un délai d'expiration ou un statut d'erreur

Réessayez une seule fois en espaçant les tentatives si le problème semble passager ; ensuite, consignez l'erreur et passez à la suite

429

Trop de requêtes simultanées

Ralentir, appliquer un délai d'attente avec variation, réessayer

500, 503

Erreur inattendue du gestionnaire ou défaillance temporaire du backend d'authentification

Réessayer plusieurs fois avec un délai de réessai

502

La soumission asynchrone a reçu une réponse non valide

Réessayer l'envoi avec un délai de réessai

Les erreurs d’authentification sont faciles à reconnaître. Une requête sans clé renvoie un code 401 avec le message « Accès refusé. Aucune clé api_key fournie. », tandis qu’une clé erronée ou non autorisée renvoie un code 401 avec Authentication failure: Invalid API key…. Tenter à nouveau l’une ou l’autre ne fait que répéter l’échec.

Les messages de validation nomment directement le problème : Parameter '<name>' not allowed., Parameter '<name>' is required., Parameter '<name>' must be in range …, et Parameter '<a>' cannot be used with parameter '<b>'. C’est pourquoi les paramètres copiés à partir d’anciens exemples échouent sur /v2: chaque moteur n'accepte que ses propres champs documentés.

Un code 429 « Too Many Requests » signifie que vous envoyez trop de requêtes à la fois. Réduisez votre nombre de requêtes simultanées et attendez avant de réessayer. Pour les codes 500, 502 et 503, quelques tentatives avec un recul exponentiel et un jitter maximal suffisent ; les délais aléatoires empêchent un groupe de workers de réessayer tous en même temps. La search() fonction du client Python met en œuvre l’ensemble de cette politique : elle s’arrête en cas de code 401, réessaie les codes pouvant faire l’objet d’une nouvelle tentative avec des délais aléatoires, réessaie une seule fois en cas de code 422 et abandonne après quatre tentatives.

Enregistrez deux en-têtes de réponse à chaque appel pour le suivi des coûts : Searchdata-Call-Credit-Usage (crédits utilisés par cet appel) et Searchdata-Current-Credit-Usage (utilisation actuelle du compte). Le client les renvoie sous la forme usage. Enregistrez le statut, les en-têtes et le contexte de la requête, mais jamais la clé.

Distinguez les échecs HTTP des modules vides dans vos métriques. Une réponse 200 sans related[] bloc correspond à une recherche réussie et ne doit pas déclencher de nouvelle tentative.

Documentation : Erreurs et en-têtes

Combien coûte l’API SERP ?

Les forfaits Google sont calculés en fonction du nombre de recherches mensuelles : Starter à 28 $ pour 10 000, Grow à 130 $ pour 50 000, Business à 550 $ pour 250 000 et Pro à 1 600 $ pour 1 000 000. La version d'essai comprend 100 recherches Google pour 0 $. Les tarifs de Bing, DuckDuckGo et Yandex sont établis sur devis en fonction de votre volume de travail, à compter d'octobre 2026.

Formule

Prix mensuel

Recherches Google

Coût effectif aux 1 000

Essai

0

100

—

Formule de base

28 $

10 000

2,80 $

Développement

130 $

50 000

2,60

Entreprise

550

250 000

2,20

Pro

1 600 $

1 000 000

1,60 $

Bing, DuckDuckGo, Yandex

Devis

En fonction de la charge de travail

—

Les prix sont indiqués en USD, à compter d'octobre 2026. Chaque forfait, y compris la version d'essai, inclut les données sur les produits Google, les emplacements mondiaux, l'analyse des SERP, le traitement en masse, tous les appareils, les formats de sortie JSON, CSV et HTML, ainsi que la recherche d'images. Les forfaits diffèrent par leur quota mensuel de recherches.

Pour déterminer la taille d’une formule, multipliez les éléments de votre grille de marché :

Recherches mensuelles = mots-clés × marchés × appareils × types de résultats × cycles d’actualisation par mois

Ajoutez ensuite une marge pour les tests et pour les mots-clés que vous ajouterez ultérieurement. Par exemple, 500 mots-clés × 2 pays × 2 appareils × 4 cycles hebdomadaires = 8 000 recherches par mois, ce qui correspond à la formule Starter avec une marge suffisante. Si vous passez ce même projet à des cycles quotidiens, cela représente environ 60 000 recherches, ce qui vous fait passer à la formule «Business». La fréquence de rafraîchissement multiplie tous les autres éléments ; définissez-la donc en fonction de la fréquence à laquelle les décisions dépendant de ces données sont réellement prises.

Profitez de la période d’essai pour valider vos requêtes représentatives, vos marchés, vos appareils et vos champs de sortie avant de vous engager sur un volume. Si vous comparez également d’autres fournisseurs, consultez les tarifs de l’API SERP chez différents prestataires.

Quelles sont les limites de l’API SERP, et dans quels cas un autre outil est-il plus adapté ?

L’API SERP renvoie des pages de résultats de recherche, et non les pages derrière chaque lien, et elle ne définit pas de classement universel. L’extraction des données de DuckDuckGo et Yandex relève de votre code, le mode asynchrone est réservé à Google, et les réponses du mode IA de Google constituent un produit distinct. Utilisez l’API Scraper, l’API Data ou un flux géré lorsque ces limites sont importantes.

  • Elle s’arrête à la page de résultats. Pour récupérer les pages derrière les liens, utilisez l’API Scraper. Découvrez comment utiliser l’API Scraper.
  • Le mode IA est distinct. Pour les réponses, citations et mentions de marque du mode IA de Google, utilisez les données du mode IA de Google issues de l’API Data.
  • Il s'agit d'une requête ponctuelle, et non d'un flux. Si vous avez besoin d'enregistrements récurrents et contrôlés, fournis selon un calendrier plutôt que d'effectuer vous-même des appels, consultez les flux de données des résultats de recherche.
  • Seuls les moteurs répertoriés sont pris en charge. Basez-vous sur les onze moteurs mentionnés dans la référence, et non sur d’anciennes pages de documentation.
  • Les moteurs HTML nécessitent une maintenance. Il vous appartient de mettre à jour les sélecteurs DuckDuckGo et Yandex lorsque leur balisage change.
  • Le mode asynchrone est réservé à Google. Prévoyez des workers synchrones pour Bing, DuckDuckGo et Yandex.
  • Un résultat correspond à une observation. Un classement décrit une requête, un marché, un appareil et un moment donnés. C’est à vous de déterminer si une absence a une incidence commerciale, et non à l’API.
  • L'utilisation est réglementée. Collectez les résultats publics éligibles conformément au contrat de service de WebScrapingAPI et aux exigences qui s'appliquent à vous.

Foire aux questions

Qu’est-ce qu’une API SERP ?

Une API SERP est un service web qui effectue une recherche pour vous et renvoie la page de résultats du moteur de recherche sous forme de données. Vous envoyez une requête, un moteur de recherche et des paramètres contextuels tels que le pays, la langue et l'appareil. L'API SERP de WebScrapingAPI renvoie des données JSON analysées pour Google et Bing, et du code HTML dans une enveloppe JSON pour DuckDuckGo et Yandex.

Comment utiliser une API SERP ?

Enregistrez votre clé API dans une variable d’environnement, puis envoyez une requête GET à https://serpapi.webscrapingapi.com/v2 en indiquant api_key, le moteur de recherche et votre requête. Ajoutez des contrôles de marché tels que « gl » et « hl » pour Google, lisez les résultats naturels dans la réponse JSON, puis enregistrez chaque ligne avec sa requête, son marché, son appareil et l’heure de capture.

Comment obtenir une clé API SERP ?

Créez un compte WebScrapingAPI, puis abonnez-vous à l’API SERP depuis le tableau de bord pour obtenir votre clé. La période d’essai comprend 100 recherches Google. Conservez la clé dans une variable d’environnement ou un gestionnaire de secrets sur votre serveur, et ne la placez jamais dans le code d’un navigateur, des dépôts publics, des journaux ou des captures d’écran.

Existe-t-il une période d’essai gratuite pour l’API SERP ?

Oui. L’essai de l’API SERP est gratuit et comprend 100 recherches Google, ce qui est suffisant pour tester vos mots-clés, marchés, appareils et résultats avant de choisir une formule. Les formules Google payantes commencent à 28 $ par mois pour 10 000 recherches. Les tarifs de Bing, DuckDuckGo et Yandex sont établis sur devis en fonction de votre charge de travail spécifique.

Qu’est-ce que le « scraping » SERP ?

Le scraping SERP consiste à collecter les résultats affichés par un moteur de recherche pour une requête donnée, tels que les titres, les liens, les positions et les fonctionnalités comme les recherches associées. Le faire soi-même implique de gérer les blocs et les changements de mise en page. Une API SERP confie cette tâche au fournisseur : votre code envoie une requête et reçoit les résultats sous forme de données.

Puis-je utiliser l’API SERP avec Python ?

Oui. Installez Requests, lisez votre clé à partir d’une variable d’environnement, puis transmettez api_key, engine et q dans l’argument params afin que Requests les encode. Définissez un délai d’expiration d’environ 120 secondes, réessayez en cas de réponses 429 et 5xx avec un délai de réessai, puis lisez la liste des résultats naturels à partir de la réponse JSON pour Google ou Bing.

Quels moteurs de recherche l’API SERP prend-elle en charge ?

Elle prend en charge Google, Bing, DuckDuckGo et Yandex. Google dispose également de moteurs spécialisés pour la recherche asynchrone, Maps, les avis Maps, les hôtels, les vols, les tendances et la recherche d’images inversée. Google et Bing renvoient du JSON analysé. DuckDuckGo et Yandex renvoient le code HTML de la page de résultats dans une enveloppe JSON, que votre application analyse.

L’API SERP résout-elle les CAPTCHA ?

Aucune page de l’API SERP ne le garantit. WebScrapingAPI gère l’infrastructure d’accès à la recherche derrière chaque requête, et lorsqu’un moteur de recherche renvoie une page de vérification, un statut d’erreur ou un délai d’expiration, l’API répond par une erreur 422 au lieu de transmettre des données erronées. Réessayez une fois si l’échec semble temporaire, puis consignez-le.

Pourquoi DuckDuckGo et Yandex renvoient-ils du code HTML au lieu de résultats analysés ?

Pour ces deux moteurs, l’API SERP renvoie la page de résultats source au format HTML dans une enveloppe JSON plutôt que sous forme de collections analysées. C’est votre application qui choisit ce qu’elle souhaite extraire. Inspectez une réponse réelle, associez-y des sélecteurs CSS, versionnez-les, conservez le code HTML brut et signalez tout écart de correspondance d’un sélecteur suite à un changement de mise en page.

Comment suivre le classement des mots-clés avec une API SERP ?

Choisissez un ensemble fixe de mots-clés, de pays, de langues et d’appareils, puis interrogez-les selon un calendrier défini. Enregistrez le classement, le titre et le lien de chaque résultat organique avec l’heure de capture et le marché. Comparez les résultats uniquement au sein d’un même marché et d’un même appareil, et considérez les fonctionnalités SERP manquantes comme une observation, et non comme une erreur.

Commencez par 100 recherches Google gratuites

L’API SERP renvoie les résultats de Google et Bing sous forme de JSON analysé, et les pages de résultats de DuckDuckGo et Yandex sous forme de code HTML dans une enveloppe JSON, avec des paramètres de marché, de langue et d’appareil pour chaque requête. Une fois que vous connaissez vos mots-clés, vos marchés et votre fréquence de mise à jour, comparez les formules de l’API SERP et choisissez le forfait qui vous convient.

À propos de l'auteur

Suciu Dan, cofondateur @ WebScrapingAPI

Suciu Dan

cofondateur

Suciu Dan est le cofondateur de WebScrapingAPI et rédige des guides pratiques destinés aux développeurs sur le web scraping avec Python et Ruby, ainsi que sur les infrastructures de proxy.

Web scraping avec AWS Lambda : guide pour Python et Java 2026
Guides

Web scraping avec AWS Lambda : guide pour Python et Java 2026

TL;DR: En bref : le web scraping avec AWS Lambda fonctionne mieux lorsque chaque invocation est courte, bien délimitée et peut faire l'objet d'une nouvelle tentative de manière indépendante. Commencez par utiliser les requêtes HTTP directes, AWS SAM et S3, puis ajoutez SQS, des conteneurs, le rendu dans un navigateur, des proxys ou une couche de récupération gérée uniquement lorsque la charge de travail démontre qu'elle en a besoin.

Suciu Dan33 min read
Lire l'article
Comment utiliser GoSpider : exploration, nettoyage des URL et extraction de données
Guides

Comment utiliser GoSpider : exploration, nettoyage des URL et extraction de données

TL;DR: En bref : GoSpider est un robot d'exploration en ligne de commande destiné à découvrir des URL, et non un outil complet de collecte de données structurées. Ce guide d'utilisation de GoSpider présente comment effectuer une exploration limitée, gérer correctement les résultats, transférer les données de Colly vers un fichier CSV, ainsi qu'une procédure de diagnostic pour les réponses 403 ou les pages nécessitant un rendu JavaScript.

Suciu Dan24 min read
Lire l'article
Comment récupérer les données de Redfin : Guide Python des données immobilières
Guides

Comment récupérer les données de Redfin : Guide Python des données immobilières

TL;DR: Redfin expose des points d'extrémité d'API cachés qui renvoient du JSON structuré pour les listes de propriétés, ce qui permet d'ignorer complètement l'analyse HTML fragile. Ce guide vous accompagne dans la construction d'un scraper Python qui extrait les données de location et de vente, effectue des recherches par emplacement, surveille les nouvelles inscriptions via des sitemaps XML et exporte des résultats propres au format CSV ou JSON.

Suciu Dan15 min read
Lire l'article

Commencez à créer

Prêt à faire évoluer votre système de collecte de données ?

Rejoignez plus de 2 000 entreprises qui utilisent WebScrapingAPI pour extraire des données Web à l'échelle de l'entreprise, sans aucun coût d'infrastructure.