puppeteer: The chromium binary is not available for arm64

Bug description

In an ARM based Docker container (or ARM based Linux):

  1. npm install puppeteer

Error:

The chromium binary is not available for arm64.

This is related to #6622 which wasn’t really solved just worked around via Rosetta.

I’m trying to build an ARM based Docker Image that uses BackstopJS/puppeteer. Ref https://github.com/garris/BackstopJS/issues/1300

Are there any plans to build an arm64 version of chromium?

Puppeteer version

10.0.0

Node.js version

16.3.0

npm version

7.15.1

What operating system are you seeing the problem on?

Linux

Relevant log output

No response

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 110
  • Comments: 58 (5 by maintainers)

Commits related to this issue

Most upvoted comments

I have arm64 Chromium binaries available at www.chromiumforlambda.com

Thanks @talisto, that’s what I’ve been doing as a work around, but took two days to come up with that. https://github.com/garris/BackstopJS/issues/1300#issuecomment-958561525

I’m using puppeteer via Backstop JS and in my scenario Backstop uses a Docker image to do the screenshot comparisons (yields consistent results across OSes)

It would be nice if npm install puppeteer worked for multi-platform Docker images instead of trying to figure out how to add chromium yourself.

A workaround I’m using is to install chromium with the base image’s package manager (e.g. apk add chromium if you’re using the node alpine image), and then use ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true in the Dockerfile before npm install puppeteer to tell puppeteer to skip installing chromium. You may have to change the puppeteer executable path to use the package manager’s version of chromium.

@talisto would you mind sharing your Dockerfile to help all of this issue’s followers?

This is what I’m currently using:

FROM node:16-alpine3.15

