June 11, 2024Profile photoTony Masek

403 error while installing Puppeteer on Ubuntu

I’ve been using Puppeteer quite a lot for OG image generation. I’ve installed it many times without any issues, but on my last attempt, I kept getting a 403 error, when trying to download Chromium. So today I will share how I made it work, even though it is more of a workaround rather than an actual solution.

Installation

Since I’m usually using Browsershot from Spatie, I just follow the instructions on their requirements page with different Puppeteer version based on what is needed.

This time, however, it kept failing on the chromium installation step.

The 403 Error

For some reason, the link that was being used https://storage.googleapis.com/chrome-for-testing-public/125.0.6422.78/linux64/chrome-headless-shell-linux64.zip kept throwing 403 when trying to download from my droplet. While working perfectly on my local machine. I tried to find the solution for this issue, but I just needed to make it work without losing too much time on it.

Skipping the download step

The error message suggests, that you can skip the download step and to do so you can use the PUPPETEER_SKIP_DOWNLOAD env variable. So let’s do just that:

export PUPPETEER_SKIP_DOWNLOAD=true

You can verify, that this environment variable is being used by running the printenv command.

The root user

Now when installing Puppeteer globally, you will have to use the sudo which will make you a root user hence the environment variable we just set is not actually present. You can verify this by running sudo printenv. As you can see it is not set.

Using existing environment variables

To overcome this issue, we just need to use the -E flag, which will use existing environment variables. Here is a snippet from the man command explaining the flag:

-E, --preserve-env
                 Indicates to the security policy that the user wishes to preserve their existing environment variables.  The security policy may return an error if the user does not have permission to preserve the environment.

So this is the final command to run:

sudo -E npm install --location=global --unsafe-perm puppeteer

Installing chrome

Even though we have installed Puppeteer, we still don’t have Chrome installed. So we need to download the file on our local machine, because while it was throwing 403 on the droplet, locally it works fine. Then upload it to the droplet to your preferred location and finally specify the path to Puppeteer.

Specify the path

As I mentioned before - I’m using Browsershot to interact with Puppeteer. While there are probably many ways to make this work, I chose to create .env variable with the path to my Chrome executable and then create a new Browsershot class which extends the default one and sets the path (if exists) in the constructor.

Now I can just use my class instead of the default one and the path is always set for me. Here is the snippet of the custom Browsershot class:

class Browsershot extends \Spatie\Browsershot\Browsershot
{
    public function __construct(string $url = '', bool $deviceEmulate = false)
    {
        parent::__construct($url, $deviceEmulate);

        if (! empty($path = config('browsershot.executable_path'))) {
            $this->setChromePath($path);
        }
    }
}

And that’s it. If anyone knows the real solution to this issue I would be delighted if you get in touch with me on Twitter. Thanks in advance :)

Until next time,
Tony