Retour au Centre de connaissances
Réseau

En-têtes HTTP personnalisés dans BotBrowser : option, profil ou CDP

Ajoutez des en-têtes de requête propres à votre application via --bot-custom-headers, le profil ou des commandes CDP, en gardant User-Agent et Sec-CH-UA cohérents.

BotBrowser Team

Documentation

Vous préférez la doc produit maintenue ?

Cet article a une page équivalente dans le centre de documentation. Utilisez les docs pour le flux canonique, les flags à jour et la référence durable.

Ce guide traite de l'ajout d'en-têtes de requête propres à l'application sans toucher à ceux que gère le profil, comme User-Agent et Sec-CH-UA. BotBrowser transmet les en-têtes que vous configurez aux requêtes HTTP et HTTPS ; il ne peut pas décider quels noms votre backend accepte ni empêcher un serveur ou une passerelle de les rejeter.

Résumé rapide

Laissez les valeurs stables dans le profil ou dans l'option, et réservez les commandes CDP aux valeurs dynamiques ; aucun nom géré par le profil ne doit être repris dans l'ensemble personnalisé. Vérifiez le même en-tête sur la requête initiale, sur le preflight CORS et après une redirection.

Sommaire de la guide

En-têtes standard et en-têtes personnalisés

Chaque requête HTTP envoyée par un navigateur porte un ensemble de champs d'en-tête. Certains décrivent le navigateur lui-même : User-Agent indique le navigateur et sa version, Sec-CH-UA et ses équivalents décrivent la marque et la plateforme de façon structurée, et Accept-Language énumère les préférences de langue. D'autres décrivent l'application : un jeton d'autorisation, un identifiant de build, un nom de locataire ou une indication de routage qu'une passerelle lit avant que la requête n'atteigne l'application. Le premier groupe doit rester cohérent avec l'identité de navigateur que vous avez choisie. Le second, c'est vous qui le définissez entièrement.

Schéma : l'option --bot-custom-headers, le champ configs.customHeaders du profil et les commandes CDP de BotBrowser apportent des en-têtes d'application à la même requête sortante, avec les en-têtes standard gérés par le profil ; la décision finale d'autoriser revient au serveur destinataire.

Cette séparation explique pourquoi les en-têtes personnalisés forment une fonction à part. Lorsqu'un profil est chargé, BotBrowser maintient les en-têtes standard gérés par le profil, comme User-Agent et Sec-CH-UA, alignés sur l'identité de navigateur de ce profil. Les en-têtes personnalisés s'ajoutent à côté. Ils sont destinés aux valeurs propres à l'application. Un en-tête personnalisé portant le même nom qu'un en-tête existant peut le remplacer ; gardez donc hors de l'ensemble personnalisé les noms gérés par le profil, comme User-Agent et Sec-CH-UA. Si une page doit se présenter comme un navigateur précis, un en-tête isolé qui le contredit crée justement le genre d'incohérence difficile à expliquer plus tard. La règle est donc simple : les en-têtes standard viennent du profil, les en-têtes d'application viennent de vous.

La sémantique des champs est définie dans la RFC 9110. Les noms de champ ne sont pas sensibles à la casse, donc X-App-Version et x-app-version désignent le même champ. La valeur d'un champ est une chaîne et, lorsque le même nom apparaît plusieurs fois, le destinataire peut traiter les lignes comme une seule liste séparée par des virgules. Ces détails comptent en pratique, car un ensemble d'en-têtes qui paraît correct dans un objet JSON peut être lu autrement par une passerelle qui normalise les noms, fusionne les doublons ou rejette des caractères inhabituels.

Les usages typiques des en-têtes personnalisés se regroupent ainsi :

  • Des indications d'authentification et d'autorisation, comme une clé d'API ou un jeton porteur que la passerelle attend à chaque appel.
  • Des marqueurs d'application, comme un numéro de build, un identifiant de locataire ou le nom d'un indicateur de fonctionnalité que le backend utilise pour router.
  • Des commutateurs de test et de préproduction, comme un en-tête qui sélectionne un déploiement canari ou active des réponses détaillées sur un environnement de test que vous possédez.
  • Des conventions de vues web mobiles, comme une valeur X-Requested-With qu'un site attend d'un conteneur d'application.