RUN apk add --no-cache \
    msttcorefonts-installer font-noto fontconfig \
    freetype ttf-dejavu ttf-droid ttf-freefont ttf-liberation \
    chromium \
  && rm -rf /var/cache/apk/* /tmp/*

RUN update-ms-fonts \
    && fc-cache -f

ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser

WORKDIR /app

RUN npm init -y &&  \
    npm i puppeteer express

RUN addgroup pptruser \
    && adduser pptruser -D -G pptruser \
    && mkdir -p /home/pptruser/Downloads \
    && chown -R pptruser:pptruser /home/pptruser \
    && chown -R pptruser:pptruser /app

USER pptruser

COPY src/server.js /app

EXPOSE 8080

CMD ["yarn", "start"]

…some of which I lifted from here: https://github.com/ebidel/try-puppeteer/blob/master/backend/Dockerfile

…which is mostly based on the “Running Puppeteer in Docker” section of the Puppeteer troubleshooting docs: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-puppeteer-in-docker

The only relevant bits to this issue are the ENV statements, and adding chromium to the packages installed by the package manager.

It would be nice if npm install puppeteer worked for multi-platform Docker images instead of trying to figure out how to add chromium yourself.

This ^

Following the instructions here solved the issue for me: https://broddin.be/2022/09/19/fixing-the-chromium-binary-is-not-available-for-arm64/

brew install chromium --no-quarantine

Add the following lines to ~/.zshrc

export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
export PUPPETEER_EXECUTABLE_PATH=`which chromium`

and

source ~/.zshrc

Following the instructions here solved the issue for me: https://broddin.be/2022/09/19/fixing-the-chromium-binary-is-not-available-for-arm64/

brew install chromium --no-quarantine

Add the following lines to ~/.zshrc

export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
export PUPPETEER_EXECUTABLE_PATH=`which chromium`

and

source ~/.zshrc

I feel compelled to send you a basket of mini muffins. 😄 ❤️

I’ve spent a few hours trying to run one of our Docker containers on Linux/arm64, it was hard and mostly trial and error mode. My final setup is Debian 11 and Chromium 103.0.5060.53 built on Debian 11.3, running on Debian 11.3, the magic is in the bunch of flags I have had to set to make Puppeteer not stuck on a await browser.newPage(), and avoid segment faults and device access errors.

FROM node:16-bullseye-slim

ENV DEBIAN_FRONTEND noninteractive
RUN apt update -qq \
    && apt install -qq -y --no-install-recommends \
      curl \
      git \
      gnupg \
      libgconf-2-4 \
      libxss1 \
      libxtst6 \
      python \
      g++ \
      build-essential \
      chromium \
      chromium-sandbox \
      dumb-init \
      fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst \
    && rm -rf /var/lib/apt/lists/* \
    && rm -rf /src/*.deb

ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
ENV CHROME_PATH=/usr/bin/chromium
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium

WORKDIR /home/pptruser

# Add user to not run as a root.
RUN groupadd -r pptruser && useradd -r -g pptruser -G audio,video pptruser \
      && mkdir -p /home/pptruser/Downloads \
      && chown -R pptruser:pptruser /home/pptruser

COPY package*.json /home/pptruser/
COPY tasks.js /home/pptruser/
COPY processes.config.js /home/pptruser/
RUN chown -R pptruser:pptruser /home/pptruser;

# Run everything after as non-privileged user.
USER pptruser

# the install is retry threee times with a pause of 10 seconds
RUN for i in 1 2 3; \
    do \
      npm install --no-optional;\
      sleep 10; \
      ([ $i -eq 3 ] && exit 1) || true; \
    done;

ENTRYPOINT ["dumb-init", "--"]
CMD ["node_modules/.bin/pm2-docker", "processes.config.js"]
  const browser = await puppeteer.launch({
    pipe: true,
    headless: true,
    dumpio: true,
    args: [
      '--disable-dev-shm-usage',
      '--disable-setuid-sandbox',
      '--no-sandbox',
      '--no-zygote',
      '--disable-gpu',
      '--disable-audio-output',
      '--headless',
      '--single-process'
    ] 
  })
  const page = await browser.newPage()

the whole PR is at https://github.com/elastic/apm-integration-testing/pull/1493

@ReDrUm you can test my Dockerfile: https://github.com/it-novum/puppeteer-docker/blob/development/Dockerfile I have not tested it on Apple M1, but it is running on Linux arm64.

As @wujekbogdan says, using a package-managed version is unworkable, but a solution, assuming you trust their builds is to use the arm64 chromium provided by Playwright, built/hosted Microsoft.

It’s a little fiddly but the point of their project is to automatically build the latest versions of browsers for all platforms. This means that you can look at the commit history of browsers.json to find the build ID you want that aligns with https://pptr.dev/chromium-support and download that build zip.

For example, Puppeteer v21.5.0 wants Chromium 119.0.6045.105 and that’s in r1088, which can be downloaded from:

https://playwright.azureedge.net/builds/chromium/1088/chromium-linux-arm64.zip

In addition, a HEAD request to this URL will yield a content-md5 header, which can be validated against the downloaded .zip file. This build of Chromium has worked for me on arm64 with both Ubuntu 22.04 and Amazon Linux 2023.

Ideally, Puppeteer would work natively with arm64 though 😃 👍

All workarounds posted on this thread are unreliable because they are all based on installing a random version of Chrome via a package manager (no matter if it’s brew, apk, or apt).

The official Puppeteer docs clearly say that:

We see Puppeteer as an indivisible entity with Chromium. Each version of Puppeteer bundles a specific version of Chromium – the only version it is guaranteed to work with.

So while installing a stable Chromium version via a package manager works, it doesn’t guarantee that it works well because there’s no guarantee it was tested with the version of Puppeteer you use.

Also, Linux ARM is becoming more common with public clouds (thinking mainly AWS Graviton here in my experience).

It’s important to note the tight version requirements between Puppeteer and Chromium when using this approach. The version of Chromium currently available in alpine3.15 is 99.0.4844.84-r0, which mean the versions of Puppeteer you could/should use are 13.2.0-13.4.1. However, if you’re using an alpine3.14 image, you’ll get Chromium 93.0.4577.82-r0, which maps to Puppeteer 10.2.0-11.0.0.

All I had to do to get it working on my M1 chip was add:

ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium

 RUN apt-get install -y chromium  \
    && apt-get clean

Then added executablePath: '/usr/bin/chromium', when launching puppeteer:

    const browser: Browser = await puppeteer.launch({
        executablePath: '/usr/bin/chromium',
        headless: true,
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox'
        ] });

Dockerfile for above solution (no md5 checksum):

# chromium arm64 version solution: https://github.com/puppeteer/puppeteer/issues/7740#issuecomment-1833202428
# puppeteer version: ~21.5.2
# chromium version: 119.0.6045.105 (https://pptr.dev/chromium-support)
# playwright arm64 chromium build for chromium version 119.0.6045.105: r1088 (https://github.com/microsoft/playwright/commit/38115d121bd330b596a1fde2c81bbc2930783f86)

FROM node:20-slim

ENV NODE_ENV production

RUN apt-get update && apt-get install wget unzip -y

RUN wget -q -O - 'https://playwright.azureedge.net/builds/chromium/1088/chromium-linux-arm64.zip' && \
  unzip chromium-linux-arm64.zip && \
  rm -f ./chromium-linux-arm64.zip

ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true
ENV CHROME_PATH=/chrome-linux/chrome
ENV PUPPETEER_EXECUTABLE_PATH=/chrome-linux/chrome

# install the rest

A workaround I’m using is to install chromium with the base image’s package manager (e.g. apk add chromium if you’re using the node alpine image), and then use ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true in the Dockerfile before npm install puppeteer to tell puppeteer to skip installing chromium. You may have to change the puppeteer executable path to use the package manager’s version of chromium.

hello, could you please share your dockerfile, thank you!

@20manas solution does work.

however if you want to abstract the hardcoded url away and have an architecture-independent Dockerfile then you can just npm install playwright@^1.42.1 and then npx playwright install chromium —with-deps. This does the same download but without hardcoding the url

I think the previous comment was deleted?

The link to the repo was: https://github.com/juananpe/puppeteer-in-docker-in-m1

Yep, I wanted to fix a last minute bug 😃 Done --> https://github.com/juananpe/puppeteer-in-docker-in-m1

the env var downloads the build for Mac ARM though but afaik there are not chromium builds published for Linux ARM.

If you run Puppeteer on Apple Silicon in Docker, you need the Linux ARM version.

Would love to see it added.

That’s pretty annoying. Thanks for sharing @flaushi looks like I have to go to the same rabbit hole like you. I’m not sure about how to map the versions together. From the current docs it says:

The newest Chromium package supported on Alpine is 100, which corresponds to Puppeteer v13.5.0.

But the revisions.ts of v13.5.0 claims: https://github.com/puppeteer/puppeteer/blob/7b38b458c91f4180a29cee10698a909bea911f67/src/revisions.ts#L22-L25

confusing

https://linguinecode.com/post/how-to-fix-m1-mac-puppeteer-chromium-arm64-bug this helped me

Step 2: Allow Chromium to open on your M1 Mac:

Use the following command instead

 xattr -cr /Applications/Chromium.app

The ARM binary is available with the env var PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM. We are going to fully support it once GitHub Actions offer Mac ARM devices.

P.S. the env var downloads the build for Mac ARM though but afaik there are not chromium builds published for Linux ARM. P.P.S. https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html

Is anyone else running multi-arch images for visual-regression testing and noticing discrepancies between visual snapshots taken on say an amd64 vs arm64 image? For my codebase i’m seeing differences in drop shadows between systems using the same Debian image (albeit it the chromium arch differs)

@ReDrUm the ideal fix would be an arm build of Chromium for Debian, but doesn’t sound like that’s on Puppeteer’s radar.

Here’s the Dockerfile I used to work around my issues (unfortunately it’s an old version of Chrome) https://github.com/garris/BackstopJS/issues/1300#issuecomment-1018707468

A workaround I’m using is to install chromium with the base image’s package manager (e.g. apk add chromium if you’re using the node alpine image), and then use ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true in the Dockerfile before npm install puppeteer to tell puppeteer to skip installing chromium. You may have to change the puppeteer executable path to use the package manager’s version of chromium.

@talisto would you mind sharing your Dockerfile to help all of this issue’s followers?

Node.js version 14.18.1

Npm version 6.14.15

Environment :

root@RP4-2835-d03115-1xb7bb76fc:~/# cat /etc/os-release 
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

Kernel :

root@RP4-2835-d03115-1xb7bb76fc:~# uname -a
Linux RP4-2835-d03115-1xb7bb76fc 6.1.0-rpi4-rpi-v8 #1 SMP PREEMPT Debian 1:6.1.54-1+rpt2 (2023-10-05) aarch64 GNU/Linux

Issue :

 npm install n -g
----------------------------------------
/usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n
+ n@9.2.0
updated 1 package in 1.859s

   ╭────────────────────────────────────────────────────────────────╮
   │                                                                │
   │      New major version of npm available! 6.14.15 → 10.2.4      │
   │   Changelog: https://github.com/npm/cli/releases/tag/v10.2.4   │
   │               Run npm install -g npm to update!                │
   │                                                                │
   ╰────────────────────────────────────────────────────────────────╯

----------------------------------------
[ OK ]

#0540-23 | n 14.18.1
----------------------------------------
     copying : node/14.18.1
   installed : v14.18.1 (with npm 6.14.15)
----------------------------------------
[ OK ]

#0540-24 | npm -g install yarn typescript
----------------------------------------

> yarn@1.22.21 preinstall /usr/local/lib/node_modules/yarn
> :; (node ./preinstall.js > /dev/null 2>&1 || true)

/usr/local/bin/tsc -> /usr/local/lib/node_modules/typescript/bin/tsc
/usr/local/bin/tsserver -> /usr/local/lib/node_modules/typescript/bin/tsserver
/usr/local/bin/yarn -> /usr/local/lib/node_modules/yarn/bin/yarn.js
/usr/local/bin/yarnpkg -> /usr/local/lib/node_modules/yarn/bin/yarn.js
+ yarn@1.22.21
+ typescript@5.2.2
updated 2 packages in 6.233s
----------------------------------------
[ OK ]

#0540-25 | npm i grpc husky puppeteer postinstall yarn
----------------------------------------
npm WARN deprecated puppeteer@10.4.0: < 19.4.0 is no longer supported
npm WARN deprecated grpc@1.24.11: This library will not receive further updates other than security fixes. We recommend using @grpc/grpc-js instead.

> yarn@1.22.21 preinstall /opt/scorer/lib/grafana/plugins/grafana-image-renderer/node_modules/yarn
> :; (node ./preinstall.js > /dev/null 2>&1 || true)


> grpc@1.24.11 install /opt/scorer/lib/grafana/plugins/grafana-image-renderer/node_modules/grpc
> node-pre-gyp install --fallback-to-build --library=static_library

[grpc] Success: "/opt/scorer/lib/grafana/plugins/grafana-image-renderer/node_modules/grpc/src/node/extension_binary/node-v83-linux-arm64-glibc/grpc_node.node" is installed via remote

> husky@4.3.8 install /opt/scorer/lib/grafana/plugins/grafana-image-renderer/node_modules/husky
> node husky install

husky > Setting up git hooks
husky > Done

> puppeteer@10.4.0 install /opt/scorer/lib/grafana/plugins/grafana-image-renderer/node_modules/puppeteer
> node install.js

The chromium binary is not available for arm64.
If you are on Ubuntu, you can install with: 

 sudo apt install chromium


 sudo apt install chromium-browser

/opt/scorer/lib/grafana/plugins/grafana-image-renderer/node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserFetcher.js:115
                    throw new Error();
                    ^

Error
    at /opt/scorer/lib/grafana/plugins/grafana-image-renderer/node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserFetcher.js:115:27
    at FSReqCallback.oncomplete (fs.js:191:21)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! puppeteer@10.4.0 install: `node install.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the puppeteer@10.4.0 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2023-11-18T04_51_52_263Z-debug.log
----------------------------------------
[ ERROR(1) ]

Based on @nook24 works, I created a docker with dumb-init and wkhtmltopdf which works in both arm64 and amd64 (tested on both on Linux and Mac)

https://github.com/alaminopu/puppeteer-docker

Docker hub: https://hub.docker.com/repository/docker/alaminopu/puppeteer-docker/general

@drmrbrewer see https://storage.googleapis.com/chromium-browser-snapshots/index.html We are happy to review a PR implementing an alternative way to download chromium binaries. For now, you can use the package manager builds (just make sure they are compatible).

@MarcusOtter the problem is that Chromium binaries are not available for linux arm64

The ARM binary is available with the env var PUPPETEER_EXPERIMENTAL_CHROMIUM_MAC_ARM. We are going to fully support it once GitHub Actions offer Mac ARM devices. - @OrKoN

Have you considered something like BuildJet for GitHub Actions? It supports ARM and is supposed to be faster & cheaper: https://buildjet.com/for-github-actions

PS: The issue for GitHub Actions adding ARM support is: https://github.com/actions/runner-images/issues/5631

108.0.5359.94 should good enough for 19.3.0 (but not for 19.4.0). Normally if it is the same major version, it’s compatible.

Beware that the Chromium version installed via apt might not be completely compatible with the puppeteer version: double check the compatibility via https://pptr.dev/chromium-support

@nicostubi My Docker Container is using node:16-bullseye-slim as base image with "puppeteer": "^13.7.0", https://github.com/it-novum/puppeteer-docker/blob/development/src/package.json

I did not use Alpine as base image because chromium was not working (or in a wrong version or whatever can’t remember) on alpine

https://linguinecode.com/post/how-to-fix-m1-mac-puppeteer-chromium-arm64-bug this helped me

How do you get the mapping from Chromium 99.0.4844.84-r0 to puppeteer versions 13.2.0-13.4.1?

I check the CHANGELOG, which is also published as GitHub release notes. Puppeteer releases that pull in a new Chromium version will include the version and snapshot revision number. For example:

13.2.0 (2022-02-07)

Features

  • chromium: roll to Chromium 99.0.4844.16 (r961656)

That version applies until the next release that notes a Chromium change.

It’s important to note the tight version requirements between Puppeteer and Chromium when using this approach. The version of Chromium currently available in alpine3.15 is 99.0.4844.84-r0, which mean the versions of Puppeteer you could/should use are 13.2.0-13.4.1. However, if you’re using an alpine3.14 image, you’ll get Chromium 93.0.4577.82-r0, which maps to Puppeteer 10.2.0-11.0.0.

How do you get the mapping from Chromium 99.0.4844.84-r0 to puppeteer versions 13.2.0-13.4.1? Inspecting revisions.ts for 13.4.0, I see here https://github.com/puppeteer/puppeteer/blob/v13.4.0/src/revisions.ts

export const PUPPETEER_REVISIONS: Revisions = {
  chromium: '961656',
  firefox: 'latest',
};

I am trying to solve this for debian bullseye, which would install https://packages.debian.org/de/bullseye/chromium version 99.0.4844.74-1~deb11u1. Seems it’s the same version rquirements but I don’t get the mapping from 961656 to version 99.0.4844.84-r0 …

I just noticed that the Puppeteer docs actually have an example for Docker using Alpine which also sets PUPPETEER_SKIP_CHROMIUM_DOWNLOAD and uses the package manager to download Chromium:

https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-on-alpine