Faut-il bloquer les robots d'exploration IA ? Décider bot par bot, appliquer par IP
Bloquez les robots d'exploration IA selon leur rôle : arrêtez les bots d'entraînement, gardez les bots de recherche IA et renvoyez un 403 aux faux GPTBots en vérifiant l'IP. Avec du code nginx et Express testé.

Votre journal d'accès montre GPTBot, ClaudeBot et quelques noms que vous ne reconnaissez pas. Les guides que vous trouvez disent tous la même chose : listez les User-Agents dans robots.txt, puis bloquez les mêmes chaînes dans la configuration de votre serveur.
Ce conseil a une faille. Un User-Agent est une chaîne que le client saisit, et saisir « GPTBot » ne coûte rien. Une liste de blocage de noms arrête les bots honnêtes, qui auraient de toute façon respecté robots.txt, et laisse passer tous les scrapers qui empruntent un nom que vous avez autorisé. Le nom est une affirmation et l'IP en est la preuve, le même principe que la détection des bots par IP en général.
Ci-dessous, nous classons les bots par rôle, montrons ce que robots.txt peut et ne peut pas faire, faisons passer quatre vraies adresses de robots d'exploration dans notre API et vous donnons une politique en trois niveaux avec du code nginx et Express testé. Un GPTBot usurpé reçoit un 403. Un vrai Googlebot, jamais.

