El shell de Chrome sin interfaz gráfica se lanzó en Chrome 59. Es una forma de ejecutar el navegador Chrome en un entorno sin interfaz gráfica. Básicamente, es ejecutar Chrome sin Chrome. Lleva todas las funciones modernas de la plataforma web que proporcionan Chromium y el motor de renderización Blink a la línea de comandos.
Un navegador sin interfaz gráfica es una excelente herramienta para las pruebas automatizadas y los entornos de servidor en los que no necesitas un shell de IU visible. Por ejemplo, es posible que desees ejecutar algunas pruebas en una página web real, crear un PDF o simplemente inspeccionar cómo el navegador renderiza una URL.
Cómo iniciar Headless (CLI)
La forma más fácil de comenzar a usar el modo sin interfaz gráfica es abrir el objeto binario de Chrome desde la línea de comandos. Si tienes instalado Chrome 59 o una versión posterior, inicia Chrome con la marca --headless:
chrome \
--headless \ # Runs Chrome in headless mode.
--disable-gpu \ # Temporarily needed if running on Windows.
--remote-debugging-port=9222 \
https://www.chromestatus.com # URL to open. Defaults to about:blank.
chrome debe apuntar a tu instalación de Chrome. La ubicación exacta variará de una plataforma a otra. Como estoy en Mac, creé alias convenientes para cada versión de Chrome que tengo instalada.
Si estás en el canal estable de Chrome y no puedes obtener la versión beta, usa chrome-canary:
alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
alias chrome-canary="/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary"
alias chromium="/Applications/Chromium.app/Contents/MacOS/Chromium"
Descargar Chrome Canary.
Funciones de línea de comandos
En algunos casos, es posible que no necesites programar Chrome sin interfaz gráfica de forma programática. Hay algunas marcas de línea de comandos útiles para realizar tareas comunes.
Cómo imprimir el DOM
La marca --dump-dom imprime document.body.innerHTML en stdout:
chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/
### Create a PDF
The `--print-to-pdf` flag creates a PDF of the page:
```shell
chrome --headless --disable-gpu --print-to-pdf https://www.chromestatus.com/
Toma capturas de pantalla
Para capturar una captura de pantalla de una página, usa la marca --screenshot:
chrome --headless --disable-gpu --screenshot https://www.chromestatus.com/
# Size of a standard letterhead.
chrome --headless --disable-gpu --screenshot --window-size=1280,1696 https://www.chromestatus.com/
# Nexus 5x
chrome --headless --disable-gpu --screenshot --window-size=412,732 https://www.chromestatus.com/
Si ejecutas con --screenshot, se producirá un archivo llamado screenshot.png en el directorio de trabajo actual. Si buscas capturas de pantalla de página completa, las cosas son un poco más complicadas. Hay una excelente entrada de blog de David Schnurr que te ayudará. Consulta
Cómo usar Chrome sin interfaz gráfica como una herramienta automatizada de captura de pantalla .
Modo REPL (bucle de lectura, evaluación e impresión)
La marca --repl ejecuta Headless en un modo en el que puedes evaluar expresiones de JS en el navegador, directamente desde la línea de comandos:
$ chrome --headless --disable-gpu --repl --crash-dumps-dir=./tmp https://www.chromestatus.com/
[0608/112805.245285:INFO:headless_shell.cc(278)] Type a Javascript expression to evaluate or "quit" to exit.
>>> location.href
{"result":{"type":"string","value":"https://www.chromestatus.com/features"}}
>>> quit
$
¿Cómo depurar Chrome sin una IU del navegador?
Cuando ejecutas Chrome con --remote-debugging-port=9222, se inicia una instancia
con el protocolo de Herramientas para desarrolladores habilitado. El protocolo se usa para comunicarse con Chrome y controlar la instancia del navegador sin interfaz gráfica. También es lo que usan herramientas como Sublime, VS Code y Node para depurar de forma remota una aplicación. #synergy
Como no tienes una IU del navegador para ver la página, navega a http://localhost:9222 en otro navegador para verificar que todo funcione. Verás una lista de páginas inspeccionables en las que puedes hacer clic y ver lo que renderiza Headless:
Desde aquí, puedes usar las funciones conocidas de Herramientas para desarrolladores para inspeccionar, depurar y ajustar la página como lo harías normalmente. Si usas Headless de forma programática, esta página también es una potente herramienta de depuración para ver todos los comandos sin procesar del protocolo de Herramientas para desarrolladores que se transmiten por cable y se comunican con el navegador.
Cómo usar de forma programática (Node)
Titiritero
Puppeteer es una biblioteca de Node desarrollada por el equipo de Chrome. Proporciona una API de alto nivel para controlar Chrome sin interfaz gráfica (o completo). Es similar a otras bibliotecas de pruebas automatizadas, como Phantom y NightmareJS, pero solo funciona con las versiones más recientes de Chrome.
Entre otras cosas, Puppeteer se puede usar para tomar capturas de pantalla, crear archivos PDF, navegar por páginas y obtener información sobre ellas con facilidad. Te recomiendo la biblioteca si deseas automatizar rápidamente las pruebas del navegador. Oculta las complejidades del protocolo de Herramientas para desarrolladores y se encarga de tareas redundantes, como iniciar una instancia de depuración de Chrome.
Instálalo:
npm i --save puppeteer
Ejemplo : Imprime el agente de usuario
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
console.log(await browser.version());
await browser.close();
})();
Ejemplo : Toma una captura de pantalla de la página
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.chromestatus.com', {waitUntil: 'networkidle2'});
await page.pdf({path: 'page.pdf', format: 'A4'});
await browser.close();
})();
Consulta la documentación de Puppeteer para obtener más información sobre la API completa.
La biblioteca de CRI
chrome-remote-interface es una biblioteca de nivel inferior que la API de Puppeteer. Te recomiendo que lo uses si quieres estar cerca del metal y usar el protocolo de Herramientas para desarrolladores directamente.
Cómo iniciar Chrome
chrome-remote-interface no inicia Chrome por ti, por lo que deberás encargarte de eso.
En la sección de la CLI, iniciamos Chrome de forma manual con
--headless --remote-debugging-port=9222. Sin embargo, para automatizar completamente las pruebas, es probable que desees generar Chrome desde tu aplicación.
Una forma es usar child_process:
const execFile = require('child_process').execFile;
function launchHeadlessChrome(url, callback) {
// Assuming MacOSx.
const CHROME = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome';
execFile(CHROME, ['--headless', '--disable-gpu', '--remote-debugging-port=9222', url], callback);
}
launchHeadlessChrome('https://www.chromestatus.com', (err, stdout, stderr) => {
...
});
Pero las cosas se complican si quieres una solución portátil que funcione en varias plataformas. Solo mira esa ruta codificada de forma rígida a Chrome :(
Cómo usar ChromeLauncher
Lighthouse es una herramienta maravillosa
para probar la calidad de tus apps web. Se desarrolló un módulo sólido para iniciar Chrome en Lighthouse y ahora se extrae para su uso independiente.
El módulo NPM chrome-launcher
encontrará dónde
está instalado Chrome, configurará una instancia de depuración, iniciará el navegador y lo finalizará
cuando termine tu programa. Lo mejor es que funciona multiplataforma gracias a Node.
De forma predeterminada, chrome-launcher intentará iniciar Chrome Canary (si está instalado), pero puedes cambiarlo para seleccionar manualmente qué Chrome usar. Para usarlo, primero instala desde npm:
npm i --save chrome-launcher
Ejemplo : Usa chrome-launcher para iniciar Headless
const chromeLauncher = require('chrome-launcher');
// Optional: set logging level of launcher to see its output.
// Install it using: npm i --save lighthouse-logger
// const log = require('lighthouse-logger');
// log.setLevel('info');
/**
* Launches a debugging instance of Chrome.
* @param {boolean=} headless True (default) launches Chrome in headless mode.
* False launches a full version of Chrome.
* @return {Promise<ChromeLauncher>}
*/
function launchChrome(headless=true) {
return chromeLauncher.launch({
// port: 9222, // Uncomment to force a specific port of your choice.
chromeFlags: [
'--window-size=412,732',
'--disable-gpu',
headless ? '--headless' : ''
]
});
}
launchChrome().then(chrome => {
console.log(`Chrome debuggable on port: ${chrome.port}`);
...
// chrome.kill();
});
La ejecución de esta secuencia de comandos no hace mucho, pero deberías ver una instancia de Chrome en el administrador de tareas que cargó about:blank. Recuerda que no habrá ninguna IU del navegador. No tenemos interfaz gráfica.
Para controlar el navegador, necesitamos el protocolo de Herramientas para desarrolladores.
Cómo recuperar información sobre la página
Para instalar la biblioteca, haz lo siguiente:
npm i --save chrome-remote-interface
Ejemplos
Ejemplo : Imprime el agente de usuario
const CDP = require('chrome-remote-interface');
...
launchChrome().then(async chrome => {
const version = await CDP.Version({port: chrome.port});
console.log(version['User-Agent']);
});
Los resultados son similares a HeadlessChrome/60.0.3082.0.
Ejemplo : Verifica si el sitio tiene un manifiesto de la app web
const CDP = require('chrome-remote-interface');
...
(async function() {
const chrome = await launchChrome();
const protocol = await CDP({port: chrome.port});
// Extract the DevTools protocol domains we need and enable them.
// See API docs: https://chromedevtools.github.io/devtools-protocol/
const {Page} = protocol;
await Page.enable();
Page.navigate({url: 'https://www.chromestatus.com/'});
// Wait for window.onload before doing stuff.
Page.loadEventFired(async () => {
const manifest = await Page.getAppManifest();
if (manifest.url) {
console.log('Manifest: ' + manifest.url);
console.log(manifest.data);
} else {
console.log('Site has no app manifest');
}
protocol.close();
chrome.kill(); // Kill Chrome.
});
})();
Ejemplo : Extrae el <title> de la página con las APIs de DOM.
const CDP = require('chrome-remote-interface');
...
(async function() {
const chrome = await launchChrome();
const protocol = await CDP({port: chrome.port});
// Extract the DevTools protocol domains we need and enable them.
// See API docs: https://chromedevtools.github.io/devtools-protocol/
const {Page, Runtime} = protocol;
await Promise.all([Page.enable(), Runtime.enable()]);
Page.navigate({url: 'https://www.chromestatus.com/'});
// Wait for window.onload before doing stuff.
Page.loadEventFired(async () => {
const js = "document.querySelector('title').textContent";
// Evaluate the JS expression in the page.
const result = await Runtime.evaluate({expression: js});
console.log('Title of page: ' + result.result.value);
protocol.close();
chrome.kill(); // Kill Chrome.
});
})();
Cómo usar Selenium, WebDriver y ChromeDriver
Por el momento, Selenium abre una instancia completa de Chrome. En otras palabras, es una solución automatizada, pero no completamente sin interfaz gráfica. Sin embargo, Selenium se puede configurar para ejecutar Chrome sin interfaz gráfica con un poco de trabajo. Te recomiendo que ejecutes Selenium con Chrome sin interfaz gráfica si deseas obtener las instrucciones completas para configurar todo por tu cuenta, pero incluí algunos ejemplos a continuación para que comiences.
Cómo usar ChromeDriver
ChromeDriver 2.32 usa Chrome 61 y funciona bien con Chrome sin interfaz gráfica.
Instala:
npm i --save-dev selenium-webdriver chromedriver
Ejemplo:
const fs = require('fs');
const webdriver = require('selenium-webdriver');
const chromedriver = require('chromedriver');
const chromeCapabilities = webdriver.Capabilities.chrome();
chromeCapabilities.set('chromeOptions', {args: ['--headless']});
const driver = new webdriver.Builder()
.forBrowser('chrome')
.withCapabilities(chromeCapabilities)
.build();
// Navigate to google.com, enter a search.
driver.get('https://www.google.com/');
driver.findElement({name: 'q'}).sendKeys('webdriver');
driver.findElement({name: 'btnG'}).click();
driver.wait(webdriver.until.titleIs('webdriver - Google Search'), 1000);
// Take screenshot of results page. Save to disk.
driver.takeScreenshot().then(base64png => {
fs.writeFileSync('screenshot.png', new Buffer(base64png, 'base64'));
});
driver.quit();
Cómo usar WebDriverIO
WebDriverIO es una API de nivel superior sobre Selenium WebDriver.
Instala:
npm i --save-dev webdriverio chromedriver
Ejemplo: Filtra funciones de CSS en chromestatus.com
const webdriverio = require('webdriverio');
const chromedriver = require('chromedriver');
const PORT = 9515;
chromedriver.start([
'--url-base=wd/hub',
`--port=${PORT}`,
'--verbose'
]);
(async () => {
const opts = {
port: PORT,
desiredCapabilities: {
browserName: 'chrome',
chromeOptions: {args: ['--headless']}
}
};
const browser = webdriverio.remote(opts).init();
await browser.url('https://www.chromestatus.com/features');
const title = await browser.getTitle();
console.log(`Title: ${title}`);
await browser.waitForText('.num-features', 3000);
let numFeatures = await browser.getText('.num-features');
console.log(`Chrome has ${numFeatures} total features`);
await browser.setValue('input[type="search"]', 'CSS');
console.log('Filtering features...');
await browser.pause(1000);
numFeatures = await browser.getText('.num-features');
console.log(`Chrome has ${numFeatures} CSS features`);
const buffer = await browser.saveScreenshot('screenshot.png');
console.log('Saved screenshot...');
chromedriver.stop();
browser.end();
})();
Descarga la versión anterior de Chrome sin interfaz gráfica como chrome-headless-shell
A partir de la versión 112 de Chrome, está disponible el nuevo modo sin interfaz gráfica de Chrome (--headless=new). Este modo permite a los desarrolladores ejecutar Chrome en lugar de un objeto binario independiente en un entorno desatendido sin ninguna IU visible, lo que es útil para casos de uso de pruebas y automatización.
Existen casos de uso distintos para el shell sin interfaz gráfica anterior y el nuevo modo sin interfaz gráfica:
- El shell sin interfaz gráfica anterior es un wrapper ligero alrededor del módulo
//contentde Chromium y, por lo tanto, tiene muchas menos dependencias. En particular, no requiere X11/Wayland, D-Bus y, en algunos aspectos, tiene un mejor rendimiento que el navegador Chrome completo. Esto lo hace adecuado para casos de uso, como la captura de pantalla automatizada o el web scraping. - Por otro lado, el nuevo modo sin interfaz gráfica es el navegador Chrome real y, por lo tanto, es más auténtico, confiable y ofrece más funciones. Esto lo hace más adecuado para pruebas de apps web de extremo a extremo de alta precisión o pruebas de extensiones del navegador.
En otras palabras, existe un equilibrio entre el rendimiento y la autenticidad. ¿Qué modo sin interfaz gráfica es el más adecuado para ti? Depende de tu caso de uso.
Es posible que los desarrolladores y evaluadores que no requieren la funcionalidad completa de Chrome para sus casos de uso de automatización deseen usar la versión anterior de Headless. De lo contrario, es probable que la nueva versión de Headless sea la mejor opción.
Para garantizar que los desarrolladores y evaluadores sigan teniendo la opción entre estas dos opciones, nos complace anunciar que la implementación anterior de Headless ahora está disponible como un objeto binario chrome-headless-shell independiente. Estos nuevos objetos binarios chrome-headless-shell se generan para cada versión de Chrome orientada al usuario y están disponibles para su descarga a través de la infraestructura de Chrome for Testing a partir de Chrome 120.
¿Cómo puedo obtener objetos binarios chrome-headless-shell?
Al igual que con otros objetos binarios de Chrome for Testing, la forma más fácil de descargar chrome-headless-shell para tu plataforma es usar nuestra utilidad de línea de comandos, disponible con npm.@puppeteer/browsers Estos son algunos ejemplos:
# Download the latest available `chrome-headless-shell` binary corresponding to the Stable channel.
npx @puppeteer/browsers install chrome-headless-shell@stable
# Download a specific `chrome-headless-shell` version.
npx @puppeteer/browsers install chrome-headless-shell@120.0.6098.0
Si prefieres compilar tus propias secuencias de comandos automatizadas para descargar objetos binarios chrome-headless-shell, te ayudaremos. Chrome for Testing ofrece extremos de API de JSON con las versiones más recientes disponibles por canal de versiones de Chrome (estable, beta, para desarrolladores y Canary). Para obtener una descripción general rápida del estado más reciente, consulta el panel de disponibilidad de Chrome for Testing.
Comentarios
Esperamos recibir tus comentarios sobre chrome-headless-shell. Si tienes algún problema, no dudes en informarnos al respecto.
Más recursos
Estos son algunos recursos útiles para comenzar:
Documentos
- Visor del protocolo de Herramientas para desarrolladores: Documentos de referencia de la API
Herramientas
- chrome-remote-interface: Módulo de nodo que encapsula el protocolo de Herramientas para desarrolladores
- Lighthouse: Herramienta automatizada para probar la calidad de las apps web ; usa mucho el protocolo
- chrome-launcher: Módulo de nodo para iniciar Chrome, listo para la automatización
Demostraciones
- "The Headless Web": Excelente entrada de blog de Paul Kinlan sobre el uso de Headless con api.ai
Preguntas frecuentes
¿Necesito la marca --disable-gpu?
Solo en Windows. Otras plataformas ya no lo requieren. La marca --disable-gpu es una solución temporal para algunos errores. No necesitarás esta marca en versiones futuras de Chrome. Consulta crbug.com/737678
para obtener más información.
¿Entonces todavía necesito Xvfb?
No. Chrome sin interfaz gráfica no usa una ventana, por lo que ya no se necesita un servidor de visualización como Xvfb. Puedes ejecutar tus pruebas automatizadas sin problemas.
¿Qué es Xvfb? Xvfb es un servidor de visualización en memoria para sistemas similares a Unix que te permite ejecutar aplicaciones gráficas (como Chrome) sin una pantalla física conectada. Muchas personas usan Xvfb para ejecutar versiones anteriores de Chrome para realizar pruebas "sin interfaz gráfica".
¿Cómo creo un contenedor de Docker que ejecute Chrome sin interfaz gráfica?
Consulta lighthouse-ci. Tiene un
Dockerfile de ejemplo
que usa node:8-slim como imagen base, instala y
ejecuta Lighthouse
en App Engine Flex.
¿Puedo usar esto con Selenium, WebDriver o ChromeDriver?
Sí. Consulta Cómo usar Selenium, WebDriver y ChromeDriver.
¿Cómo se relaciona esto con PhantomJS?
Chrome sin interfaz gráfica es similar a herramientas como PhantomJS. Ambos se pueden usar para pruebas automatizadas en un entorno sin interfaz gráfica. La principal diferencia entre ambos es que Phantom usa una versión anterior de WebKit como motor de renderización, mientras que Chrome sin interfaz gráfica usa la versión más reciente de Blink.
Por el momento, Phantom también proporciona una API de nivel superior que el protocolo de Herramientas para desarrolladores.
¿Dónde informo errores?
Para errores en Chrome sin interfaz gráfica, envíalos a crbug.com.
Para errores en el protocolo de Herramientas para desarrolladores, envíalos a github.com/ChromeDevTools/devtools-protocol.