How to create PDF in Lambda using Puppeteer

Crespo Wang
The Startup
Published in
3 min readAug 6, 2019

In my previous post, I demonstrated how to create a PDF in Lambda using wkhtmltopdf, I am sure there are folks want to use Puppeteer over wkhtmltopdf, let’s wire things up together.

To make things easier to understand here is the full solution https://github.com/crespowang/serverless-lambda-puppeteer

Serverless.yml

This time I will still be using Serverless framework. I want to put the lambda behind API Gateway, in order to configure API Gateway to play nicely with PDF as the content-type, you will need to have the following in the serverless.yml

This will add application/pdf as Binary Media Types in API Gateway settings.

This is very important according to AWS documentation.

If the Content-Type header of the response and the Accept header of the original request match an entry of thebinaryMediaTypes list, API Gateway passes through the body. This occurs when the Content-Type header and the Acceptheader are the same; otherwise, API Gateway converts the response body to the type specified in the Accept header.

As I am writing it now, Lambda runtime nodejs10.x doesn’t work with chrome-aws-lambda, you will see the error if you try to execute the function.

Error in Lambda NodeJS10.x

TypeScript + Babel + WebPack

This is just my personal preference, TypeScript over JavaScript, and I use babel-loader rather than tsc to transpile TypeScript into JavaScript, simply it’s a bit faster, see more details here.

puppeteer-core + chrome-aws-lambda

I can’t use the full version of puppeteer because the deployment package will go over AWS Lambda size limit, luckily with chrome-aws-lambda it ships an appropriate chromium binary for lambda nodejs environment. puppeteer-core is a version of Puppeteer that doesn’t download Chromium by default, so together with chrome-aws-lambda it provides a “full” puppeteer and is small enough to be deployed.

It works fine in Lambda, but if you will have an error in your local dev run.

Chromium revision is not downloaded. Run "npm install" or "yarn install"

This is because as we just talked about, puppeteer-core doesn’t download chromium and chrome-aws-lambda is only for AWS lambda, ie not for your local environment, to make it work locally we need to install the full puppeteer as devDependencies, and in the code we need to check if the request comes from serverless-offline, if yes then set the executablePath to your local Chromium.

./node_modules/puppeteer/.local-chromium/mac-674921/chrome-mac/Chromium.app/Contents/MacOS/Chromium

is the local executablePath for chromium we installed with puppeteer on devDependencies.

Please note that you only need the full puppeteer and the event.isOffline thing if you care about local dev environment, it is not necessary for running in AWS.

Lastly, after adjusting the serverless.yml you can deploy to your domain.

yarn sls deploy

If you send a GET request with Accept: application/pdf header, it should open the PDF in your browser.

In summary, puppeteer-core + chrome-aws-lambda is a good solution for running puppeteer in Lambda without using layers.

Now it is 2020, see how to do it in the new decade.

--

--