De headless Chrome-shell werd meegeleverd met Chrome 59. Het is een manier om de Chrome-browser in een headless omgeving te draaien. In feite draait Chrome zonder Chrome! Het brengt alle moderne webplatformfuncties van Chromium en de Blink-renderingengine naar de commandoregel.
Een headless browser is een uitstekend hulpmiddel voor geautomatiseerd testen en serveromgevingen waar een zichtbare gebruikersinterface niet nodig is. Je wilt bijvoorbeeld tests uitvoeren op een echte webpagina, er een PDF van maken of gewoon inspecteren hoe de browser een URL weergeeft.
Headless starten (CLI)
De eenvoudigste manier om met de headless-modus aan de slag te gaan, is door het Chrome-programma vanuit de commandoregel te openen. Als je Chrome 59 of hoger hebt geïnstalleerd, start je Chrome met de vlag --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 moet verwijzen naar jouw Chrome-installatie. De exacte locatie verschilt per platform. Omdat ik een Mac gebruik, heb ik handige aliassen aangemaakt voor elke versie van Chrome die ik heb geïnstalleerd.
Als je de stabiele versie van Chrome gebruikt en de bètaversie niet kunt downloaden, gebruik dan 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"
Download Chrome Canary .
Opdrachtregelfuncties
In sommige gevallen is het niet nodig om Headless Chrome programmatisch te scripten . Er zijn een aantal handige commandoregelopties beschikbaar om veelvoorkomende taken uit te voeren.
Het DOM afdrukken
De vlag --dump-dom print document.body.innerHTML naar 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/
Screenshots maken
Om een schermafbeelding van een pagina te maken, gebruikt u de vlag --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/
Als je de opdracht uitvoert met --screenshot wordt er een bestand met de naam screenshot.png in de huidige werkmap aangemaakt. Als je screenshots van een volledige pagina wilt maken, is het iets ingewikkelder. David Schnurr heeft een uitstekend blogartikel geschreven waarin hij dit uitlegt. Bekijk het artikel "Using headless Chrome as an automated screenshot tool" .
REPL-modus (lees-, evalueer- en printlus)
Met de vlag --repl wordt Headless uitgevoerd in een modus waarin je JavaScript-expressies rechtstreeks vanuit de commandoregel in de browser kunt evalueren:
$ 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
$
Debuggen in Chrome zonder browserinterface?
Wanneer je Chrome start met --remote-debugging-port=9222 , wordt een instantie gestart met het DevTools-protocol ingeschakeld. Dit protocol wordt gebruikt om met Chrome te communiceren en de headless browserinstantie aan te sturen. Het is ook wat tools zoals Sublime, VS Code en Node gebruiken voor het debuggen van een applicatie op afstand. #synergie
Aangezien je geen browserinterface hebt om de pagina te bekijken, ga je in een andere browser naar http://localhost:9222 om te controleren of alles werkt. Je ziet dan een lijst met pagina's die je kunt inspecteren. Klik hierop om te zien wat Headless weergeeft.

