Running Puppeteer or Playwright inside AWS Lambda, Vercel or Netlify functions is a classic source of pain: the full Chromium build is too big for the package, it needs lots of memory, and every cold start launches a browser. This guide covers the options and gives working handlers that call a hosted render API instead.
puppeteer package downloads a Chrome build that is larger than that on its own.| Option | Good for |
|---|---|
@sparticuz/chromium + puppeteer-core | Staying fully self-hosted: a compressed Chromium built for Lambda that fits the zip limit You track Chromium/Puppeteer version pairs and still pay the memory and cold-start cost |
| Lambda container image (up to 10 GB) | Any browser, any fonts: package regular Playwright or Puppeteer in Docker Bigger images mean slower cold starts; you maintain the image |
| A hosted API (Shotmint, …) | No browser in the function at all: one HTTP call, a tiny bundle, no extra memory Pages are rendered by a third party; costs per render |
If you need to render private pages that only exist inside your VPC, self-host. Otherwise a hosted API keeps the function small and fast, and the code below has zero dependencies.
Works behind a Function URL or API Gateway. Set SHOTMINT_KEY as an environment variable (or read it from Secrets Manager).
// index.mjs
export const handler = async (event) => {
const url = event.queryStringParameters?.url ?? "https://example.com";
const r = await fetch("https://shotmint.creasework.com/v1/pdf?" + new URLSearchParams({ url, format: "A4" }), {
headers: { "X-API-Key": process.env.SHOTMINT_KEY },
});
if (!r.ok) return { statusCode: r.status, body: await r.text() };
const buf = Buffer.from(await r.arrayBuffer());
return {
statusCode: 200,
isBase64Encoded: true,
headers: { "Content-Type": "application/pdf" },
body: buf.toString("base64"),
};
};
No layer and no requests needed.
import base64, os, urllib.parse, urllib.request
def handler(event, context):
url = (event.get("queryStringParameters") or {}).get("url", "https://example.com")
q = urllib.parse.urlencode({"url": url, "width": 1280, "format": "png"})
req = urllib.request.Request("https://shotmint.creasework.com/v1/screenshot?" + q,
headers={"X-API-Key": os.environ["SHOTMINT_KEY"]})
with urllib.request.urlopen(req, timeout=60) as r:
body = r.read()
return {"statusCode": 200, "isBase64Encoded": True,
"headers": {"Content-Type": "image/png"},
"body": base64.b64encode(body).decode()}
Streams the image straight through, so nothing is buffered in the function. cache_ttl makes repeat requests for the same URL free for a day, and the CDN header lets Vercel cache it too.
// app/api/screenshot/route.js
export const runtime = "nodejs";
const ALLOWED = ["example.com", "www.example.com"]; // don't let strangers spend your credits
export async function GET(req) {
const url = new URL(req.url).searchParams.get("url") || "https://example.com";
if (!ALLOWED.includes(new URL(url).hostname)) return new Response("host not allowed", { status: 403 });
const r = await fetch("https://shotmint.creasework.com/v1/screenshot?" + new URLSearchParams({
url, width: "1280", format: "webp", cache_ttl: "86400",
}), { headers: { "X-API-Key": process.env.SHOTMINT_KEY } });
if (!r.ok) return new Response(await r.text(), { status: r.status });
return new Response(r.body, {
headers: { "Content-Type": r.headers.get("content-type"), "Cache-Control": "public, s-maxage=86400" },
});
}
format=webp or jpeg with quality, or upload the bytes to S3 / Vercel Blob and return a link instead of the body.maxDuration above your slowest page.error field and is not charged; always check the status before returning bytes.Try the output first, no key needed: website screenshot, full-page screenshot and URL to PDF. Related: Puppeteer alternative, Node.js guide, Python guide.
One screenshot or PDF = one credit. €5 buys 2,000 renders, credits never expire and there's no subscription. Cache hits with cache_ttl and failed renders are free.
No signup, no card. Get a key in one click, then buy credits only if you need more (from €5 for 2,000, never expire).
Get a free API key Full API reference