# Robots d'IA sur Netlify - robots.txt, fichier _headers et Edge Function de filtrage

> Publier un robots.txt sur Netlify, ajouter X-Robots-Tag avec _headers et filtrer les robots d'IA par User-Agent avec une Edge Function ou l'extension dédiée.

Source : https://iabig.com/fr/plateformes/robots-ia-netlify/ — Guides CC BY 4.0, extraits de code MIT

Netlify sert un site statique ou hybride depuis son propre réseau, sans serveur web à configurer : tout passe par des fichiers déposés dans le dossier publié, par `netlify.toml` et, si besoin, par du code exécuté en périphérie du réseau. Pour les robots d'IA, cela donne trois leviers : le fichier robots.txt, qui exprime vos préférences, les en-têtes HTTP comme `X-Robots-Tag`, et le filtrage réel des requêtes, soit avec une Edge Function que vous écrivez, soit avec l'extension **User Agent Blocker** fournie par Netlify. Ce guide détaille chacun, avec une configuration qui refuse l'entraînement tout en laissant passer les robots de recherche de ChatGPT, Claude et Perplexity.

## Publier robots.txt

Un robots.txt sur Netlify est un fichier statique comme un autre : il doit se trouver à la racine du dossier publié (*publish directory*). Avec un générateur de site ou un framework, déposez le fichier là où l'outil copie les fichiers statiques tels quels, souvent un dossier `public/` ou `static/`, puis vérifiez après la construction qu'il figure bien à la racine du dossier déployé.

```text
# public/robots.txt - copié tel quel à la racine du site publié

# 1. Entraînement de modèles : refusé (choix éditorial)
User-agent: GPTBot
User-agent: ClaudeBot
User-agent: CCBot
User-agent: meta-externalagent
User-agent: MistralAI-Training
User-agent: Bytespider
User-agent: Applebot-Extended
User-agent: Google-Extended
Disallow: /

# 2. Recherche et récupération à la demande : autorisé
#    Ces robots n'appliquent que ce groupe : on y recopie les exclusions.
User-agent: OAI-SearchBot
User-agent: ChatGPT-User
User-agent: Claude-SearchBot
User-agent: Claude-User
User-agent: PerplexityBot
User-agent: Perplexity-User
Disallow: /admin/
Allow: /

# 3. Tous les autres robots
User-agent: *
Disallow: /admin/

Sitemap: https://www.example.com/sitemap.xml
```

Le guide de Netlify sur le blocage des robots d'IA rappelle que tous les produits d'IA ne respectent pas robots.txt. C'est vrai, mais les principaux éditeurs déclarent le respecter pour leurs robots d'exploration : commencez par ce fichier, et ne passez au filtrage que pour les robots qui l'ignorent.

## Ajouter X-Robots-Tag avec _headers

Le fichier `_headers`, lui aussi placé dans le dossier publié, associe des chemins à des en-têtes. Chaque chemin est suivi des en-têtes indentés ; les lignes qui commencent par `#` sont des commentaires.

```text
# _headers (à la racine du dossier publié)

# Documents PDF : ne pas indexer
/documents/*
  X-Robots-Tag: noindex

# Pages de résultats de recherche interne
/recherche/*
  X-Robots-Tag: noindex, nofollow
```

La même règle peut s'écrire dans `netlify.toml` :

```toml
[[headers]]
  for = "/documents/*"
  [headers.values]
    X-Robots-Tag = "noindex"
```

Deux limites, documentées par Netlify, comptent ici. Les en-têtes personnalisés ne s'appliquent qu'aux fichiers servis depuis le stockage de Netlify : une page rendue côté serveur par une fonction ou une Edge Function, ou un contenu servi par proxy, ne les reçoit pas, et c'est alors au code de renvoyer l'en-tête. Par ailleurs, les en-têtes déclarés dans `_headers` ou `netlify.toml` valent pour toutes les constructions et ne peuvent pas être limités à un contexte de déploiement.

Côté robots d'IA, gardez la mesure : Google documente `X-Robots-Tag`, mais les pages d'OpenAI, d'Anthropic et de Perplexity consultées pour ce guide n'en parlent pas. Pour eux, robots.txt reste la seule consigne documentée. Et un robot à qui robots.txt interdit une URL ne verra jamais l'en-tête de cette URL.

## L'extension User Agent Blocker

Netlify propose une extension maison qui bloque les requêtes d'une liste prédéfinie de robots d'IA et de robots SEO ou de recherche, en s'appuyant elle-même sur une Edge Function. Sa mise en place, d'après la documentation :

1. Dans le tableau de bord, **Extensions**, rechercher **User Agent Blocker**, puis **Install** (l'extension devient disponible pour toute l'équipe).
2. Dans le projet concerné, sous **Extensions**, ouvrir **User Agent Blocker**.
3. Sous **Block User Agents**, cocher les catégories à bloquer.
4. **Redeploy site**, confirmer avec **Save**, puis **Enable analytics and deploy site**.

Netlify précise que la liste n'est pas exhaustive et que l'extension ne s'active que sur un projet à la fois. La documentation ne donne ni la liste nominative des robots, ni le code HTTP renvoyé, ni les offres concernées : vérifiez ce que bloque chaque case avant de l'activer. Cocher « tous les robots d'IA », comme le suggère la page, risque d'écarter aussi les robots de recherche qui vous citent.

## Écrire sa propre Edge Function

Pour décider robot par robot, une Edge Function de quelques lignes suffit. Les fichiers placés dans `netlify/edge-functions/` sont détectés automatiquement ; une fonction qui renvoie `undefined` laisse la requête poursuivre son chemin.

