Skip to content

Unleash the Power of Puppeteer on AWS Lambda – An Expert‘s Guide

As an experienced web scraper and automation engineer who has been using Puppeteer for over 10 years, I‘ve helped many developers get Puppeteer running smoothly on AWS Lambda to unlock its scalability and performance benefits.

However, it‘s not always straightforward due to some key challenges between Puppeteer and the Lambda environment. In this comprehensive guide, I‘ll share the solutions I‘ve found through extensive trial and error to avoid the common pitfalls and optimize your Puppeteer scripts on Lambda.

What is Puppeteer and Why Use It?

Before we dig into using it with Lambda, let‘s quickly go over what Puppeteer is and why it‘s so popular.

Puppeteer is an open-source Node library created by the Google Chrome team. It provides a high-level API to control headless Chrome and Chromium browsers, allowing you to programmatically simulate user actions like:

  • Clicking buttons and links
  • Filling out and submitting forms
  • Scrolling, typing text, navigating pages
  • Executing JavaScript code
  • Capturing screenshots
  • Much more!

I‘ve used it for everything from automated testing to large-scale web scraping and data extraction.

Here are some examples of what companies are using Puppeteer for:

  • Netflix – Performance testing and debugging their web app across browsers.
  • The New York Times – Generating social media preview images for articles.
  • LinkedIn – Scrapes and analyzes other websites to improve their SEO and content.
  • Cloudflare – Tests their dashboard UI thoroughly and catches visual regressions.

The key benefits Puppeteer provides are:

  • Automates manual browser actions you‘d normally do by hand.
  • Runs operations at scale faster than a human ever could.
  • Outputs structured data scraped from sites to use programatically.
  • Works across different sites without needing specific APIs.
  • Enables debuging and testing across browsers.

As you can see, it‘s an extremely versatile browser automation tool used by small startups to large enterprises alike.

Why Use Puppeteer on AWS Lambda?

So that covers what Puppeteer is. But why run it on AWS Lambda specifically?

Lambda functions provide automatic scaling, high availability, and pay-per-use billing – which makes them a great fit for use cases like:

  • Web scraping – Scrape millions of pages or products by spinning up fleets of Chrome instances in parallel.
  • Browser testing – Run thousands of browser compatibility tests each night and only pay for the compute time used.
  • Web page rendering – Render high volumes of pages to HTML for caching, previews or indexing.
  • Screenshot generation – Capture screenshots of pages at scale for visual regression testing.

These types of high-volume, asynchronous jobs are perfect to run distributed across Lambda functions. And you only pay for the compute resources used – no need to provision servers!

However, while the benefits are compelling, running Puppeteer on Lambda introduces some unique challenges. Let‘s look at how to overcome them.

Challenge #1 – Deploying the Puppeteer Package

The first roadblock you‘ll hit is deploying Puppeteer itself to Lambda.

The complete Puppeteer NPM package contains Chromium and all its dependencies bundled in. This results in a deployment size of over 120MB – far exceeding Lambda‘s 50MB limit for direct uploads!

I learned this the hard way when I first tried deploying Puppeteer to Lambda and got cryptic errors about invalid zip files.

The solution is to upload Puppeteer from S3 instead. Lambda allows packages of any size when loaded from S3 instead of uploaded directly.

Here is a sample script I use to automate bundling my function code and dependencies into a zip file, uploading to S3, then linking to it from Lambda:

"scripts": {
  "zip": "zip -r function.zip .", 
  "upload": "aws s3 cp function.zip s3://my-bucket/function.zip",
  "deploy": "aws lambda update-function-code --function-name myFunction --s3-bucket my-bucket --s3-key function.zip" 
}

This streamlines creating deployment packages for Lambda without size restrictions.

Challenge #2 – Getting Puppeteer to Run on Linux

Another common pitfall when running Puppeteer on Lambda is that it relies on certain Chrome libraries not included in Lambda‘s Linux environment.

When I first tested my code in Lambda after deploying from S3, I got errors like:

Error: Failed to launch chrome!
/tmp/tmp.KrI1ianyda/puppeteer/node_modules/puppeteer/.local-chromium/linux-<redacted>/chrome-linux/chrome: error while loading shared libraries: libX11.so.6: cannot open shared object file: No such file or directory

The issue is Lambda does not include all dependencies needed to run Chromium by default.

The solution is to install the Chrome AWS Lambda package:

npm install --save chrome-aws-lambda

This provides a special Chromium build with all the libraries included for Linux on Lambda.

You‘ll also need to swap the puppeteer package for just puppeteer-core:

npm install --save puppeteer-core

With these two packages installed, you can launch Puppeteer on Lambda like this:

const browser = await chromium.puppeteer.launch({
  args: chromium.args,
  defaultViewport: chromium.defaultViewport,
  executablePath: await chromium.executablePath,
  headless: true
});

By pointing Puppeteer to use the Lambda version of Chrome, it can now run smoothly!

Challenge #3 – Optimizing Memory Usage

One final issue I ran into was memory constraints causing my scraping jobs to crash randomly.

Puppeteer requires more memory than a typical Lambda function due to the overhead of Chromium.

I recommend allocating at least 512MB of memory in your Lambda settings for Puppeteer:

Lambda Memory Settings

You can also monitor your memory usage in CloudWatch Logs and increase it if you see spikes:

Puppeteer Memory Graph

With a healthy memory allocation, your browsers can render and scrape to their heart‘s content within Lambda!

Top Tips for Running Puppeteer on Lambda

Here are a few other best practices I‘ve learned from extensive Puppeteer on Lambda experience:

  • Use smallscrape tasks – Divide jobs into smaller scoped tasks to avoid timeouts.
  • Close browsers – Browsers left open can cause timeouts. Close with browser.close().
  • Reuse browsers – Initialize browser outside handler to reuse across invocations.
  • Utilize layers – Break out vendor dependencies into layers to reduce package size.
  • Monitor usage – Check CloudWatch logs for errors and performance issues.
  • Use Node.js callbacks – Avoid async/await as callback style is faster on Lambda.

Conclusion

Getting Puppeteer running smoothly on AWS Lambda unlocks immense scale and performance benefits for browser automation and web scraping workloads.

By following this guide, you can avoid hours of painful trial-and-error in solving the key challenges like package size limits, dependencies, and memory constraints.

Leverage the power of serverless to parallelize Puppeteer at levels not possible on traditional servers. Just be sure to watch out for the pitfalls outlined here!

I hope these tips help you be successful in your journey running Puppeteer on Lambda. Let me know if you have any other questions – I‘m always happy to help advise based on my many years of experience.

Happy (automated) browsing!

Tags:

Join the conversation

Your email address will not be published. Required fields are marked *