La recherche de mots-clés ne se limite plus au Volume de recherche mensuel. Les trois plus riches sources gratuites d'intention de recherche — Google Autocomplete, les blocs People Also Ask (PAA) et les Related Searches — sont accessibles directement depuis la page de résultats et l'endpoint de suggestion de Google. Ce guide montre comment scraper Google People Also Ask et Autocomplete pour la recherche de mots-clés en Python, avec des proxies résidentiels géo-ciblés pour obtenir des suggestions propres et localisées.
Pourquoi scraper Google People Also Ask et Autocomplete pour la recherche de mots-clés
Chaque source gratuite capte une facette différente de l'intention utilisateur :
- Autocomplete (endpoint
suggestqueries.google.com/complete/search?client=chrome&q=) renvoie les requêtes les plus tapées par les internautes, triées par popularité relative. Idéal pour découvrir la longue traîne et les variantes de requêtes. - People Also Ask expose les questions que Google considère comme sémantiquement proches de la requête. Chaque accordéon peut se déplier pour révéler 3 à 5 nouvelles questions, créant une expansion récursive.
- Related Searches en bas de page liste 8 à 10 termes connexes, utiles pour cartographier un sujet.
Contrairement au Google Custom Search API qui facture 5 USD pour 1 000 requêtes et ne renvoie pas de suggestions, ces endpoints publics sont gratuits mais protégés par des limites de débit par IP. D'où la nécessité de proxies résidentiels.
Contexte technique : pourquoi Google bloque et localise
Google applique plusieurs mécanismes documentés dans ses consignes aux webmasters :
- Limites de débit par IP : au-delà d'environ 100 requêtes/min sur Autocomplete depuis une même IP, Google renvoie HTTP 429 ou vide la réponse.
- Biais de localisation : Autocomplete et PAA dépendent fortement de l'IP émettrice. Une requête depuis une IP française renvoie des suggestions différentes d'une IP allemande, même pour le même mot-clé.
- Détection d'automatisation : TLS fingerprint, headers inhabituels, absence de cookies de session — autant de signaux que Google utilise pour distinguer un navigateur humain d'un script.
Les proxies résidentiels résolvent ces trois problèmes : leurs IPs sont issues de vrais FAI (donc moins suspectes), elles peuvent être géo-ciblées par pays et ville, et la rotation de session répartit la charge. ProxyHat expose ces capacités via gate.proxyhat.com:8080 avec un format de username qui encode le pays et la ville.
Comparaison des sources gratuites de mots-clés
| Source | Endpoint / lieu | Intention captée | Volume typique par requête |
|---|---|---|---|
| Autocomplete | suggestqueries.google.com | Longue traîne, variantes | 10 suggestions |
| People Also Ask | SERP organique | Questions informationnelles | 4-8 questions initiales, récursif |
| Related Searches | Bas de SERP | Sujets connexes | 8-10 termes |
1. Récupérer Autocomplete en JSON avec curl
L'endpoint client=chrome renvoie du JSON lisible directement :
curl -s --proxy http://user-country-DE-city-berlin:pass@gate.proxyhat.com:8080 \
'https://suggestqueries.google.com/complete/search?client=chrome&q=python%20web%20scraping&gl=de&hl=de' \
-H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
La réponse est un tableau : [requête, [suggestions...], [types...], [fréquences...]]. Les fréquences sont relatives (non documentées officiellement) mais utiles pour trier.
2. Scraper Autocomplete en Python avec httpx et ProxyHat
import httpx
import json
import asyncio
from typing import List
PROXY = "http://user-country-DE-city-berlin:pass@gate.proxyhat.com:8080"
SUGGEST_URL = "https://suggestqueries.google.com/complete/search"
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36",
"Accept-Language": "de-DE,de;q=0.9,en;q=0.8",
}
async def fetch_autocomplete(client: httpx.AsyncClient, keyword: str, gl: str = "de", hl: str = "de") -> List[str]:
params = {"client": "chrome", "q": keyword, "gl": gl, "hl": hl}
try:
resp = await client.get(SUGGEST_URL, params=params, headers=HEADERS, timeout=10.0)
resp.raise_for_status()
data = resp.json()
return data[1] if isinstance(data, list) and len(data) > 1 else []
except (httpx.HTTPError, json.JSONDecodeError) as exc:
print(f"Erreur pour '{keyword}': {exc}")
return []
async def main():
async with httpx.AsyncClient(proxy=PROXY) as client:
suggestions = await fetch_autocomplete(client, "python web scraping")
for s in suggestions:
print(s)
if __name__ == "__main__":
asyncio.run(main())
Astuce production : ajoutez un retry avec backoff exponentiel (ex. tenacity) et limitez la concurrence à 5-10 requêtes parallèles pour éviter HTTP 429.
3. Expander un mot-clé en centaines de variantes
La technique classique : préfixer le mot-clé avec chaque lettre a-z et des modificateurs (comment, pourquoi, meilleur, vs, 2026…). Un seul seed devient ~300 suggestions après dédup.
import string
import asyncio
import httpx
from itertools import chain
MODIFIERS = ["comment", "pourquoi", "meilleur", "prix", "avis", "vs", "2026", "gratuit", "alternative"]
def build_queries(seed: str) -> List[str]:
queries = []
for letter in string.ascii_lowercase:
queries.append(f"{seed} {letter}")
for mod in MODIFIERS:
queries.append(f"{mod} {seed}")
queries.append(f"{seed} {mod}")
return queries
async def expand_seed(seed: str, proxy: str, gl: str, hl: str) -> List[str]:
queries = build_queries(seed)
sem = asyncio.Semaphore(8) # concurrence limitée
async with httpx.AsyncClient(proxy=proxy) as client:
async def guarded(q):
async with sem:
await asyncio.sleep(0.3) # politesse
return await fetch_autocomplete(client, q, gl, hl)
results = await asyncio.gather(*[guarded(q) for q in queries])
return sorted(set(chain.from_iterable(results)))
# Usage : expand_seed("python web scraping", PROXY, "de", "de")
4. Extraire les questions People Also Ask avec Playwright
Le bloc PAA est rendu dynamiquement : il faut un vrai navigateur pour cliquer sur les accordéons et déclencher l'apparition des questions suivantes. Playwright est idéal pour cela.
from playwright.async_api import async_playwright
import asyncio
import json
PROXY_SERVER = "gate.proxyhat.com:8080"
PROXY_USER = "user-country-DE-city-berlin"
PROXY_PASS = "pass"
async def scrape_paa(keyword: str, max_depth: int = 3) -> list[dict]:
questions = []
async with async_playwright() as p:
browser = await p.chromium.launch(
headless=True,
proxy={
"server": f"http://{PROXY_SERVER}",
"username": PROXY_USER,
"password": PROXY_PASS,
},
)
context = await browser.new_context(
locale="de-DE",
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0 Safari/537.36",
)
page = await context.new_page()
await page.goto(f"https://www.google.com/search?q={keyword}&gl=de&hl=de", wait_until="domcontentloaded")
await page.wait_for_timeout(2000)
for _ in range(max_depth):
elements = await page.query_selector_all('div[jsname] div[role="heading"]')
for el in elements:
text = (await el.inner_text()).strip()
if text.endswith("?") and text not in [q["question"] for q in questions]:
# tenter de cliquer pour révéler la question suivante
try:
await el.click(timeout=2000)
await page.wait_for_timeout(800)
except Exception:
pass
questions.append({"question": text, "source": "paa"})
await page.wait_for_timeout(1000)
await browser.close()
return questions
# asyncio.run(scrape_paa("python web scraping"))
Pour extraire aussi les citations sources des réponses PAA, ciblez les sélecteurs cite dans le conteneur de réponse. Ces URLs sont des mines d'or pour identifier les sites qui font autorité sur un sujet.
5. Expansion récursive des PAA
Chaque question PAA peut devenir un nouveau seed pour Autocomplete et une nouvelle requête SERP. Une graine de 1 mot-clé peut générer 200+ questions en 3 niveaux de profondeur.
async def recursive_paa(seed: str, depth: int = 2, proxy: str = PROXY) -> list[dict]:
seen = set()
queue = [seed]
all_q = []
for level in range(depth):
next_level = []
tasks = []
for kw in queue:
if kw in seen:
continue
seen.add(kw)
tasks.append(scrape_paa(kw, max_depth=2))
results = await asyncio.gather(*tasks, return_exceptions=True)
for res in results:
if isinstance(res, list):
for item in res:
q = item["question"]
if q not in seen:
all_q.append(item)
next_level.append(q)
queue = next_level
return all_q
6. Déduplication, clustering par intention et export CSV
import csv
import re
from collections import defaultdict
INTENT_PATTERNS = {
"informational": [r"^comment", r"^pourquoi", r"^qu'est-ce", r"^c'est quoi"],
"commercial": [r"meilleur", r"avis", r"comparatif", r"top"],
"transactional": [r"acheter", r"prix", r"gratuit", r"telecharger"],
"navigational": [r"login", r"connexion", r"site officiel"],
}
def classify_intent(query: str) -> str:
q = query.lower()
for intent, patterns in INTENT_PATTERNS.items():
if any(re.search(p, q) for p in patterns):
return intent
return "informational"
def dedupe_and_cluster(queries: list[str]) -> list[dict]:
unique = sorted(set(q.lower().strip() for q in queries))
clusters = defaultdict(list)
for q in unique:
clusters[classify_intent(q)].append(q)
return [{"intent": k, "count": len(v), "queries": v} for k, v in clusters.items()]
def export_csv(clusters: list[dict], path: str = "keywords.csv"):
with open(path, "w", newline="", encoding="utf-8") as f:
w = csv.writer(f)
w.writerow(["intent", "keyword"])
for c in clusters:
for q in c["queries"]:
w.writerow([c["intent"], q])
# Usage :
# clusters = dedupe_and_cluster(all_suggestions + [q["question"] for q in paa_results])
# export_csv(clusters)
Le CSV résultant alimente directement un plan de contenu : une page par intention commerciale, un bloc FAQ pour les questions informationnelles, un glossaire pour les définitions.
Configurer ProxyHat pour le géo-ciblage
ProxyHat encode le pays et la ville dans le username, ce qui permet de cibler précisément la locale des suggestions :
user-country-DE-city-berlin:pass@gate.proxyhat.com:8080— suggestions allemandes depuis Berlin.user-country-FR-city-paris:pass@gate.proxyhat.com:8080— suggestions françaises.user-session-abc123:pass@gate.proxyhat.com:8080— session sticky pour conserver la même IP pendant tout un crawl PAA.
Voir la liste complète des localisations ProxyHat et la tarification pour estimer votre volume. Pour des cas d'usage avancés, consultez la documentation ProxyHat.
Erreurs courantes et cas limites
- HTTP 429 en rafale : la concurrence trop élevée sur Autocomplete déclenche le rate limit. Plafonnez à 8-10 connexions par IP et ajoutez 1-3 s de jitter.
- Suggestions vides : souvent un problème de
gl/hlincohérent avec l'IP du proxy. Alignez la locale du proxy avec ces paramètres. - PAA absent de la SERP : certaines requêtes très commerciales n'affichent pas de bloc PAA. Testez d'abord manuellement.
- Sélecteurs Playwright cassés : Google change son DOM fréquemment. Préférez des sélecteurs basés sur
roleetjsnameplutôt que des classes CSS. - Biais de cache : si vous relancez la même requête, Google peut servir une version mise en cache. Variez les sessions (
user-session-XYZ) pour des données fraîches.
Considérations éthiques et légales
Les suggestions Autocomplete et les blocs PAA sont des données publiques affichées dans le navigateur. Leur extraction pour de la recherche de mots-clés est largement pratiquée, mais quelques règles s'imposent :
- Respectez
robots.txtde Google pour les chemins listés. - Limitéz votre débit : 1-3 requêtes/s par IP est raisonnable.
- À très grande échelle (100 000+ requêtes/jour), préférez l'API officielle Google Custom Search ou des fournisseurs tiers comme DataForSEO pour rester conforme aux Conditions d'utilisation.
- Ne stockez pas de données personnelles (noms, emails) si elles apparaissent dans les suggestions.
Pour approfondir les bonnes pratiques de scraping, lisez notre guide sur les cas d'usage de web scraping et le suivi de SERP.
Points clés à retenir
- Autocomplete, PAA et Related Searches couvrent trois intentions distinctes : longue traîne, questions, sujets connexes.
- Un seed + préfixes a-z + modificateurs génère ~300 suggestions ; la récursion PAA ajoute 200+ questions en 2-3 niveaux.
- Les proxies résidentiels géo-ciblés (gate.proxyhat.com:8080, username -country-XX-city-YY) sont essentiels pour des suggestions localisées et éviter HTTP 429.
- Clusterisez par intention (informationnelle, commerciale, transactionnelle) avant d'exporter en CSV pour le plan de contenu.
- Throttlez poliment (1-3 req/s/IP) et préférez les APIs officielles à très grande échelle.
FAQ
Comment scraper Google People Also Ask et Autocomplete en Python ?
Utilisez l'endpoint public suggestqueries.google.com/complete/search?client=chrome&q= pour Autocomplete (réponse JSON), et Playwright pour cliquer sur les accordéons PAA et extraire les questions. Combinez avec des proxies résidentiels géo-ciblés via gate.proxyhat.com:8080 pour éviter les blocages par IP et obtenir des suggestions localisées.
Pourquoi utiliser des proxies pour scraper Autocomplete et PAA ?
Les appels rapides vers Google déclenchent des limites de débit par IP (souvent HTTP 429 au-delà de ~100 req/min) et un biais linguistique local. Les proxies résidentiels avec géo-ciblage pays/ville renvoient des suggestions localisées propres et répartissent la charge entre plusieurs IP de vrais FAI.
Quel type de proxy fonctionne le mieux pour scraper Google PAA ?
Les proxies résidentiels sont préférés car leurs adresses IP proviennent de vrais FAI et imitent le trafic humain, ce qui réduit CAPTCHAs et blocages. Les proxies datacenter sont plus rapides mais plus facilement détectés par Google. Pour PAA avec Playwright, une session sticky résidentielle est idéale.
Comment éviter les blocages en scrapant People Also Ask ?
Limitez la concurrence (5-10 requêtes parallèles), faites pivoter les sessions résidentielles, ajoutez des délais aléatoires de 1-3 secondes, géo-ciblez par pays, et respectez robots.txt. Préférez l'API officielle Google Custom Search à très grande échelle (au-delà de 100 000 requêtes/jour).