Les en-têtes personnalisés ne servent pas à décrire le chemin réseau. Des en-têtes comme X-Forwarded-For et X-Real-IP relèvent de l'infrastructure de proxys et de répartiteurs de charge, et un serveur correctement configuré n'accorde aucun poids à une valeur fixée par la personne qui exploite le navigateur. Les définir depuis le navigateur ne fait que créer de la confusion, alors utilisez des noms propres à votre application.

Les valeurs des en-têtes relèvent de la responsabilité de l'opérateur. Un en-tête qui transporte un identifiant secret doit être traité comme tout autre secret : gardez-le hors des journaux partagés, renouvelez-le selon le calendrier que définit votre backend et envoyez-le uniquement aux origines censées le recevoir. BotBrowser envoie les en-têtes que vous configurez aux requêtes HTTP et HTTPS, donc l'étendue de ce que vous configurez est l'étendue de ce qui est exposé.

Choisir entre l'option, la configuration du profil et les commandes CDP

BotBrowser documente trois façons de définir des en-têtes personnalisés, et le bon choix dépend de la fréquence de changement de l'ensemble et de la personne qui le maintient. Les trois exigent une licence PRO.

La première est l'option de lancement --bot-custom-headers. Elle prend un objet JSON dont les clés sont des noms d'en-tête et les valeurs des chaînes. C'est la solution la plus simple pour un ensemble statique : les en-têtes sont fixés au démarrage du navigateur, ils s'appliquent dès la toute première requête et la commande de lancement est l'unique endroit où les lire. Elle convient à une tâche planifiée, à une exécution de CI ou à un service qui appelle toujours le même backend avec le même marqueur d'application.

La deuxième est le champ de profil configs.customHeaders. Ici, les en-têtes sont stockés dans la configuration du profil plutôt que dans la commande de lancement. C'est utile lorsque l'ensemble appartient au profil et non à l'exécution, par exemple lorsqu'un profil représente toujours un même conteneur d'application et doit porter le même marqueur partout où il sert. Les en-têtes voyagent avec le fichier de profil, si bien que tout lanceur qui le charge obtient le même comportement sans argument supplémentaire.

La troisième est constituée des commandes CDP de niveau navigateur : BotBrowser.setCustomHeaders, BotBrowser.getCustomHeaders, BotBrowser.addCustomHeader, BotBrowser.removeCustomHeader et BotBrowser.clearCustomHeaders. Elles modifient l'ensemble d'en-têtes pendant que le navigateur fonctionne, sans redémarrage. La documentation présente les commandes CDP comme la plus souple des trois méthodes, ce qui en fait le choix naturel pour un jeton qui tourne pendant une session ou pour un en-tête qui doit changer entre deux navigations.

Un court guide de décision :

  • L'ensemble ne change jamais pendant une exécution : utilisez l'option.
  • L'ensemble appartient à un profil précis et doit le suivre : utilisez configs.customHeaders.
  • L'ensemble change pendant que le navigateur est ouvert : utilisez les commandes CDP sur la session de niveau navigateur.
  • Des contextes de navigation différents ont besoin d'ensembles différents : transmettez l'option par des options propres à chaque contexte, comme indiqué plus loin.

Les trois méthodes peuvent coexister, il vaut donc mieux décider d'avance laquelle est responsable de chaque en-tête. La documentation les classe par priorité : les commandes CDP d'abord, puis l'option de ligne de commande, puis le champ du profil. Même ainsi, si un même nom est défini à deux endroits, vérifiez quelle valeur est envoyée avant qu'un serveur ne se plaigne. Une convention pratique consiste à garder les marqueurs stables dans le profil ou dans l'option et à réserver les commandes CDP aux valeurs réellement dynamiques.

Un point de vocabulaire aide à lire la documentation. Un ensemble remplacé par setCustomHeaders remplace l'ensemble personnalisé précédent, pas les en-têtes standard gérés par le profil. addCustomHeader et removeCustomHeader touchent une seule entrée personnalisée, et clearCustomHeaders vide l'ensemble personnalisé. Ne les utilisez pas pour supprimer ou réécrire User-Agent ou Sec-CH-UA ; laissez ces noms au profil.

Pour les cookies, n'utilisez pas d'en-tête Cookie. BotBrowser dispose d'une option dédiée, --bot-cookies, avec import limité à un contexte, et c'est la voie prise en charge pour l'état des cookies. Traiter les cookies comme un en-tête personnalisé reviendrait à ignorer la portée et l'expiration que les cookies sont conçus pour avoir.

Lancer avec un ensemble d'en-têtes statique

