En 2017, Chrome 59 a introduit le mode headless, qui vous permet d'exécuter le navigateur dans un environnement sans assistance, sans interface utilisateur visible. En bref, vous pouvez exécuter Chrome sans Chrome.
Le mode headless est un choix populaire pour l'automatisation des navigateurs, par le biais de projets tels que Puppeteer ou ChromeDriver. Voici un exemple de ligne de commande minimal utilisant le mode headless pour créer un fichier PDF d'une URL donnée:
chrome --headless --print-to-pdf https://developer.chrome.com/
Comment fonctionne le mode headless ?
Avant d'examiner le fonctionnement de "Headless", il est important de comprendre son fonctionnement. L'extrait de ligne de commande précédent utilise l'indicateur de ligne de commande --headless
, suggérant que l'option "Headless" n'est qu'un mode de fonctionnement du navigateur Chrome standard. Étonnamment, ce n'était peut-être pas vrai.
En fait, l'ancienne interface headless était une implémentation alternative et distincte du navigateur qui était envoyée dans le même binaire Chrome. Il ne partage aucun code du navigateur Chrome dans //chrome
.
La mise en œuvre et la maintenance d'un navigateur headless distinct entraînaient de nombreux coûts d'ingénierie. Comme headless était une implémentation distincte, elle avait ses propres bugs et fonctionnalités qui n'étaient pas présentes dans Headful Chrome. Cela créait une confusion pour les tests automatisés du navigateur, qui peuvent réussir en mode headful, mais échouer en mode headless, ou inversement.
De plus, Headless a exclu tout test automatisé basé sur l'installation d'extensions de navigateur. Il en va de même pour toutes les autres fonctions au niveau du navigateur. À moins d'utiliser une implémentation sans interface graphique distincte, celle-ci n'était pas compatible.
L'équipe Chrome a désormais unifié les modes headless et headless.
Le nouveau mode headless est disponible dans Chrome 112. Dans ce mode, Chrome crée, mais n'affiche aucune fenêtre de plate-forme. Toutes les autres fonctions, existantes et futures, sont disponibles sans limitation.
Utiliser le mode headless
Pour utiliser le nouveau mode headless, transmettez l'indicateur de ligne de commande --headless=new
:
chrome --headless=new
Pour l'instant, l'ancien mode headless est toujours disponible avec:
chrome --headless=old
Dans Puppeteer
Pour activer le nouveau mode headless dans Puppeteer:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
headless: 'new',
// `headless: true` (default) enables old Headless;
// `headless: 'new'` enables new Headless;
// `headless: false` enables "headful" mode.
});
const page = await browser.newPage();
await page.goto('https://developer.chrome.com/');
// …
await browser.close();
Dans Selenium-WebDriver
Pour utiliser le nouveau mode headless dans Selenium-WebDriver:
const driver = await env
.builder()
.setChromeOptions(options.addArguments('--headless=new'))
.build();
await driver.get('https://developer.chrome.com/');
// …
await driver.quit();
Consultez l'article de blog de l'équipe Selenium pour en savoir plus, y compris pour découvrir des exemples utilisant des liaisons d'autres langages.
Options de ligne de commande
Les options de ligne de commande suivantes sont disponibles dans le nouveau mode headless.
--dump-dom
L'option --dump-dom
imprime le DOM sérialisé de la page cible sur stdout.
Exemple :
chrome --headless=new --dump-dom https://developer.chrome.com/
Cette opération est différente de l'impression du code source HTML, ce que vous pouvez faire avec curl
. Pour vous fournir la sortie de --dump-dom
, Chrome analyse d'abord le code HTML dans un DOM, exécute toutes les <script>
susceptibles de modifier le DOM, puis le transforme en chaîne HTML sérialisée.
--screenshot
L'option --screenshot
effectue une capture d'écran de la page cible et l'enregistre sous le nom screenshot.png
dans le répertoire de travail actuel. Cela est particulièrement utile lorsqu'il est combiné avec l'indicateur --window-size
.
Exemple :
chrome --headless=new --screenshot --window-size=412,892 https://developer.chrome.com/
--print-to-pdf
L'indicateur --print-to-pdf
enregistre la page cible au format PDF nommé output.pdf
dans le répertoire de travail actuel. Exemple :
chrome --headless=new --print-to-pdf https://developer.chrome.com/
Vous pouvez éventuellement ajouter l'option --no-pdf-header-footer
pour omettre l'en-tête d'impression (avec la date et l'heure actuelles) et le pied de page (avec l'URL et le numéro de page).
chrome --headless=new --print-to-pdf --no-pdf-header-footer https://developer.chrome.com/
Non: la fonctionnalité derrière l'indicateur --no-pdf-header-footer
était auparavant disponible avec l'option --print-to-pdf-no-header
. Si vous utilisez une version antérieure, vous devrez peut-être revenir à l'ancien nom.
--timeout
L'indicateur --timeout
définit le temps d'attente maximal (en millisecondes) au terme duquel le contenu de la page est capturé par --dump-dom
, --screenshot
et --print-to-pdf
, même si la page est toujours en cours de chargement.
chrome --headless=new --print-to-pdf --timeout=5000 https://developer.chrome.com/
L'indicateur --timeout=5000
indique à Chrome d'attendre jusqu'à cinq secondes avant d'imprimer le PDF. L'exécution de ce processus prend donc au maximum 5 secondes.
--virtual-time-budget
--virtual-time-budget
agit comme une "avance rapide" pour tout code dépendant de l'heure (par exemple, setTimeout
/setInterval
). Il oblige le navigateur à exécuter n'importe quel code de la page aussi rapidement que possible tout en laissant à la page croire que le temps passe réellement.
Pour illustrer son utilisation, prenons l'exemple de cette démonstration, qui incrémente, consigne et affiche un compteur toutes les secondes à l'aide de setTimeout(fn, 1000)
. Voici le code approprié:
<output>0</output>
<script>
const element = document.querySelector('output');
let counter = 0;
setInterval(() => {
counter++;
console.log(counter);
element.textContent = counter;
}, 1_000);
</script>
Au bout d'une seconde, la page contient "1", "2" après deux secondes, et ainsi de suite. Pour capturer l'état de la page au bout de 42 secondes et l'enregistrer au format PDF, procédez comme suit:
chrome --headless=new --print-to-pdf --virtual-time-budget=42000 https://mathiasbynens.be/demo/time
--allow-chrome-scheme-url
L'indicateur --allow-chrome-scheme-url
est requis pour accéder aux URL chrome://
.
Cet indicateur est disponible à partir de Chrome 123. Exemple :
chrome --headless=new --print-to-pdf --allow-chrome-scheme-url chrome://gpu
Déboguer
Étant donné que Chrome est en réalité invisible en mode headless, il peut sembler difficile de résoudre un problème. Il est possible de déboguer Chrome headless d'une manière très semblable à celle de Chrome headful.
Lancez Chrome en mode headless avec l'indicateur de ligne de commande --remote-debugging-port
.
chrome --headless=new --remote-debugging-port=0 https://developer.chrome.com/
Cette commande imprime une URL WebSocket unique vers stdout, par exemple:
DevTools listening on ws://127.0.0.1:60926/devtools/browser/b4bd6eaa-b7c8-4319-8212-225097472fd9
Dans une instance Chrome tête-à-tête, nous pouvons ensuite utiliser le débogage à distance des outils pour les développeurs Chrome pour nous connecter à la cible headless et l'inspecter.
- Accédez à
chrome://inspect
et cliquez sur le bouton Configure (Configurer). - Saisissez l'adresse IP et le numéro de port issus de l'URL WebSocket.
- Dans l'exemple précédent, j'ai saisi
127.0.0.1:60926
.
- Dans l'exemple précédent, j'ai saisi
- Cliquez sur OK. Une cible distante doit s'afficher avec tous ses onglets et autres cibles répertoriés.
- Cliquez sur Inspecter pour accéder aux outils pour les développeurs Chrome et inspecter la cible headless distante, y compris une vue en direct de la page.
Commentaires
Nous sommes impatients de recevoir vos commentaires sur le nouveau mode headless. Si vous rencontrez des problèmes, signalez un bug.