browserless/chrome
Deploy headless Chrome in Docker. Run on our cloud or bring your own. Free for non-commercial uses.
100M+
NOTE: This is the old v1 of Browserless. We would recommend using version 2 instead.
Browserless allows remote clients to connect and execute headless work, all inside of docker. It supports the standard, unforked Puppeteer, Selenium and Playwright libraries, as well offering REST-based APIs for common actions like data collection, PDF generation and more.
It takes care of common issues such as missing system-fonts, missing external libraries, and performance improvements, along with edge-cases like downloading files and managing sessions. For details, check out the documentation at browserless.io/docs/docker-quickstart.
If you've been struggling to deploy headless browsers without running into issues or bloated resource requirements, then Browserless was built for you. Run the browsers in our cloud or on your own, free for non-commercial uses.
browserless listens for both incoming websocket requests, generally issued by most libraries, as well as pre-build REST APIs to do common functions (PDF generation, images and so on). When a websocket connects to browserless it invokes Chrome and proxies your request into it. Once the session is done then it closes and awaits for more connections. Some libraries use Chrome's HTTP endpoints, like /json
to inspect debug-able targets, which browserless also supports.
Your application still runs the script itself (much like a database interaction), which gives you total control over what library you want to choose and when to do upgrades. This is preferable over other solutions as Chrome is still breaking their debugging protocol quite frequently.
See more options on our full documentation site.
docker run -p 3000:3000 browserless/chrome
http://localhost:3000/
to use the interactive debugger.browserless comes with two methods of debugging. The first is a web-based debugger for trying out small chunks of code without setting up a new project. You can see our public-facing debugger here.
The second method is an active-session debugger. When browserless runs http requests, and puppeteer sessions, it keeps track of some browser state, and makes those sessions available for debugging. You can simply load the web-based debugger in the browser, and click the menu icon in the top-left. It'll reveal all currently running sessions and a link to "view" them in Chrome's remote devtools. You can also query the /session
API to get a JSON representation of sessions as well.
If you're using the active-session debugger, and it's executing too fast, you can apply a ?pause
query parameter to your puppeteer.connect
call (or HTTP REST calls) and browserless will pause your script until the debugger connects. This way you don't miss any critical actions!
browserless ships with an interactive debugger that makes writing scripts faster and interactive. You can use things like debugger;
and console.log
to capture what's happening on the page while your script is running. All of the Chrome devtools are there at your disposal. A small list of features includes:
debugger;
and console.log
console
tabindex.js
and a package.json
to get things goingIf you're using nginx in front of the docker image (or Node) then you'll need to proxy through Upgrade headers. Below is an example of a location block that does such:
location / {
proxy_pass YOUR_DOCKER_IMAGE_LOCATION;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
TL;DR You can simply pull our M1 specific builds:
docker pull browserless/chrome:1-arm64
Fist, if you're on a amd64 machine (non-M1 Mac) you'll need to setup multi-platform builds. There's a lot of good resources out there to read about this, however you'll need to ensure you're on the latest docker with experimental features enabled.
# Setup the machine to build arm64
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
# Create a builder to handle arm64 builds
docker buildx create --name builder --driver docker-container --use
# Setup the builder to get started
docker buildx inspect --bootstrap
Once complete, you can specify a platform target and build against it. In our production tags, we build a special 1-arm64
tag, which is what we'll use in the example below.
docker buildx build --platform linux/arm64 -t browserless/chrome:arm64 .
In order to support arm64 inside of docker, we utilize some functionality inside of playwright to download an arm64 linux build. Since most distributions out there don't have an arm64-specific build Chromium, this means that puppeteer's chromium doesn't exist for arm64 (as far as we're aware). This, in short, means that the chromium version inside of the arm builds isn't matched exactly for the version of puppeteer that it comes bundled with. Most of the time this will go unnoticed, however if you have an issue it's possible that it's because the version of chromium in the arm64-builds isn't an exact match.
We offer a first-class hosted product located here. Alternatively you can host this image on just about any major platform that offers hosting for docker. The hosted service takes care of all the machine provisioning, notifications, dashboards and monitoring plus more:
If you're interested in using this image for commercial aspects, then please read the below section on licensing.
Puppeteer allows you to specify a remote location for chrome via the browserWSEndpoint
option. Setting this for browserless is a single line of code change.
Before
const browser = await puppeteer.launch();
After
const browser = await puppeteer.connect({ browserWSEndpoint: 'ws://localhost:3000' });
Getting started with Selenium and webdriver couldn't be easier. Once browserless is up and running simply update your application or test to use it as a remote connection:
Before
const webdriver = require('selenium-webdriver');
const fs = require('fs');
const chromeCapabilities = webdriver.Capabilities.chrome();
chromeCapabilities.set(
'chromeOptions', {
args: [
'--headless',
'--no-sandbox',
],
}
);
const driver = new webdriver.Builder()
.forBrowser('chrome')
.withCapabilities(chromeCapabilities)
.build();
After
const webdriver = require('selenium-webdriver');
const fs = require('fs');
const chromeCapabilities = webdriver.Capabilities.chrome();
chromeCapabilities.set(
'chromeOptions', {
args: [
'--headless',
'--no-sandbox',
],
}
);
const driver = new webdriver.Builder()
.forBrowser('chrome')
.withCapabilities(chromeCapabilities)
.usingServer('http://localhost:3000/webdriver') // <-- Apply usingServer and that's it
.build();
We support running with playwright via their remote connection method on the chromium
interface. Since playwright is very similar to puppeteer, even launch arguments and other things "just work":
Before
const browser = await pw.chromium.launch();
After
const browser = await pw.chromium.connect({
browserWSEndpoint: 'wss://chrome.browserless.io?token=YOUR-API-TOKEN',
});
After that, the rest of your code remains the same with no other changes required.
Most libraries allow you to specify a remote instance of Chrome to interact with. They are either looking for a websocket endpoint, a host and port, or some address. Browserless supports these by default, however if you're having issues please make an issue in this project and we'll try and work with the library authors to get them integrated with browserless.
You can find a much larger list of supported libraries on our documentation site.
Running Chrome on lambda is a fantastic idea but in practice is quite challenging. You're met with pretty tough upload limits, building Chrome yourself, and then dealing with odd invocation issues should everything else go ok. A lot of issues in various repositories are due to just challenges of getting Chrome running smoothly in AWS (see here). You can see for yourself by going to nearly any library and sorting issues by most commented.
Getting Chrome running well in docker is also a challenge as there's quiet a few packages you need in order to get Chrome running. Once that's done then there's still missing fonts, getting libraries to work with it, and having limitations on service reliability.
All of these issues prompted me to build a first-class image and workflow for interacting with Chrome in a more streamlined way. With browserless you never have to worry about fonts, extra packages, library support, or anything else. It should just work. On top of that it comes with a prescribed approach on how you interact with Chrome, which is through socket connections (similar to a database or any other external appliance). What this means is that you get the ability to drive Chrome remotely without having to do updates/releases to the thing that runs Chrome since it's divorced from your application.
If you want to use browserless to build commercial sites, applications, or in a continuous-integration system that's closed-source then you'll need to purchase a commercial license. This allows you to keep your software proprietary whilst still using browserless. You can purchase a commercial license here. A commercial license grants you:
Not only does it grant you a license to run such a critical piece of infrastructure, but you are also supporting further innovation in this space and our ability to contribute to it!
If you are creating an open source application under a license compatible with the GNU GPL license v3, you may use browserless under the terms of the GPLv3. You can read more about this license here.
docker pull browserless/chrome