Pour un ensemble statique, transmettez l'objet JSON à l'option de lancement. Dans un shell, les guillemets simples autour de la valeur préservent le JSON :

chrome --bot-profile="path/to/profile.enc" \
       --bot-custom-headers='{"X-App-Version":"2.1.0","X-Tenant":"acme-test"}'

Lorsque vous lancez depuis du code, la règle de guillemets change. Les guillemets simples de l'exemple shell n'existent que pour le shell. En JavaScript, l'argument est transmis directement au processus, la valeur doit donc être la chaîne JSON nue. Si vous ajoutez des guillemets autour, ils deviennent une partie de la valeur et le navigateur reçoit un texte qui n'est pas du JSON valide.

const headers = { 'X-App-Version': '2.1.0', 'X-Tenant': 'acme-test' };

// Correct : l'argument est l'option, un signe égal et le texte JSON
args.push('--bot-custom-headers=' + JSON.stringify(headers));

// Incorrect : les guillemets simples deviennent une partie de la valeur
args.push(`--bot-custom-headers='${JSON.stringify(headers)}'`);

Un lancement complet avec Playwright ressemble à ceci :

const { chromium } = require('playwright-core');

(async () => {
  const headers = { 'X-Auth': 'token123', 'X-Client': 'webapp' };

  const browser = await chromium.launch({
    executablePath: 'path/to/botbrowser/chrome',
    headless: true,
    args: ['--bot-profile=path/to/profile.enc', '--bot-custom-headers=' + JSON.stringify(headers)],
  });

  const page = await browser.newPage();
  await page.goto('https://example.com');
  await browser.close();
})();

La version Puppeteer ne diffère que par l'appel de lancement :

const puppeteer = require('puppeteer-core');

(async () => {
  const headers = { 'X-Auth': 'token123' };

  const browser = await puppeteer.launch({
    executablePath: 'path/to/botbrowser/chrome',
    headless: true,
    args: ['--bot-profile=path/to/profile.enc', '--bot-custom-headers=' + JSON.stringify(headers)],
  });

  const page = await browser.newPage();
  await page.goto('https://example.com');
  await browser.close();
})();

Si vous préférez conserver les en-têtes avec le profil, placez le même objet sous configs.customHeaders dans la configuration du profil. La valeur est un simple objet de paires de chaînes, exactement comme pour l'option, et un objet vide est la valeur par défaut. Lorsqu'une valeur de profil et une option existent toutes les deux, vérifiez le résultat sur un point d'écho avant de vous fier à l'une ou à l'autre, comme décrit dans la section de vérification.

Quelques détails méritent d'être réglés avant le premier lancement :

  • N'utilisez que des valeurs de type chaîne. Les nombres et les booléens doivent être écrits sous forme de chaînes, car les valeurs d'en-tête sont du texte.
  • Limitez les noms à des caractères de jeton ordinaires. Les espaces et la ponctuation dans un nom sont rejetés par de nombreux serveurs et par les intermédiaires du trajet.
  • Gardez une taille totale raisonnable. La documentation ne fixe pas de limite précise, mais chaque en-tête est envoyé avec chaque requête, et les serveurs et passerelles appliquent leurs propres limites de taille d'en-têtes.
  • N'incluez pas de secrets dans une commande de lancement conservée dans des scripts partagés ou visible dans la liste des processus. Lisez-les depuis l'environnement ou un coffre de secrets au moment du lancement.

Dans les configurations de type vue web Android, la documentation montre la même option utilisée pour reproduire une valeur X-Requested-With qu'enverrait un conteneur d'application. Le schéma est identique : un seul objet JSON transmis par l'option, appliqué aux requêtes HTTP et HTTPS.

Modifier les en-têtes à l'exécution et par contexte de navigation

Une option statique ne suffit plus lorsqu'une valeur change pendant une session, par exemple un jeton de courte durée que l'on renouvelle, ou un en-tête qui doit différer entre deux étapes d'un parcours. BotBrowser fournit pour cela des commandes CDP. Elles doivent être envoyées à la session de niveau navigateur, et non à une session de niveau page.

Avec Playwright, ouvrez une session de niveau navigateur et envoyez la commande :

const cdpSession = await browser.newBrowserCDPSession();

// Remplace tout l'ensemble personnalisé
await cdpSession.send('BotBrowser.setCustomHeaders', {
  headers: { 'X-Requested-With': 'com.example.app', 'X-Session': 'first' },
});