Vanuit hier kunt u de vertrouwde DevTools-functies gebruiken om de pagina te inspecteren, debuggen en aanpassen zoals u gewend bent. Als u Headless programmatisch gebruikt, is deze pagina ook een krachtige debugtool waarmee u alle onbewerkte DevTools-protocolopdrachten kunt zien die over de verbinding met de browser worden verzonden.
Programmatisch gebruiken (Node)
Poppenspeler
Puppeteer is een Node.js-bibliotheek ontwikkeld door het Chrome-team. Het biedt een API op hoog niveau om headless (of volledige) Chrome te besturen. Het is vergelijkbaar met andere bibliotheken voor geautomatiseerd testen zoals Phantom en NightmareJS, maar het werkt alleen met de nieuwste versies van Chrome.
Puppeteer kan onder andere gebruikt worden om eenvoudig screenshots te maken, PDF's te genereren, door pagina's te navigeren en informatie over die pagina's op te halen. Ik raad de bibliotheek aan als je snel browsertesten wilt automatiseren. Het verbergt de complexiteit van het DevTools-protocol en neemt overbodige taken over, zoals het starten van een debug-instantie van Chrome.
Installeer het:
npm i --save puppeteer
Voorbeeld - print de gebruikersagent
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
console.log(await browser.version());
await browser.close();
})();
Bijvoorbeeld : een schermafbeelding maken van de pagina.
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();
})();
Raadpleeg de documentatie van Puppeteer voor meer informatie over de volledige API.
De CRI-bibliotheek
chrome-remote-interface is een bibliotheek op een lager niveau dan de API van Puppeteer. Ik raad deze aan als je dicht bij de hardware wilt werken en het DevTools-protocol direct wilt gebruiken.
Chrome opstarten
Chrome-remote-interface start Chrome niet automatisch voor je op, dus dat moet je zelf doen.
In het CLI-gedeelte hebben we Chrome handmatig gestart met --headless --remote-debugging-port=9222 . Om tests volledig te automatiseren, is het echter waarschijnlijk beter om Chrome vanuit je applicatie te starten.
Een manier is om child_process te gebruiken:
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) => {
...
});
Maar het wordt lastig als je een draagbare oplossing wilt die op meerdere platformen werkt. Kijk maar eens naar dat hardgecodeerde pad naar Chrome :(
ChromeLauncher gebruiken
Lighthouse is een fantastische tool om de kwaliteit van je webapplicaties te testen. Binnen Lighthouse is een robuuste module ontwikkeld voor het starten van Chrome, die nu apart beschikbaar is voor zelfstandig gebruik. De chrome-launcher NPM-module zoekt de installatielocatie van Chrome op, zet een debug-instantie op, start de browser en sluit deze af zodra je programma klaar is. Het mooiste is dat het platformonafhankelijk werkt dankzij Node!
Standaard probeert chrome-launcher Chrome Canary te starten (indien geïnstalleerd), maar je kunt dit wijzigen om handmatig te selecteren welke Chrome-versie je wilt gebruiken. Om dit te gebruiken, installeer je eerst via npm:
npm i --save chrome-launcher
Voorbeeld - het gebruik van chrome-launcher om een headless-applicatie te starten
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();
});
Het uitvoeren van dit script doet niet veel, maar je zou een instantie van Chrome in Taakbeheer moeten zien verschijnen die about:blank heeft geladen. Onthoud dat er geen browserinterface zichtbaar zal zijn. We werken zonder grafische interface.
Om de browser te besturen, hebben we het DevTools-protocol nodig!
Informatie over de pagina ophalen
Om de bibliotheek te installeren:
npm i --save chrome-remote-interface
Voorbeelden
Voorbeeld - print de gebruikersagent
const CDP = require('chrome-remote-interface');
...
launchChrome().then(async chrome => {
const version = await CDP.Version({port: chrome.port});
console.log(version['User-Agent']);
});
Dit resulteert in iets als: HeadlessChrome/60.0.3082.0
Voorbeeld : controleer of de site een webapp-manifest heeft.
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.
});
})();
Voorbeeld : extraheer de <title> van de pagina met behulp van DOM API's.
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.
});
})();
Gebruikmakend van Selenium, WebDriver en ChromeDriver
Op dit moment opent Selenium een volledige instantie van Chrome. Met andere woorden, het is een geautomatiseerde oplossing, maar niet volledig headless. Selenium kan echter met een beetje moeite zo geconfigureerd worden dat het headless Chrome uitvoert. Ik raad aan om het artikel "Running Selenium with Headless Chrome" te lezen voor de volledige instructies over hoe je dit zelf kunt instellen, maar hieronder vind je alvast een paar voorbeelden om je op weg te helpen.
ChromeDriver gebruiken
ChromeDriver 2.32 gebruikt Chrome 61 en werkt goed met headless Chrome.
Installeren:
npm i --save-dev selenium-webdriver chromedriver
Voorbeeld:
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();
WebDriverIO gebruiken
WebDriverIO is een API op een hoger niveau, gebouwd bovenop Selenium WebDriver.
Installeren:
npm i --save-dev webdriverio chromedriver
Voorbeeld: filter CSS-functies op 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();
})();
Download de oude Headless Chrome-versie als chrome-headless-shell
Vanaf Chrome versie 112 is de nieuwe Headless-modus ( --headless=new ) beschikbaar. Deze modus stelt ontwikkelaars in staat om Chrome zelf uit te voeren in plaats van een apart binair bestand, in een onbeheerde omgeving zonder zichtbare gebruikersinterface. Dit is handig voor test- en automatiseringsdoeleinden.
Er zijn verschillende toepassingsscenario's voor de oude headless shell en de nieuwe headless-modus:
- De oude Headless shell is een lichtgewicht wrapper rond de
//contentmodule van Chromium en heeft daardoor aanzienlijk minder afhankelijkheden. Zo vereist hij bijvoorbeeld geen X11/Wayland of D-Bus en presteert hij in sommige opzichten beter dan de volwaardige Chrome-browser. Dit maakt hem geschikt voor toepassingen zoals geautomatiseerd screenshotten of webscraping. - De nieuwe Headless-modus daarentegen is de echte Chrome-browser en is daardoor authentieker, betrouwbaarder en biedt meer functies. Dit maakt hem geschikter voor zeer nauwkeurige end-to-end webapplicatietests of het testen van browserextensies.
Met andere woorden, er is een afweging tussen prestaties en authenticiteit. Welke headless-modus is het meest geschikt voor jou? Dat hangt af van je gebruikssituatie.
Ontwikkelaars en testers die voor hun automatiseringsprojecten niet de volledige functionaliteit van Chrome nodig hebben, kunnen de oude Headless-versie gebruiken. Anders is de nieuwe Headless-versie waarschijnlijk de beste keuze.
Om ervoor te zorgen dat ontwikkelaars en testers de keuze tussen deze twee opties behouden, kondigen we met genoegen aan dat de oude Headless-implementatie nu beschikbaar is als een zelfstandig chrome-headless-shell binair bestand. Deze nieuwe chrome-headless-shell binaire bestanden worden gegenereerd voor elke Chrome-release die voor gebruikers toegankelijk is en kunnen vanaf Chrome 120 worden gedownload via de Chrome for Testing-infrastructuur .
Hoe kan ik de binaire bestanden chrome-headless-shell verkrijgen?
Net als bij andere Chrome for Testing-binaries is de eenvoudigste manier om chrome-headless-shell voor je platform te downloaden via ons @puppeteer/browsers command-line hulpprogramma , dat beschikbaar is via npm . Hier zijn een paar voorbeelden:
# 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
Als je liever je eigen geautomatiseerde scripts maakt om de binaire bestanden chrome-headless-shell te downloaden, dan zit je bij ons goed. Chrome for Testing biedt JSON API-eindpunten met de nieuwste beschikbare versies per Chrome-releasekanaal (Stable, Beta, Dev en Canary). Raadpleeg het beschikbaarheidsdashboard van Chrome for Testing voor een snel overzicht van de actuele status.
Feedback
We kijken uit naar uw feedback over chrome-headless-shell . Als u problemen ondervindt, kunt u deze gerust melden .
Aanvullende bronnen
Hieronder vind je een aantal handige hulpmiddelen om je op weg te helpen:
Dokters
- DevTools Protocol Viewer - API-referentiedocumentatie
Hulpmiddelen
- chrome-remote-interface - een Node.js-module die het DevTools-protocol omvat.
- Lighthouse - een geautomatiseerd hulpmiddel voor het testen van de kwaliteit van webapplicaties; maakt intensief gebruik van het Lighthouse-protocol.
- chrome-launcher - een Node.js-module voor het starten van Chrome, klaar voor automatisering.
Demo's
- " Het Headless Web " - Paul Kinlans geweldige blogpost over het gebruik van Headless met api.ai.
Veelgestelde vragen
Moet ik de vlag --disable-gpu gebruiken?
Alleen op Windows. Op andere platforms is dit niet langer nodig. De vlag --disable-gpu is een tijdelijke oplossing voor een aantal bugs. Je hebt deze vlag niet meer nodig in toekomstige versies van Chrome. Zie crbug.com/737678 voor meer informatie.
Dus ik heb Xvfb nog steeds nodig?
Nee. Headless Chrome gebruikt geen venster, dus een displayserver zoals Xvfb is niet langer nodig. Je kunt je geautomatiseerde tests dus prima zonder uitvoeren.
Wat is Xvfb? Xvfb is een in-memory displayserver voor Unix-achtige systemen waarmee je grafische applicaties (zoals Chrome) kunt uitvoeren zonder een aangesloten fysiek beeldscherm. Veel mensen gebruiken Xvfb om oudere versies van Chrome te draaien voor "headless" testen.
Hoe maak ik een Docker-container aan die Headless Chrome uitvoert?
Bekijk lighthouse-ci eens. Daar vind je een voorbeeld Dockerfile dat node:8-slim als basisimage gebruikt en Lighthouse installeert en uitvoert op App Engine Flex.
Kan ik dit gebruiken met Selenium / WebDriver / ChromeDriver ?
Ja. Zie Selenium, WebDriver en ChromeDriver gebruiken .
Wat is het verband met PhantomJS?
Headless Chrome is vergelijkbaar met tools zoals PhantomJS . Beide kunnen worden gebruikt voor geautomatiseerd testen in een headless omgeving. Het belangrijkste verschil tussen de twee is dat PhantomJS een oudere versie van WebKit als rendering engine gebruikt, terwijl Headless Chrome de nieuwste versie van Blink gebruikt.
Op dit moment biedt Phantom ook een API op een hoger niveau dan het DevTools-protocol .
Waar kan ik bugs melden?
Meld bugs in Headless Chrome op crbug.com .
Bugs in het DevTools-protocol kunt u melden op github.com/ChromeDevTools/devtools-protocol .