How to generate PDF from HTML on AWS Lambda

Anyone had luck in creating a function for html to pdf generation on AWS?
The closest I could get was using wkhtmltopdf and I can get the base64 of the pdf of the html string, but when I output it to the response, I can’t open the PDF.
Any good examples?

This is the code I’m using:

import wkhtmltopdf from "wkhtmltopdf";
import MemoryStream from "memorystream";

process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'];

export async function main(event, context, callback) {
    const html = '<h1>Test</h1><p>Hello world</p>';
    const memStream = new MemoryStream();

    wkhtmltopdf(html, { pageSize: 'letter' }, function(code, signal) {
        let pdf =;
        const response = {
            statusCode: 200,
            headers: {
                'Content-type' : 'application/pdf',
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Credentials": true
            body: pdf.toString('base64'),
            isBase64Encoded : true
        callback(null, response);

And I’m also including the wkhtmltopdf binary on the root that I get from this tutorial:


I’m not sure if this is related but if you declare your handler function async then you don’t use callback. If you’re using the Node 8.10 runtime it won’t work.

1 Like

Take a look at this

1 Like

You might also give chromeless or serverless chrome a shot:

1 Like

Thanks for the suggestions and guidance.

My problem was that I was testing directly on the service endpoint.
As soon as I called the service from the frontend (Javascript) and open it on a new window it worked:"data:application/pdf;base64, " + pdf);

Api2Pdf runs on AWS Lambda and supports wkhtmltopdf as well as Headless Chrome. Super easy.

Checkout this post, it might help

There are people asking for the solution using headless chrome puppeteer, here it is

Does anyone has this working?

I have a piece of code that works fine when running locally, yet when I deploy this to AWS Lambda then I get an error.

Here is what I tried:

const converter = require('html-pdf');

const pdf = await new Promise(async (resolve, reject) => {
    converter.create(html).toBuffer((err, buffer) => {

Once, deployed I’m getting:

Error: write EPIPE

I searched for the solution and found this SO:

The solution is apparently to add phantomPath

Therefore, I modified the code like this:

const phantomPath = path.join(ROOT_PATH, `static/phantomjs_linux-x86_64`)

converter.create(html, { phantomPath }).toBuffer((err, buffer) => {

Additionally, I downloaded and added precompiled phantomjs_linux-x86_64 to static directory that gets deployed to AWS Lambda.

Yet, that still fails with Error: write EPIPE even though the file is there and I pass phantomPath

Any help or advice?


I think I’ve finally found the issue - it must be the permissions! When I deploy my function and check files in static directory I see:

-rw-r--r-- 1 slicer 497 56587116 Apr  3  2020 phantomjs_linux-x86_64

I tried to change the permissions with chmod a+x phantomjs_linux-x86_64 yet I got:

Error: Command failed: chmod a+x /var/task/static/phantomjs_linux-x86_64
chmod: changing permissions of ‘/var/task/static/phantomjs_linux-x86_64’: Read-only file system

Therefore, I assumed I should be able to reproduce this on mac too and I downloaded and replaced phantomjs_linux-x86_64 with phantomjs_osx locally. Next, I removed permissions with: chmod ago-x phantomjs_osx:

-rw-r--r--   1 iaforek  staff  45020592 Apr  3 15:09 phantomjs_osx

When I ran the function locally… BOOM I was able to reproduce the same error:

Unhandled exception: write EPIPE