// Lit l'ensemble personnalisé actuel
const current = await cdpSession.send('BotBrowser.getCustomHeaders');
console.log(current.headers);

// Ajoute ou met à jour une entrée
await cdpSession.send('BotBrowser.addCustomHeader', {
  name: 'X-Session',
  value: 'refreshed',
});

// Supprime une entrée ou vide l'ensemble personnalisé
await cdpSession.send('BotBrowser.removeCustomHeader', { name: 'X-Session' });
await cdpSession.send('BotBrowser.clearCustomHeaders');

Avec Puppeteer, la session de niveau navigateur provient de la cible du navigateur :

const cdpSession = await browser.target().createCDPSession();

await cdpSession.send('BotBrowser.setCustomHeaders', {
  headers: { 'X-Requested-With': 'com.example.app' },
});

await cdpSession.send('BotBrowser.addCustomHeader', {
  name: 'X-Token',
  value: 'my-token',
});

Si vous envoyez l'une de ces commandes à une session de niveau page, l'appel échoue avec ProtocolError: 'BotBrowser.setCustomHeaders' wasn't found. Cette erreur indique généralement que la session a été créée depuis une page plutôt que depuis le navigateur. Passez à la session de niveau navigateur et la commande est trouvée.

Les cinq commandes couvrent tout le cycle de vie d'un ensemble personnalisé :

  • setCustomHeaders remplace tous les en-têtes personnalisés par l'objet que vous transmettez.
  • getCustomHeaders renvoie l'ensemble personnalisé actuel, utile pour consigner ce sur quoi vous allez vous appuyer.
  • addCustomHeader ajoute ou met à jour une seule entrée d'après son nom.
  • removeCustomHeader supprime une seule entrée d'après son nom.
  • clearCustomHeaders supprime tous les en-têtes personnalisés.

Un schéma fiable consiste à appliquer le nouvel ensemble, à lancer ensuite la navigation qui en dépend, puis à relire l'ensemble avec getCustomHeaders lorsque vous avez besoin d'être sûr de l'état actuel.

Des tâches différentes ont parfois besoin d'en-têtes différents dans le même navigateur. BotBrowser le permet en attribuant les en-têtes par contexte de navigation. Les options propres à un contexte sont transmises par BotBrowser.setBrowserContextFlags, et l'option d'en-têtes personnalisés figure parmi celles qu'un contexte peut porter :

const client = await browser.target().createCDPSession();

const contextA = await browser.createBrowserContext();
await client.send('BotBrowser.setBrowserContextFlags', {
  browserContextId: contextA._contextId,
  botbrowserFlags: ['--bot-profile=path/to/profile.enc', '--bot-custom-headers={"X-Requested-With":"com.app.one"}'],
});

const contextB = await browser.createBrowserContext();
await client.send('BotBrowser.setBrowserContextFlags', {
  browserContextId: contextB._contextId,
  botbrowserFlags: ['--bot-profile=path/to/profile.enc', '--bot-custom-headers={"X-Requested-With":"com.app.two"}'],
});

Ici, chaque contexte porte son propre ensemble d'en-têtes, de sorte que deux pages ouvertes en même temps envoient des marqueurs d'application différents. Gardez la même règle de guillemets en tête : dans le tableau, chaque entrée est un argument, le texte JSON s'écrit donc sans guillemets de shell supplémentaires.

Vérifier les en-têtes et gérer le preflight CORS

Vérifiez toujours une configuration d'en-têtes auprès d'un point d'accès qui renvoie ce qu'il a reçu. Un service d'écho public comme httpbin convient pour un contrôle rapide, et un point de préproduction que vous maîtrisez est encore préférable, car il montre aussi ce que votre propre passerelle fait des valeurs.

const page = await context.newPage();
await page.goto('https://httpbin.org/headers');
const headersText = await page.textContent('body');
console.log('Received headers:', headersText);

Une bonne vérification comporte trois volets :

  • Confirmez que chaque en-tête personnalisé configuré apparaît dans la réponse, avec la valeur exacte que vous avez fixée.
  • Confirmez que User-Agent et Sec-CH-UA correspondent toujours au profil chargé, ce qui montre que l'ensemble standard n'a pas été touché.
  • Ouvrez le panneau Réseau des outils de développement du navigateur et vérifiez que les en-têtes apparaissent sur les différents types de requêtes de la page, comme le document, les scripts, les images et les appels fetch.