Faut-il bloquer les robots d'exploration IA ? Cela dépend du rôle du bot
Vous devriez bloquer les robots d'exploration IA dont le rôle vous déplaît et garder ceux qui vous envoient des lecteurs. Les bots IA remplissent trois rôles différents, et bloquer chacun d'eux vous coûte quelque chose de différent.
- Les robots d'entraînement collectent des pages susceptibles d'entraîner de futurs modèles. OpenAI indique qu'interdire GPTBot « signale que le contenu d'un site ne doit pas être utilisé pour entraîner des modèles de fondation d'IA générative ». Les bloquer ne coûte rien en recherche.
- Les bots de recherche IA indexent des pages pour qu'un assistant puisse les citer. OpenAI indique que les sites qui ont exclu OAI-SearchBot « ne seront pas affichés dans les réponses de recherche de ChatGPT ». Les bloquer vous coûte des citations et les clics qui vont avec.
- Les récupérateurs déclenchés par l'utilisateur chargent une page parce qu'une personne a demandé à un assistant de la lire. Les bloquer fait échouer la demande de cette personne.
Un éditeur derrière un paywall a une raison claire de refuser l'entraînement. Une marque qui veut que les assistants la recommandent devrait garder les bots de recherche. La plupart des sites finissent par un compromis : non à l'entraînement, oui à la recherche, une limite de vitesse pour les récupérateurs. Nous expliquons quel bot OpenAI bloquer et ce que coûte chaque choix dans un article séparé. Les agents qui achètent pour le compte d'un utilisateur posent un problème différent, traité dans la fraude des agents d'achat IA au checkout.
Quels bots IA entraînent et lesquels vous citent
Ce tableau classe par rôle les bots IA que vous risquez le plus de voir, avec ce que chaque opérateur dit de robots.txt. Chaque cellule provient de la propre page de l'opérateur, consultée le 20 octobre 2026.
| Bot | Opérateur | Rôle | robots.txt, selon les mots de l'opérateur |
|---|---|---|---|
| GPTBot | OpenAI | Entraînement | Disallow signifie que le contenu « ne doit pas être utilisé pour l'entraînement » |
| OAI-SearchBot | OpenAI | Recherche IA | Les sites exclus ne sont pas affichés dans les réponses de recherche de ChatGPT |
| ChatGPT-User | OpenAI | Récupération déclenchée par l'utilisateur | Les règles robots.txt « peuvent ne pas s'appliquer » |
| ClaudeBot | Anthropic | Entraînement | Respecte robots.txt et Crawl-delay |
| Claude-SearchBot | Anthropic | Recherche IA | Respecte robots.txt et Crawl-delay |
| Claude-User | Anthropic | Récupération déclenchée par l'utilisateur | Respecte robots.txt et Crawl-delay |
| Google-Extended | Jeton pour l'usage par l'IA, pas de robot | Uniquement un jeton robots.txt, sans User-Agent propre | |
| Googlebot | Recherche, pas un bot IA à bloquer | Les robots courants « respectent toujours les règles robots.txt lorsqu'ils explorent automatiquement » | |
| PerplexityBot | Perplexity | Recherche IA | Non précisé ; Perplexity recommande de l'autoriser |
| Perplexity-User | Perplexity | Récupération déclenchée par l'utilisateur | « ignore généralement les règles robots.txt » |
| CCBot | Common Crawl | Archive ouverte du web que chacun peut télécharger | Consulte d'abord robots.txt ; respecte Crawl-delay |
| Applebot-Extended | Apple | Jeton pour l'usage d'entraînement IA, pas de robot | Apple indique qu'il « n'explore pas les pages web » |
| Meta-ExternalAgent | Meta | Entraînement et indexation | Non précisé ; Meta documente une règle Disallow pour lui |
| Bytespider | ByteDance | Non documenté sur une page que nous avons pu ouvrir | Non documenté sur une page que nous avons pu ouvrir |
La preuve est une question distincte de la politique. Un bot ne peut être vérifié que si son opérateur publie d'où il explore :
| Opérateur | Fichier de plages | Préfixes au 20 octobre 2026 | DNS inverse documenté | Vérifié par GeoIPHub |
|---|---|---|---|---|
| OpenAI | gptbot.json, plus searchbot.json et chatgpt-user.json | 18, 39 et 234 | Non documenté | Oui, les trois |
| Anthropic | bots.json, un seul fichier pour les trois bots | 38 (fichier daté du 7 octobre 2026) | Non documenté | Oui, une correspondance est nommée ClaudeBot |
| common-crawlers.json et quatre autres | 317 pour les robots courants | Oui : googlebot.com, google.com, googleusercontent.com | Oui | |
| Perplexity | perplexitybot.json et perplexity-user.json | 8 et 4 | Non documenté | Oui |
| Common Crawl | ccbot.json | 5 | Oui, crawl.commoncrawl.org, IPv4 uniquement | Oui |
| Apple | applebot.json | 24 | Oui, applebot.apple.com | Oui, pour Applebot |
| Meta | Non publié | Non publié | Non documenté | Correspondance d'ASN uniquement, verified: false |
| ByteDance | Nous n'en avons trouvé aucun | Aucun trouvé | Non documenté | Non |
Avant de copier une liste depuis un autre site, vérifiez ses noms. Certains guides bien classés sur ce sujet citent encore anthropic-ai et Claude-Web, que la page actuelle d'Anthropic ne liste pas, et oublient Claude-SearchBot et Claude-User. Une liste obsolète bloque des chaînes que personne n'envoie.
Ce que robots.txt peut et ne peut pas faire
robots.txt peut dire aux bots bien élevés ce que vous voulez, et il ne peut rien arrêter. La RFC 9309, le standard qui le définit, indique : « These rules are not a form of access authorization » (ces règles ne constituent pas une forme d'autorisation d'accès). La question de savoir si l'ignorer a des conséquences juridiques relève d'un avocat.
Il reste le premier niveau, parce que la plupart des bots nommés le lisent. Ce fichier refuse l'entraînement, accueille la recherche IA et laisse la recherche Google tranquille :
# Training: no
User-agent: GPTBot
User-agent: ClaudeBot
User-agent: CCBot
User-agent: Google-Extended
User-agent: Applebot-Extended
User-agent: Meta-ExternalAgent
User-agent: Bytespider
Disallow: /
# AI search: yes
User-agent: OAI-SearchBot
User-agent: PerplexityBot
Allow: /
# Anthropic honours Crawl-delay (seconds between requests)
User-agent: Claude-SearchBot
Allow: /
Crawl-delay: 2
Quatre détails déterminent si ce fichier fait ce que vous pensez :
- Google-Extended et Applebot-Extended sont des jetons, pas des robots. La page des robots courants de Google, mise à jour le 15 octobre 2026, indique que « Google-Extended n'a pas de chaîne User-Agent de requête HTTP distincte » et qu'il « n'a pas d'incidence sur l'inclusion d'un site dans la recherche Google ». Aucune requête n'arrive jamais de Google-Extended, donc aucune règle IP ne peut le bloquer. La page Applebot d'Apple indique qu'Applebot-Extended « n'explore pas les pages web » non plus.
- Bloquer Googlebot pour empêcher l'usage par l'IA vous coûte la recherche. C'est aussi le cas d'un groupe
User-agent: *avecDisallow: /. - Les récupérateurs déclenchés par l'utilisateur peuvent ignorer le fichier. OpenAI dit de ChatGPT-User que « les règles robots.txt peuvent ne pas s'appliquer ». Perplexity indique que Perplexity-User « ignore généralement les règles robots.txt ».
- Les modifications ne sont pas instantanées. OpenAI indique qu'« il peut falloir environ 24 heures après une mise à jour du robots.txt d'un site pour que nos systèmes s'ajustent ».
Les fichiers plus récents comme llms.txt et ai.txt sont des propositions. Comme robots.txt, ils demandent et n'appliquent rien.
L'erreur inverse consiste à mettre des robots de recherche sur une liste de blocage de « bots IA ». Le guide de Contentstack pour bloquer les robots d'exploration IA montre une fonction edge dont la liste de bots inclut googlebot et bingbot à côté de gptbot et claudebot, et leur répond à tous « Forbidden: AI crawlers are not allowed. » Copiée telle quelle, cette règle retire un site de la recherche Google et Bing. Quiconque se fait passer pour Googlebot est un faux Googlebot, un problème différent avec une solution différente.
Vrai robot ou usurpation : comment fonctionne la vérification
Vous distinguez un vrai robot d'une usurpation en comparant l'IP de connexion à ce que publie l'opérateur nommé. Laquelle des trois méthodes fonctionne dépend de l'opérateur.
- Les fichiers de plages. OpenAI, Anthropic, Perplexity, Common Crawl, Apple et Google publient des listes JSON de leurs préfixes. Pour OpenAI et Anthropic, c'est la seule méthode, car leurs adresses n'ont pas de DNS inverse.
- Le DNS inverse confirmé dans les deux sens. Le guide de vérification de Google vous fait résoudre l'IP en un nom, vérifier le domaine, puis résoudre le nom en retour et confirmer qu'il renvoie la même IP. Apple et Common Crawl documentent la même méthode.
- Les requêtes signées (Web Bot Auth). Un bot signe chaque requête avec une clé publiée. C'est encore un brouillon, traité dans la section edge plus bas.
Notre guide pour vérifier un robot d'exploration IA par IP détaille les trois. Nous avons interrogé quatre adresses de robots d'exploration à 04:37 UTC le 20 octobre 2026, sans clé. Voici l'adresse ClaudeBot, abrégée, imbrication conservée et valeurs non modifiées :
{
"ip": "216.73.216.10",
"asn": {
"asn": 16509,
"org": "AMAZON-02 - Amazon.com, Inc."
},
"threat": {
"is_crawler": true,
"crawler": {
"verified": true,
"name": "ClaudeBot",
"operator": "Anthropic",
"category": "ai",
"verification_method": "ip_range_list"
}
},
"scoring": {
"fraud_score": 0,
"recommended_action": "allow",
"detection_methods": ["datacenter_ip", "no_ptr_datacenter", "verified_crawler"]
}
}
Les trois autres, issues de la même exécution :
| IP | crawler.name / opérateur / catégorie | Vérifié, méthode | Score, action | detection_methods | ASN |
|---|---|---|---|---|---|
| 132.196.86.1 | GPTBot / OpenAI / ai | true, ip_range_list | 0, allow | datacenter_ip, no_ptr_datacenter, verified_crawler | 8075 MICROSOFT-CORP-MSN-AS-BLOCK |
| 66.249.66.1 | Googlebot / Google / search_engine | true, ip_range_list | 0, allow | datacenter_ip, verified_crawler | 15169 GOOGLE |
| 107.178.192.1 | GoogleUserTriggeredFetcher / Google / fetcher | true, ip_range_list | 0, allow | datacenter_ip, rdns_hosting, verified_crawler | 396982 GOOGLE-CLOUD-PLATFORM |
L'adresse GPTBot est le premier hôte de 132.196.86.0/24, le premier préfixe du fichier gptbot.json d'OpenAI. Nous avons ensuite demandé les noms au DNS, à 04:45 UTC :
$ dig -x 216.73.216.10 +short # ClaudeBot: NXDOMAIN, no name
$ dig -x 132.196.86.1 +short # GPTBot: NXDOMAIN, no name
$ dig -x 66.249.66.1 +short
crawl-66-249-66-1.googlebot.com.
$ dig crawl-66-249-66-1.googlebot.com +short
66.249.66.1
C'est le constat que la plupart des guides manquent. ClaudeBot et GPTBot n'ont pas d'enregistrement PTR, donc le DNS inverse ne peut pas les vérifier. Le fichier de plages est le seul contrôle possible. no_ptr_datacenter se déclenche sur les deux, et pourtant le score reste à 0, parce que verified_crawler est un signal disculpant. Pour ces opérateurs, l'absence de PTR est normale. Googlebot passe dans les deux sens : son nom se résout en retour vers la même adresse.
Deux limites s'appliquent. Le champ category vaut « ai » pour les bots IA d'entraînement comme pour les autres, donc le code de politique doit se baser sur crawler.name. Et la requête ne voit qu'une IP, jamais le User-Agent, donc l'API ne signale jamais d'usurpation. La comparaison entre le nom revendiqué et le nom prouvé se fait dans votre code. Vous pouvez effectuer le même contrôle à la main dans notre outil de recherche IP.
Une politique en trois niveaux : demander, vérifier, limiter
Une politique qui tient la route comporte trois niveaux : demander avec robots.txt, vérifier chaque revendication de bot par rapport à son IP et limiter le débit de tout le reste. Bloquez par rôle, appliquez par IP, et ne mettez jamais Googlebot sur une liste de blocage IA.
Niveau 1 : demander. robots.txt porte votre décision bot par bot, plus Crawl-delay pour les opérateurs qui le respectent.
Niveau 2 : vérifier. Lorsqu'un User-Agent nomme un bot, interrogez l'IP de connexion et comparez les noms. Si l'IP n'appartient pas à ce bot, la requête reçoit un 403. Si elle lui appartient, appliquez votre décision de niveau 1, de sorte qu'un GPTBot vérifié qui ignore votre Disallow soit tout de même refusé.
Niveau 3 : limiter. Tout le reste est soumis à une limite de débit : les requêtes qui ne revendiquent aucun bot, les bots qui ne peuvent pas être vérifiés et les récupérateurs qui agissent pour une personne.
| Cas | Exemple | Action |
|---|---|---|
| Bot vérifié que vous autorisez | Googlebot depuis 66.249.66.1 | Servir normalement, sans limite de débit |
| Bot vérifié que vous avez refusé, qui arrive quand même | GPTBot depuis 132.196.86.1 alors que GPTBot est interdit | 403 |
| Revendication non vérifiée : l'UA nomme un bot, l'IP ne correspond pas | UA GPTBot depuis 216.73.216.10, une adresse Anthropic | 403, ou un challenge si vous préférez |
| Bot impossible à vérifier | Bytespider, Meta-ExternalAgent | Limiter le débit ; robots.txt est votre seul levier |
| Aucune revendication de bot | Navigateurs, et scrapers qui se font passer pour des navigateurs | Limiter le débit par IP |
La troisième ligne est la plus instructive. 216.73.216.10 est un robot vérifié, mais pas celui que nomme la requête, donc un contrôle qui demande seulement « est-ce un robot vérifié ? » le laisserait entrer. Comparez les noms. De même, 107.178.192.1 est un récupérateur Google vérifié, mais une requête qui en provient en se présentant comme Googlebot n'est pas Googlebot.
Journalisez chaque échec de niveau 2. Une adresse hors des plages publiées signifie généralement une usurpation, mais il peut s'agir d'un préfixe que l'opérateur vient d'ajouter. Nos fichiers de plages sont récupérés à nouveau chaque jour et la base de recherche reconstruite chaque jour, donc la vérification d'un nouveau préfixe peut prendre jusqu'à environ deux jours.
L'appliquer dans nginx et Express, avec un test de GPTBot usurpé
L'application tient en un petit service Express qui effectue la requête, plus une configuration nginx qui l'interroge pour chaque requête se présentant comme un bot. nginx standard ne peut pas appeler une API HTTP en ligne, donc le module auth_request envoie une sous-requête au vérificateur et nginx met la réponse en cache. Sans nginx, le même fichier protège à lui seul une application Express.
Le vérificateur compare le User-Agent aux jetons de bots actuels, interroge l'IP avec GET https://api.geoiphub.com/v1/lookup/{ip} et l'en-tête x-api-key, met le résultat en cache pendant une heure et compare threat.crawler.name au nom revendiqué. Il a besoin d'une table de correspondance des noms, car l'API écrit certains noms sans le trait d'union : OAISearchBot, ChatGPTUser, PerplexityUser. Consultez les champs crawler dans la documentation de l'API.
// bot-gate.js: tier 2 (verify the IP behind a bot claim) and tier 3 (rate-limit the rest).
// Tested with Node 24.20.0, Express 5.3.0 and express-rate-limit 8.7.1.
const express = require('express');
const { rateLimit } = require('express-rate-limit');
const { BlockList, isIP } = require('node:net');
const API_KEY = process.env.GEOIPHUB_KEY; // production: always set a key
const CACHE_MS = 60 * 60 * 1000; // one hour per IP
const cache = new Map(); // ip: { at, crawler }
// Your policy: User-Agent tokens you refuse even when verified. Everything verified and not listed passes.
const BLOCKED = new Set((process.env.BLOCKED_BOTS || 'GPTBot,ClaudeBot,CCBot').split(','));
// Maps each User-Agent token to the crawler.name our API returns for that operator's range file.
// Anthropic publishes one file for all three of its bots, so a match comes back as ClaudeBot.
const EXPECTED = {
'GPTBot': 'GPTBot',
'OAI-SearchBot': 'OAISearchBot',
'ChatGPT-User': 'ChatGPTUser',
'ClaudeBot': 'ClaudeBot',
'Claude-User': 'ClaudeBot',
'Claude-SearchBot': 'ClaudeBot',
'PerplexityBot': 'PerplexityBot',
'Perplexity-User': 'PerplexityUser',
'CCBot': 'CCBot',
'Googlebot': 'Googlebot',
'bingbot': 'Bingbot',
'Applebot': 'Applebot',
};
// Longest tokens first, so "Claude-SearchBot" is not read as a shorter token.
const TOKENS = Object.keys(EXPECTED).sort((a, b) => b.length - a.length);
// A real crawler never connects from a private or loopback address.
const privateNets = new BlockList();
for (const [net, bits] of [['10.0.0.0', 8], ['172.16.0.0', 12], ['192.168.0.0', 16],
['127.0.0.0', 8], ['100.64.0.0', 10]]) privateNets.addSubnet(net, bits, 'ipv4');
privateNets.addSubnet('fc00::', 7, 'ipv6');
privateNets.addAddress('::1', 'ipv6');
function claimedBot(ua = '') {
const lower = ua.toLowerCase();
return TOKENS.find((t) => lower.includes(t.toLowerCase())) || null;
}
async function lookupCrawler(ip) {
const hit = cache.get(ip);
if (hit && Date.now() - hit.at < CACHE_MS) return hit.crawler;
const res = await fetch(`https://api.geoiphub.com/v1/lookup/${ip}`, {
headers: API_KEY ? { 'x-api-key': API_KEY } : {}, // keyless only for a local test
signal: AbortSignal.timeout(1500),
});
if (!res.ok) throw new Error(`lookup ${res.status}`);
const data = await res.json();
cache.set(ip, { at: Date.now(), crawler: data.threat.crawler });
return data.threat.crawler;
}
async function verifyBot(req, res, next) {
const claim = claimedBot(req.get('user-agent'));
if (!claim) return next(); // no bot claim: tier 3 handles it
const ip = req.ip.replace(/^::ffff:/, '');
const family = isIP(ip) === 6 ? 'ipv6' : 'ipv4';
if (privateNets.check(ip, family)) {
return res.status(403).send(`unverified ${claim} claim\n`);
}
let crawler;
try {
crawler = await lookupCrawler(ip);
} catch (err) {
// Fail mode: never fail open to "verified". Mark it and let the rate limiter decide.
req.botUnverified = true;
return next();
}
// The API never flags a spoof: it sees only the IP, not the User-Agent.
// The spoof check is this comparison, in your code.
const verified = crawler.verified === true && crawler.name === EXPECTED[claim];
if (!verified) return res.status(403).send(`unverified ${claim} claim\n`);
if (BLOCKED.has(claim)) return res.status(403).send(`${claim} is blocked by policy\n`);
req.verifiedBot = crawler.name;
return next();
}
// Tier 3: everyone without a verified bot name, keyed per IPv4 address or per IPv6 /64.
// nginx auth_request understands only 2xx, 401 and 403, so the verifier endpoint answers 403.
const limiter = rateLimit({
windowMs: 60 * 1000,
limit: 120,
ipv6Subnet: 64,
skip: (req) => Boolean(req.verifiedBot),
handler: (req, res) => res.set('Cache-Control', 'no-store')
.status(req.path === '/_verify_bot' ? 403 : 429).send('rate limited\n'),
});
const app = express();
app.set('trust proxy', 'loopback'); // only nginx on this host may set X-Forwarded-For
// Endpoint for nginx auth_request: 204 lets the request through, 403 stops it.
// After a failed lookup, no-store keeps nginx from caching the 204, so the limiter sees every request.
app.get('/_verify_bot', verifyBot, limiter, (req, res) => {
if (req.botUnverified) res.set('Cache-Control', 'no-store');
res.sendStatus(204);
});
// Standalone use without nginx: protect every route.
app.use(verifyBot, limiter);
app.get('/', (req, res) => res.send('ok\n'));
app.listen(3000, '127.0.0.1');
Trois choix sont délibérés. Si la requête échoue ou prend plus de 1,5 seconde, la requête n'est jamais considérée comme vérifiée ; elle passe au limiteur de débit. Derrière nginx, cette réponse est envoyée avec no-store, donc nginx ne la met pas en cache et le vérificateur compte chaque requête dans la même limite. La liste de politique contient des jetons User-Agent, donc refuser ClaudeBot ne refuse pas Claude-SearchBot, même si les deux reviennent de la requête sous le nom ClaudeBot. trust proxy est limité à loopback, car sinon un client pourrait envoyer son propre X-Forwarded-For et choisir l'adresse que vous vérifiez. Et seules les revendications de bot sont interrogées, donc le volume suit le trafic de bots, pas les pages vues. L'offre gratuite couvre 1 500 requêtes par jour avec une clé, tous les champs inclus.
Le côté nginx associe le User-Agent à un bot revendiqué, saute la sous-requête lorsqu'il n'y a pas de revendication et met en cache le 204 ou le 403 du vérificateur par adresse et par bot pendant une heure, sauf les réponses marquées no-store :
# Goes in the http {} block. Tested with nginx 1.30.6 built with --with-http_auth_request_module.
# Which bot does the User-Agent claim? Empty means no claim.
map $http_user_agent $claimed_bot {
default "";
"~*(GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|Claude-User|Claude-SearchBot|PerplexityBot|Perplexity-User|CCBot|Googlebot|bingbot|Applebot)" $1;
}
# Tier 3 key: rate-limit requests with no bot claim. Claims go to tier 2 instead.
map $claimed_bot $limit_key {
"" $binary_remote_addr;
default "";
}
limit_req_zone $limit_key zone=perip:10m rate=10r/s;
# Cache the verifier's answer per address and claimed bot for one hour.
proxy_cache_path /var/cache/nginx/botcheck keys_zone=botcheck:1m max_size=10m inactive=1h;
server {
listen 8080;
location / {
limit_req zone=perip burst=20 nodelay;
limit_req_status 429;
auth_request /_verify_bot;
proxy_pass http://127.0.0.1:8000; # your app
}
location = /_verify_bot {
internal;
if ($claimed_bot = "") { return 204; } # no claim: no lookup
proxy_pass http://127.0.0.1:3000; # bot-gate.js
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Forwarded-For $remote_addr;
proxy_cache botcheck;
proxy_cache_key $remote_addr$claimed_bot;
proxy_cache_valid 204 403 1h;
}
}
nginx -t a validé cette configuration, et nous l'avons exécutée devant le fichier Express le 20 octobre 2026, à 05:05 UTC. D'abord le test du GPTBot usurpé, via nginx, depuis la même machine :
$ curl -s -o /dev/null -w "%{http_code}\n" \
-A "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot" \
http://localhost:8080/
403
$ curl -s -o /dev/null -w "%{http_code}\n" \
-A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36" \
http://localhost:8080/
200
Cette chaîne GPTBot est l'exemple actuel de la page des bots d'OpenAI. Depuis votre propre machine, la requête provient de 127.0.0.1, qu'aucun robot n'utilise, donc le vérificateur la refuse avant toute requête. Pour observer la requête, appelez directement le fichier Express avec l'adresse que nginx transmettrait :
$ GPT='Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot'
$ GB='Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)'
$ curl -s -A "$GPT" -H "X-Forwarded-For: 216.73.216.10" http://127.0.0.1:3000/
unverified GPTBot claim
$ curl -s -A "$GPT" -H "X-Forwarded-For: 132.196.86.1" http://127.0.0.1:3000/
GPTBot is blocked by policy
$ curl -s -A "$GB" -H "X-Forwarded-For: 107.178.192.1" http://127.0.0.1:3000/
unverified Googlebot claim
$ curl -s -A "$GB" -H "X-Forwarded-For: 66.249.66.1" http://127.0.0.1:3000/
ok
Suivez la première ligne de bout en bout. Le User-Agent revendique GPTBot. Le vérificateur interroge 216.73.216.10, et l'API répond avec un robot vérifié nommé ClaudeBot. ClaudeBot n'est pas GPTBot, donc la requête reçoit un 403. La vraie adresse GPTBot, 132.196.86.1, passe la vérification et n'est refusée que parce que cette politique refuse l'entraînement ; avec BLOCKED_BOTS=CCBot, elle a obtenu un 200. Une revendication Claude-SearchBot depuis 216.73.216.10 a obtenu un 200, parce que cette politique refuse le jeton ClaudeBot, pas le bot de recherche d'Anthropic. Une copie de test de la configuration nginx qui transmettait les mêmes quatre adresses a renvoyé 403, 403, 403 et 200. Avec l'API rendue volontairement inaccessible, 130 revendications bingbot depuis une même adresse via nginx ont obtenu 120 réponses avec le statut 200, puis des 403 : une panne limite le débit des revendications de bot au lieu de les laisser passer.
Si vous testez sans clé, faites court. Les requêtes anonymes sont limitées par minute, et le 30e appel dans une même fenêtre de 60 secondes est déjà un 429 qui bloque votre IP pendant deux heures.
Limiter le débit de ce que vous ne pouvez pas vérifier au lieu de le bloquer
La limitation de débit est le bon outil pour le trafic que vous ne pouvez prouver ni dans un sens ni dans l'autre : bots invérifiables, récupérateurs déclenchés par l'utilisateur et tout ce qui ne revendique aucun bot. Pour voir quels bots publient des fichiers de plages et lesquels n'en publient pas, consultez notre liste fichier par fichier. Une limite empêche un scraper de copier votre site en un après-midi sans bloquer les personnes derrière un récupérateur.
Les deux extraits le font déjà. Le limit_req de nginx se base sur l'adresse du client pour les requêtes sans revendication de bot, à 10 par seconde avec une rafale de 20. Lors de notre test, 40 requêtes enchaînées ont renvoyé 25 succès et 15 réponses avec le statut 429. Ajustez les valeurs, et excluez les ressources statiques si un seul chargement de page en récupère des dizaines. Le limiteur Express regroupe les clients IPv6 par /64, car un abonné contrôle généralement un /64 entier ; consultez limiter le débit IPv6 par préfixe /64 pour savoir quand élargir à /56 ou /48.
Crawl-delay est la version polie pour les bots qui le respectent. La page d'aide sur le robot d'exploration d'Anthropic indique « nous prenons en charge l'extension non standard Crawl-delay de robots.txt », et la FAQ de Common Crawl indique « Nous respectons le paramètre Crawl-delay ». D'autres non. La spécification robots.txt de Google indique que des champs « comme crawl-delay ne sont pas pris en charge », et Apple indique qu'« Applebot ne suit pas crawl-delay ». Les pages d'OpenAI et de Perplexity ne le mentionnent pas.
Le niveau 2 n'intercepte que les requêtes qui nomment un bot. Pour bloquer les scrapers IA qui ne se présentent jamais comme des bots, ajoutez du comportement au niveau 3 : cadence des requêtes, chemins et réseau d'où provient la requête. Notre article sur la façon de détecter le web scraping dans vos journaux couvre ces signaux.
Options en périphérie : le blocage IA de Cloudflare et le pay per crawl
Derrière Cloudflare, vous pouvez bloquer les robots d'exploration IA avec un réglage plutôt qu'avec du code, ou les faire payer à la requête. Aucune des deux options ne vous dispense de savoir à quels bots vous avez affaire.
Cloudflare a annoncé le 1er juillet 2025, dans un article modifié pour la dernière fois le 15 juillet 2026, qu'il « changeait le comportement par défaut pour bloquer les robots d'exploration IA à moins qu'ils ne paient les créateurs pour leur contenu ». Si vous appliquez aussi vos propres règles, vérifiez ce que Cloudflare bloque déjà sur votre zone pour que les deux couches concordent.
Avec le pay per crawl, un robot qui demande une page payante reçoit « une réponse 402 Payment Required, accompagnée d'un en-tête crawler-price », et peut réessayer avec une intention de paiement. Les robots signent leurs requêtes selon les propositions Web Bot Auth afin que personne ne puisse payer à la place d'un autre. Cloudflare indique que le pay per crawl « est actuellement en bêta privée ».
Web Bot Auth n'est pas encore un standard. Le 20 octobre 2026, le groupe de travail webbotauth de l'IETF avait un seul document de groupe de travail, draft-ietf-webbotauth-httpsig-protocol-00 du 1er septembre 2026, et aucune RFC ; le jalon d'avril 2026 de sa charte pour une spécification sur la voie de la normalisation est dépassé. Un brouillon individuel, draft-illyes-webbotauth-jafar, propose un format JSON commun pour les fichiers de plages des robots. En attendant, les plages IP et le DNS inverse sont ce que vous pouvez vérifier.
Mesurer ce que la politique a changé
Mesurez la politique en journalisant le résultat de la vérification pour chaque requête de bot, puis en comparant avant et après.
- Part par bot vérifié. Journalisez
crawler.nameetcrawler.verifiedà côté de chaque requête qui a revendiqué un bot. La part de revendications en échec est votre taux d'usurpation. La part par nom montre quels opérateurs vous explorent réellement. - Visites référées par l'IA. Comptez les visites référées par chatgpt.com, perplexity.ai, claude.ai, copilot.microsoft.com et gemini.google.com. Considérez ce chiffre comme un plancher, car une partie du trafic des assistants arrive sans référent.
- Volume d'exploration. Comparez les requêtes par jour de chaque bot avant et après un changement. Le rapport Statistiques sur l'exploration de la Search Console ne couvre que les robots de Google, donc les autres bots doivent provenir de vos propres journaux.
Si les citations baissent après que vous avez bloqué un bot de recherche IA, vous avez votre réponse concernant ce bot.
Quand revoir votre politique envers les robots d'exploration IA
Revoyez votre politique envers les robots d'exploration IA chaque fois qu'un opérateur ajoute un bot, modifie un fichier de plages ou retire un jeton, et au moins une fois par trimestre. La page des bots d'OpenAI liste désormais OAI-AdsBot, avec son propre adsbot.json. Nos flux de robots n'incluent pas ce fichier et le code ci-dessus ne le nomme pas, donc une revendication OAI-AdsBot tombe au niveau 3 jusqu'à ce que vous décidiez.
Soyez clair sur ce que cette configuration ne peut pas faire :
- Elle ne prouve que les bots qui publient des plages. Bytespider et Meta-ExternalAgent ne peuvent pas être vérifiés, et une usurpation de l'un ou l'autre ressemble exactement à l'original.
- Les nouveaux préfixes arrivent avec retard. Un préfixe ajouté aujourd'hui peut mettre jusqu'à environ deux jours à être vérifié, donc un vrai bot peut brièvement échouer au niveau 2.
- Les blocages IP peuvent se retourner contre vous. Anthropic prévient que bloquer ses IP « peut ne pas fonctionner correctement ni garantir durablement une exclusion, car cela nous empêche de lire votre fichier robots.txt ». Gardez le Disallow dans robots.txt même lorsque le niveau 2 l'applique.
- La requête ne voit pas le User-Agent. Le contrôle d'usurpation est la comparaison des noms dans votre code.
- Le niveau 2 manque les scrapers qui ne revendiquent jamais de nom. Ceux-là relèvent du niveau 3.
Commencez par vos propres journaux. Choisissez une adresse qui a revendiqué GPTBot ou ClaudeBot cette semaine, faites-la passer dans une requête et comparez crawler.name au nom qu'elle revendiquait.
Questions fréquentes
Dois-je bloquer les robots d'exploration IA ?
Cela dépend du rôle du bot. Bloquez les robots d'entraînement comme GPTBot et ClaudeBot si vous refusez que votre contenu entraîne des modèles. Autorisez les bots de recherche IA comme OAI-SearchBot si vous voulez être cité. Limitez le débit des récupérateurs déclenchés par l'utilisateur plutôt que de compter sur robots.txt.
robots.txt arrête-t-il les robots d'exploration IA ?
Seulement ceux qui choisissent de le respecter. La RFC 9309 indique que ses règles « ne constituent pas une forme d'autorisation d'accès ». Un scraper qui utilise un User-Agent GPTBot l'ignore, donc l'application doit vérifier l'IP à l'arrivée de la requête.
Bloquer les robots d'exploration IA nuit-il au SEO ?
Bloquer le jeton Google-Extended n'a aucun effet sur la recherche Google ; Google indique que cela « n'a pas d'incidence » sur l'inclusion d'un site dans la recherche. Bloquer Googlebot pour empêcher l'usage par l'IA vous retire de la recherche. Bloquer des bots de recherche IA comme OAI-SearchBot vous exclut des réponses de recherche de l'assistant concerné.
Puis-je bloquer Google-Extended par IP ?
Non. Google-Extended est un jeton robots.txt sans User-Agent propre. Ce sont les robots existants de Google qui récupèrent les pages, donc le seul contrôle possible est une règle robots.txt pour ce jeton. Applebot-Extended fonctionne de la même façon : Apple indique qu'il n'explore pas les pages web.
Comment savoir si une requête qui se présente comme GPTBot est authentique ?
Vérifiez que l'IP de connexion figure dans le fichier gptbot.json publié par OpenAI. Le DNS inverse n'aide pas : les adresses GPTBot et ClaudeBot que nous avons vérifiées n'ont pas d'enregistrement PTR. Une requête renvoie threat.crawler.verified et le nom du bot, et votre code compare ce nom au User-Agent.
Tous les robots d'exploration IA peuvent-ils être vérifiés par IP ?
Non. Nous n'avons trouvé aucun fichier de plages de ByteDance pour Bytespider, et Meta n'en publie aucun pour Meta-ExternalAgent, donc aucun des deux ne peut être vérifié par IP. Limitez leur débit au lieu de faire confiance au User-Agent.
L'équipe derrière l'API GeoIPHub
Rédigé par l'équipe GeoIPHub, les personnes qui développent l'API de renseignement IP GeoIPHub et son scanner. Les brouillons sont préparés avec l'aide de l'IA et relus par l'équipe ; les exemples d'API sont de vraies requêtes sur l'API en production, sauf mention « illustratif ».