```ts
// netlify/edge-functions/bloquer-robots-ia.ts
import type { Config, Context } from "@netlify/edge-functions";

// Robots refusés : ici les robots d'entraînement. Comparaison insensible à la casse.
const ROBOTS_REFUSES = [
  "GPTBot",
  "ClaudeBot",
  "CCBot",
  "meta-externalagent",
  "Bytespider",
];

export default async (request: Request, context: Context) => {
  const ua = (request.headers.get("user-agent") ?? "").toLowerCase();
  const robot = ROBOTS_REFUSES.find((nom) => ua.includes(nom.toLowerCase()));

  if (robot) {
    // Visible dans les journaux de la fonction
    console.log(`robot refusé : ${robot} depuis ${context.ip}`);
    return new Response("Accès refusé aux robots d'entraînement.", {
      status: 403,
      headers: { "content-type": "text/plain; charset=utf-8" },
    });
  }
  // Rien à faire : la requête continue normalement.
  return;
};

export const config: Config = {
  path: "/*",
  // robots.txt doit rester lisible par tous les robots
  excludedPath: ["/robots.txt"],
};
```

Nous avons vérifié la logique de cette fonction hors de Netlify, avec Node.js : un User-Agent GPTBot ou `ccbot` reçoit 403, `OAI-SearchBot` et un navigateur poursuivent. L'exclusion de `/robots.txt` est essentielle, car un robot qui ne peut pas lire le fichier ne peut pas y découvrir votre refus. La documentation de Netlify utilise des motifs `URLPattern` pour `path` et `excludedPath`, qui doivent commencer par `/`.

## Limiter le débit et filtrer par IP

Netlify propose aussi des règles de limitation de débit. Celles que l'on écrit dans le code, par exemple dans l'objet `config` d'une Edge Function avec `windowLimit`, `windowSize` et `aggregateBy`, ne ciblent que des chemins ; les règles qui portent sur un en-tête comme `user-agent` sont réservées à l'offre Enterprise avec High-Performance Edge. Les **Firewall Traffic Rules** bloquent ou autorisent par adresse IP, plage d'adresses ou pays, et un visiteur bloqué voit une page 404 de Netlify. Elles conviennent pour écarter une plage abusive, pas pour reconnaître un robot.

## Tester

```bash
# robots.txt bien publié, en 200
curl -I https://www.example.com/robots.txt

# Robot d'entraînement : 403 attendu avec l'Edge Function
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" https://www.example.com/

# robots.txt reste accessible au même robot : 200 attendu
curl -s -o /dev/null -w '%{http_code}\n' -A "GPTBot/1.4" https://www.example.com/robots.txt

# Robot de recherche : 200 attendu
curl -s -o /dev/null -w '%{http_code}\n' -A "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; PerplexityBot/1.0; +https://perplexity.ai/perplexitybot)" https://www.example.com/

# En-tête posé par _headers
curl -sI https://www.example.com/documents/tarifs.pdf | grep -i x-robots-tag
```

Ces tests restent indicatifs : ils reproduisent le nom du robot, pas son adresse IP. Les messages `console.log` de la fonction apparaissent dans les journaux des Edge Functions du projet, ce qui permet de confirmer que de vraies requêtes sont refusées. Pour contrôler robot par robot quelles URL votre fichier autorise, passez-le dans le [testeur de robots.txt IABIG](/fr/outils/testeur-robots-txt/).

## Pièges à éviter

- **Croire que le filtrage arrête les usurpateurs.** Une Edge Function fondée sur le User-Agent ne voit que ce que le client déclare. Un collecteur qui se présente comme un navigateur passe ; il faudrait comparer `context.ip` aux plages publiées par chaque éditeur pour aller plus loin.
- **Bloquer des robots de recherche par effet de bord.** Une sous-chaîne trop courte comme `bot` refuse tout le monde, Googlebot compris.
- **Bloquer `Google-Extended` ou `Applebot-Extended` dans une fonction.** Ce sont des jetons robots.txt, pas des robots : aucune requête ne porte ces noms.
- **Oublier les réponses rendues côté serveur.** `_headers` ne s'y applique pas.

## Revenir en arrière

Supprimez ou renommez le fichier de l'Edge Function, retirez le bloc concerné de `_headers` ou de `netlify.toml`, ou désactivez l'extension, puis redéployez. Netlify permet aussi de republier un déploiement antérieur depuis la liste des déploiements. Pour robots.txt, comptez jusqu'à 24 heures avant que les robots relisent la nouvelle version.

## Sources officielles

- Netlify, Block AI crawlers and bots : <https://docs.netlify.com/build/build-with-ai/block-ai-crawlers>
- Netlify, Blocking AI bots and controlling crawlers : <https://developers.netlify.com/guides/blocking-ai-bots-and-controlling-crawlers/>
- Netlify, Custom headers : <https://docs.netlify.com/manage/routing/headers/>
- Netlify, Edge Functions API : <https://docs.netlify.com/build/edge-functions/api/>
- Netlify, Edge Functions declarations : <https://docs.netlify.com/build/edge-functions/declarations/>
- Netlify, Rate limiting : <https://docs.netlify.com/manage/security/secure-access-to-sites/rate-limiting/>
- Netlify, Traffic rules : <https://docs.netlify.com/security/secure-access-to-sites/traffic-rules/>
- Google, Robots meta tag et X-Robots-Tag : <https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag>
- RFC 9309, Robots Exclusion Protocol : <https://www.rfc-editor.org/rfc/rfc9309>
- OpenAI, Overview of OpenAI Crawlers : <https://developers.openai.com/api/docs/bots>
- Anthropic, Does Anthropic crawl data from the web : <https://support.claude.com/en/articles/8896518>
- Perplexity, Perplexity Crawlers : <https://docs.perplexity.ai/docs/resources/perplexity-crawlers>