Si un en-tête n'apparaît pas, la cause est généralement l'une de ces trois. Le JSON peut être invalide, le plus souvent à cause de l'erreur de guillemets décrite plus haut. La commande a pu être envoyée à une session de niveau page plutôt qu'à celle de niveau navigateur. Ou bien un intermédiaire entre le navigateur et le point d'écho a supprimé ou renommé le champ, et c'est pourquoi une comparaison directe avec un service que vous maîtrisez est précieuse.

Le second comportement à comprendre est CORS. Un navigateur traite une requête inter-origine autrement qu'une requête de même origine. Pour de nombreuses requêtes inter-origines, le navigateur envoie d'abord une requête de preflight avec la méthode OPTIONS. Elle contient Access-Control-Request-Method et Access-Control-Request-Headers, qui énumèrent la méthode et les en-têtes hors liste sûre que la vraie requête compte utiliser. Le serveur répond avec Access-Control-Allow-Origin, Access-Control-Allow-Methods et Access-Control-Allow-Headers, et ce n'est que si la réponse couvre la requête que le navigateur poursuit. Le guide CORS de MDN décrit l'échange complet, y compris Access-Control-Max-Age, qui permet au navigateur de réutiliser une réponse de preflight pendant un certain temps.

Les en-têtes non standard sont le déclencheur habituel. Un petit groupe d'en-têtes, comme Accept, Accept-Language et Content-Language, figure dans la liste sûre et ne provoque pas de preflight à lui seul. Un en-tête comme X-Auth-Token ou X-Tenant n'en fait pas partie. Lorsque le navigateur ajoute un tel en-tête à une requête inter-origine, un preflight peut être déclenché. Si le serveur cible ne mentionne pas le nom de l'en-tête dans Access-Control-Allow-Headers, la requête peut échouer. La documentation de BotBrowser le dit de la même façon : ajouter des en-têtes non standard peut déclencher un preflight sur certains sites, et le serveur cible doit les autoriser.

Cela a plusieurs conséquences pratiques :

  • Si vous possédez le serveur cible, ajoutez les noms d'en-tête à sa réponse Access-Control-Allow-Headers et décidez combien de temps une réponse de preflight peut être mise en cache.
  • Si vous ne possédez pas le serveur, vous ne pouvez pas changer sa façon de répondre. Choisissez un autre en-tête ou une autre approche, par exemple transporter la valeur à un endroit que le serveur accepte déjà.
  • Les requêtes de même origine n'ont pas besoin de preflight, donc un test contre votre propre origine peut réussir alors que le même en-tête échoue contre une autre origine. Testez contre l'origine que vous utiliserez réellement.
  • Une réponse de preflight qui autorise l'en-tête n'autorise pas la requête. L'authentification et l'autorisation restent des décisions distinctes du serveur.

La taille compte aussi. Serveurs, passerelles et CDN imposent des limites à la taille totale des en-têtes de requête. Un grand ensemble d'en-têtes personnalisés, ou une valeur démesurée, peut provoquer un rejet qui n'a rien à voir avec CORS ni avec BotBrowser. Si des requêtes se mettent à échouer après l'agrandissement d'un ensemble, réduisez-le avant de chercher ailleurs.

Où BotBrowser s'insère et où il s'arrête

BotBrowser prend en charge l'ajout d'en-têtes de requête HTTP personnalisés via --bot-custom-headers, via le champ de profil configs.customHeaders et via les commandes CDP de niveau navigateur BotBrowser.*CustomHeaders. Les en-têtes s'appliquent aux requêtes HTTP et HTTPS et peuvent être attribués par contexte de navigation, de sorte qu'une équipe peut envoyer un ensemble documenté d'en-têtes d'application pendant que le profil garde cohérents les en-têtes standard comme User-Agent et Sec-CH-UA. Le contrôle des en-têtes exige une licence PRO. BotBrowser ne peut pas obliger un serveur à accepter, autoriser ou approuver les en-têtes ajoutés, ne peut pas supprimer un preflight CORS ni les limites d'en-têtes et de taille qu'applique un serveur, et ne remplace pas votre propre conception d'en-têtes et d'authentification. La valeur d'un en-tête est décidée par l'application qui la lit, le côté serveur reste donc de votre responsabilité.

En pratique, cela revient à traiter la fonction comme un moyen de transport pour une conception d'en-têtes que vous avez déjà arrêtée. Décidez quels noms votre backend attend, quelles origines peuvent les recevoir, comment un jeton est émis et renouvelé, et à quoi doit ressembler une requête rejetée. Utilisez ensuite l'option, le champ de profil ou les commandes CDP pour livrer cette conception depuis le navigateur. Si la conception est solide, la livraison est simple. Si elle est floue, aucun choix d'option n'y remédiera.

Quelques limites méritent d'être gardées en tête :

  • Utilisez les en-têtes personnalisés pour ajouter des valeurs d'application. Gardez hors de l'ensemble personnalisé les en-têtes standard que gère le profil, comme User-Agent et Sec-CH-UA.
  • Les en-têtes d'infrastructure de proxy comme X-Forwarded-For sortent du cadre de ce que ce guide recommande, car ils décrivent un chemin réseau que le navigateur ne contrôle pas.
  • Les cookies relèvent de l'option dédiée aux cookies, pas d'un en-tête Cookie personnalisé.
  • Chaque en-tête que vous ajoutez est visible du serveur auquel il est envoyé et de tout intermédiaire du trajet, traitez donc l'ensemble comme public pour ces acteurs.

Pour la configuration environnante, le guide de configuration du proxy explique comment le routage réseau est mis en place, User-Agent et Client Hints explique comment les en-têtes d'identité standard suivent le profil, et navigateur multi-comptes traite de la séparation des contextes lorsque chacun a besoin de son propre ensemble d'en-têtes.

Vérification reproductible des en-têtes

L'exécution suivante utilise un fixture HTTP de loopback afin de répéter l'observation sans envoyer de secret ni de valeur de test à un service tiers. Le fixture expose /echo, renvoie une réponse 302 depuis /redirect et répond à OPTIONS avec la liste demandée. La commande est volontairement plus petite qu'un lancement de navigateur : elle teste le protocole et le diagnostic, tandis que l'option BotBrowser et les appels CDP restent les mécanismes de livraison décrits plus haut.

echo custom=custom-http-headers-20261017 ua=fixture-UA/1.0 sec=\"Fixture\";v=\"1\"
redirect status=200 custom=custom-http-headers-20261017
preflight status=204 allow=x-test-run

La première ligne montre que la valeur applicative, le champ user-agent et le champ de forme client hints sont arrivés ensemble au récepteur contrôlé. La deuxième est utile car une redirection peut changer l'origine ou faire retirer un en-tête selon la politique du navigateur et du serveur ; ce fixture a conservé l'en-tête personnalisé lors d'une redirection sur le même hôte. La troisième ligne est une réponse du serveur, pas une autorisation du navigateur : allow=x-test-run signifie que le récepteur a inscrit ce nom dans la liste du preflight, sans authentifier la requête finale.

Utilisez la sortie comme arbre de diagnostic. Si custom manque dans la ligne echo, vérifiez le quoting JSON et la portée de l'option. Si l'echo réussit mais qu'une requête cross-origin s'arrête avant l'appel applicatif, vérifiez Access-Control-Allow-Headers et la politique d'origine. Si la requête initiale réussit mais que la ligne de redirection diffère, comparez la cible, les indicateurs du contexte et toute passerelle qui réécrit les champs. Le fixture enregistre User-Agent et une valeur de forme Sec-CH-UA uniquement pour montrer ce que reçoit le serveur ; ce n'est pas un score de détecteur et cela ne prétend pas que Node.js est le moteur BotBrowser. Le fichier d'évidence conserve les digests du binaire Node et du profil stable pour répéter le même contrôle local.

Ce que cette page ajoute à la référence

La page de référence documente les choix de configuration. La comparaison ajoutée vérifie une valeur du profil, une valeur de lancement et une valeur CDP limitée au contexte sur la requête initiale, le preflight CORS et une redirection. Un écart sur un seul saut indique la portée de la requête ou la politique du serveur.

Sources

Références publiques utilisées pour les affirmations sur les en-têtes, CORS et BotBrowser :

Conclusion pratique

Décidez à l'avance quelle méthode possède chaque en-tête et ne reprenez pas les noms gérés par le profil. Si la valeur arrive sur la requête initiale mais échoue au preflight ou à la redirection, le problème vient de la portée ou de la politique du serveur, pas du navigateur.

#en-têtes HTTP#Custom-Headers#réseau#confidentialité#Request

Cet article fait partie du guide : Vue d’ensemble de la configuration proxy : carte des décisions réseau

Faites passer BotBrowser de la recherche à la production

Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.