[{"data":1,"prerenderedAt":1590},["Reactive",2],{"/guides/puppeteer-pdf-aws-lambda":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"dateModified":10,"author":11,"faq":12,"body":22,"_type":1585,"_id":1586,"_source":1587,"_file":1588,"_extension":1589},"/guides/puppeteer-pdf-aws-lambda","guides",false,"","Puppeteer PDFs on Lambda and Vercel with @sparticuz/chromium","Puppeteer and Playwright PDFs on AWS Lambda and Vercel: the version pairing that works today, our bundle sizes against each limit, and the 6 MB response cap.","2026-11-09","Cyril Nicodème",[13,16,19],{"question":14,"answer":15},"Does @sparticuz/chromium work on arm64 (Graviton) Lambda functions?","Not from the main npm package, which includes only x64 binaries. Since Chromium 135, each GitHub release also has an arm64 Lambda layer zip and an arm64 pack tar. Use the layer, or @sparticuz/chromium-min with the arm64 pack.",{"question":17,"answer":18},"How do I add a Lambda layer for @sparticuz/chromium?","Take the layer zip from a GitHub release, or build it with make chromium.x64.zip from the repository. It's over 50 MB, so upload it to S3 and publish the layer from there. Then make @sparticuz/chromium a dev dependency, since the layer carries the binary. Without a layer, it stays a production dependency.",{"question":20,"answer":21},"Can @sparticuz/chromium make tagged (accessible) PDFs?","No. This build of Chromium can't make tagged PDFs, and the package's README says you'd need to compile Chromium yourself to get them.",{"type":23,"children":24,"toc":1567},"root",[25,64,69,76,95,107,118,131,193,227,233,254,256,323,365,401,407,429,431,548,758,771,822,864,958,964,984,990,1010,1019,1056,1084,1090,1125,1134,1185,1190,1212,1218,1232,1338,1343,1366,1372,1415,1421,1434,1443,1479,1509,1515,1521,1533,1538,1558,1563],{"type":26,"tag":27,"props":28,"children":29},"element","p",{},[30,33,40,42,48,50,55,57,62],{"type":31,"value":32},"text","A PDF function built from ",{"type":26,"tag":34,"props":35,"children":37},"code",{"className":36},[],[38],{"type":31,"value":39},"puppeteer-core",{"type":31,"value":41}," and ",{"type":26,"tag":34,"props":43,"children":45},{"className":44},[],[46],{"type":31,"value":47},"@sparticuz/chromium",{"type":31,"value":49}," zips to 78 MB, and Lambda refuses a direct upload over 50 MB. So ship it through S3, a layer or a container image. Then pin ",{"type":26,"tag":34,"props":51,"children":53},{"className":52},[],[54],{"type":31,"value":39},{"type":31,"value":56}," to the Chromium version ",{"type":26,"tag":34,"props":58,"children":60},{"className":59},[],[61],{"type":31,"value":47},{"type":31,"value":63}," ships (25.11.x for 153 today), give the function 1,600 MB of memory or more, and send the PDF back through S3 or a stream.",{"type":26,"tag":27,"props":65,"children":66},{},[67],{"type":31,"value":68},"On Lambda or Vercel, you're still running a browser, just in a smaller box, and each of those workarounds is one more thing you maintain.",{"type":26,"tag":70,"props":71,"children":73},"h2",{"id":72},"how-do-you-run-puppeteer-pagepdf-on-aws-lambda",[74],{"type":31,"value":75},"How do you run Puppeteer page.pdf() on AWS Lambda?",{"type":26,"tag":27,"props":77,"children":78},{},[79,81,86,88,93],{"type":31,"value":80},"Here's a handler for the Node.js 22 runtime on x86_64, written for ",{"type":26,"tag":34,"props":82,"children":84},{"className":83},[],[85],{"type":31,"value":39},{"type":31,"value":87}," 25.11.0 and ",{"type":26,"tag":34,"props":89,"children":91},{"className":90},[],[92],{"type":31,"value":47},{"type":31,"value":94}," 153.0.0:",{"type":26,"tag":96,"props":97,"children":102},"pre",{"className":98,"code":100,"language":101,"meta":7},[99],"language-javascript","// index.mjs\nimport chromium from '@sparticuz/chromium';\nimport puppeteer from 'puppeteer-core';\nimport { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';\n\nconst s3 = new S3Client({});\n\nexport const handler = async (event) => {\n    const browser = await puppeteer.launch({\n        args: await puppeteer.defaultArgs({ args: chromium.args, headless: 'shell' }),\n        executablePath: await chromium.executablePath(),\n        headless: 'shell',\n    });\n\n    try {\n        const page = await browser.newPage();\n        await page.setContent(event.html, { waitUntil: 'load' });\n        const pdf = await page.pdf({ format: 'A4', printBackground: true });\n\n        // Write the PDF to S3 rather than returning it (see the 6 MB limit below)\n        const key = `pdfs/${Date.now()}.pdf`;\n        await s3.send(new PutObjectCommand({\n            Bucket: process.env.PDF_BUCKET,\n            Key: key,\n            Body: pdf,\n            ContentType: 'application/pdf',\n        }));\n        return { key };\n    } finally {\n        // Always close the browser, even when the job throws\n        await browser.close();\n    }\n};\n","javascript",[103],{"type":26,"tag":34,"props":104,"children":105},{"__ignoreMap":7},[106],{"type":31,"value":100},{"type":26,"tag":96,"props":108,"children":113},{"className":109,"code":111,"language":112,"meta":7},[110],"language-json","{\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@sparticuz/chromium\": \"153.0.0\",\n    \"puppeteer-core\": \"~25.11.0\"\n  }\n}\n","json",[114],{"type":26,"tag":34,"props":115,"children":116},{"__ignoreMap":7},[117],{"type":31,"value":111},{"type":26,"tag":27,"props":119,"children":120},{},[121,123,129],{"type":31,"value":122},"The Node.js runtimes already include the AWS SDK for JavaScript v3, so ",{"type":26,"tag":34,"props":124,"children":126},{"className":125},[],[127],{"type":31,"value":128},"@aws-sdk/client-s3",{"type":31,"value":130}," isn't in the bundle. Then get three settings right:",{"type":26,"tag":132,"props":133,"children":134},"ul",{},[135,158,168],{"type":26,"tag":136,"props":137,"children":138},"li",{},[139,145,147,156],{"type":26,"tag":140,"props":141,"children":142},"strong",{},[143],{"type":31,"value":144},"Memory.",{"type":31,"value":146}," The ",{"type":26,"tag":148,"props":149,"children":153},"a",{"href":150,"rel":151},"https://github.com/Sparticuz/chromium",[152],"nofollow",[154],{"type":31,"value":155},"@sparticuz/chromium README",{"type":31,"value":157}," asks for at least 512 MB and recommends 1,600 MB or more. Lambda gives CPU in proportion to memory, with the equivalent of one vCPU at 1,769 MB.",{"type":26,"tag":136,"props":159,"children":160},{},[161,166],{"type":26,"tag":140,"props":162,"children":163},{},[164],{"type":31,"value":165},"Timeout.",{"type":31,"value":167}," Raise it well past the default, since a cold start unpacks Chromium before the first page loads.",{"type":26,"tag":136,"props":169,"children":170},{},[171,176,178,183,185,191],{"type":26,"tag":140,"props":172,"children":173},{},[174],{"type":31,"value":175},"Bundling.",{"type":31,"value":177}," If you bundle with esbuild, webpack or rollup, mark ",{"type":26,"tag":34,"props":179,"children":181},{"className":180},[],[182],{"type":31,"value":47},{"type":31,"value":184}," as external. The error ",{"type":26,"tag":34,"props":186,"children":188},{"className":187},[],[189],{"type":31,"value":190},"The input directory \"/var/task/bin\" does not exist",{"type":31,"value":192}," almost certainly means you didn't.",{"type":26,"tag":27,"props":194,"children":195},{},[196,201,203,209,211,217,219,225],{"type":26,"tag":34,"props":197,"children":199},{"className":198},[],[200],{"type":31,"value":47},{"type":31,"value":202}," 153.0.0 needs Node.js ",{"type":26,"tag":34,"props":204,"children":206},{"className":205},[],[207],{"type":31,"value":208},"^22.17.0",{"type":31,"value":210}," or ",{"type":26,"tag":34,"props":212,"children":214},{"className":213},[],[215],{"type":31,"value":216},">=24.0.0",{"type":31,"value":218},". For waiting on fonts and freeing memory between jobs, the same rules as on a server apply: see ",{"type":26,"tag":148,"props":220,"children":222},{"href":221},"/guides/puppeteer-pdf-in-production/",[223],{"type":31,"value":224},"our Puppeteer production guide",{"type":31,"value":226},".",{"type":26,"tag":70,"props":228,"children":230},{"id":229},"which-puppeteer-core-version-works-with-sparticuzchromium",[231],{"type":31,"value":232},"Which puppeteer-core version works with @sparticuz/chromium?",{"type":26,"tag":27,"props":234,"children":235},{},[236,238,243,245,252],{"type":31,"value":237},"The one whose Chrome for Testing has the same major version. ",{"type":26,"tag":34,"props":239,"children":241},{"className":240},[],[242],{"type":31,"value":47},{"type":31,"value":244}," versions follow Chromium's (153.x.x is Chromium 153) and don't follow semantic versioning, so a breaking change can land in a patch release. Puppeteer's ",{"type":26,"tag":148,"props":246,"children":249},{"href":247,"rel":248},"https://pptr.dev/supported-browsers",[152],[250],{"type":31,"value":251},"supported browsers page",{"type":31,"value":253}," says which Chrome each release targets:",{"type":31,"value":255},"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",{"type":26,"tag":257,"props":258,"children":259},"table",{},[260,282],{"type":26,"tag":261,"props":262,"children":263},"thead",{},[264],{"type":26,"tag":265,"props":266,"children":267},"tr",{},[268,273,278],{"type":26,"tag":269,"props":270,"children":271},"th",{},[272],{"type":31,"value":39},{"type":26,"tag":269,"props":274,"children":275},{},[276],{"type":31,"value":277},"Chrome for Testing",{"type":26,"tag":269,"props":279,"children":280},{},[281],{"type":31,"value":47},{"type":26,"tag":283,"props":284,"children":285},"tbody",{},[286,305],{"type":26,"tag":265,"props":287,"children":288},{},[289,295,300],{"type":26,"tag":290,"props":291,"children":292},"td",{},[293],{"type":31,"value":294},"25.11.0",{"type":26,"tag":290,"props":296,"children":297},{},[298],{"type":31,"value":299},"153.0.8010.36",{"type":26,"tag":290,"props":301,"children":302},{},[303],{"type":31,"value":304},"153.0.0",{"type":26,"tag":265,"props":306,"children":307},{},[308,313,318],{"type":26,"tag":290,"props":309,"children":310},{},[311],{"type":31,"value":312},"25.16.0 (npm latest)",{"type":26,"tag":290,"props":314,"children":315},{},[316],{"type":31,"value":317},"156.0.8078.47",{"type":26,"tag":290,"props":319,"children":320},{},[321],{"type":31,"value":322},"none yet",{"type":26,"tag":27,"props":324,"children":325},{},[326,328,334,336,341,343,348,350,356,358,363],{"type":31,"value":327},"That second row is what ",{"type":26,"tag":34,"props":329,"children":331},{"className":330},[],[332],{"type":31,"value":333},"npm install puppeteer-core",{"type":31,"value":335}," gives you on November 9, 2026. The newest ",{"type":26,"tag":34,"props":337,"children":339},{"className":338},[],[340],{"type":31,"value":47},{"type":31,"value":342}," is 153.0.0, published September 11. Install both at their latest and you get a pair that was never meant to run together. Pin ",{"type":26,"tag":34,"props":344,"children":346},{"className":345},[],[347],{"type":31,"value":39},{"type":31,"value":349}," to ",{"type":26,"tag":34,"props":351,"children":353},{"className":352},[],[354],{"type":31,"value":355},"~25.11.0",{"type":31,"value":357}," until a ",{"type":26,"tag":34,"props":359,"children":361},{"className":360},[],[362],{"type":31,"value":47},{"type":31,"value":364}," 156 ships.",{"type":26,"tag":27,"props":366,"children":367},{},[368,370,377,379,385,387,392,394,399],{"type":31,"value":369},"When you upgrade, move both packages together. In one ",{"type":26,"tag":148,"props":371,"children":374},{"href":372,"rel":373},"https://www.reddit.com/r/node/comments/1o741zn/puppeteercore_with_sparticuzchromium_fails_on/",[152],[375],{"type":31,"value":376},"r/node thread",{"type":31,"value":378},", Chromium wouldn't start on Vercel with ",{"type":26,"tag":34,"props":380,"children":382},{"className":381},[],[383],{"type":31,"value":384},"error while loading shared libraries: libnss3.so",{"type":31,"value":386},", and one commenter fixed it by taking ",{"type":26,"tag":34,"props":388,"children":390},{"className":389},[],[391],{"type":31,"value":47},{"type":31,"value":393}," from 131 to 141 with ",{"type":26,"tag":34,"props":395,"children":397},{"className":396},[],[398],{"type":31,"value":39},{"type":31,"value":400}," alongside.",{"type":26,"tag":70,"props":402,"children":404},{"id":403},"will-sparticuzchromium-fit-in-a-lambda-or-vercel-function",[405],{"type":31,"value":406},"Will @sparticuz/chromium fit in a Lambda or Vercel function?",{"type":26,"tag":27,"props":408,"children":409},{},[410,412,419,421,427],{"type":31,"value":411},"It fits the unzipped limit, not the zipped one. Lambda takes ",{"type":26,"tag":148,"props":413,"children":416},{"href":414,"rel":415},"https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html",[152],[417],{"type":31,"value":418},"50 MB zipped through the API, SDKs or console",{"type":31,"value":420},", and 250 MB unzipped, layers included. Vercel's limit is 250 MB uncompressed. Here's each route zipped with its handler and ",{"type":26,"tag":34,"props":422,"children":424},{"className":423},[],[425],{"type":31,"value":426},"node_modules",{"type":31,"value":428},", at the latest npm versions on November 9, 2026 (puppeteer-core 10.4.0 for chrome-aws-lambda):",{"type":31,"value":430},"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",{"type":26,"tag":257,"props":432,"children":433},{},[434,455],{"type":26,"tag":261,"props":435,"children":436},{},[437],{"type":26,"tag":265,"props":438,"children":439},{},[440,445,450],{"type":26,"tag":269,"props":441,"children":442},{},[443],{"type":31,"value":444},"Route",{"type":26,"tag":269,"props":446,"children":447},{},[448],{"type":31,"value":449},"Zip",{"type":26,"tag":269,"props":451,"children":452},{},[453],{"type":31,"value":454},"Unzipped",{"type":26,"tag":283,"props":456,"children":457},{},[458,476,494,512,530],{"type":26,"tag":265,"props":459,"children":460},{},[461,466,471],{"type":26,"tag":290,"props":462,"children":463},{},[464],{"type":31,"value":465},"puppeteer-core 25.16.0 + @sparticuz/chromium 153.0.0",{"type":26,"tag":290,"props":467,"children":468},{},[469],{"type":31,"value":470},"78.14 MB",{"type":26,"tag":290,"props":472,"children":473},{},[474],{"type":31,"value":475},"104.26 MB",{"type":26,"tag":265,"props":477,"children":478},{},[479,484,489],{"type":26,"tag":290,"props":480,"children":481},{},[482],{"type":31,"value":483},"playwright-core 1.65.0 + @sparticuz/chromium 153.0.0",{"type":26,"tag":290,"props":485,"children":486},{},[487],{"type":31,"value":488},"75.77 MB",{"type":26,"tag":290,"props":490,"children":491},{},[492],{"type":31,"value":493},"91.23 MB",{"type":26,"tag":265,"props":495,"children":496},{},[497,502,507],{"type":26,"tag":290,"props":498,"children":499},{},[500],{"type":31,"value":501},"chrome-aws-lambda 10.1.0 + puppeteer-core 10.4.0",{"type":26,"tag":290,"props":503,"children":504},{},[505],{"type":31,"value":506},"52.28 MB",{"type":26,"tag":290,"props":508,"children":509},{},[510],{"type":31,"value":511},"61.04 MB",{"type":26,"tag":265,"props":513,"children":514},{},[515,520,525],{"type":26,"tag":290,"props":516,"children":517},{},[518],{"type":31,"value":519},"playwright-aws-lambda 0.11.0 + playwright-core 1.65.0",{"type":26,"tag":290,"props":521,"children":522},{},[523],{"type":31,"value":524},"47.54 MB",{"type":26,"tag":290,"props":526,"children":527},{},[528],{"type":31,"value":529},"58.61 MB",{"type":26,"tag":265,"props":531,"children":532},{},[533,538,543],{"type":26,"tag":290,"props":534,"children":535},{},[536],{"type":31,"value":537},"puppeteer-core 25.16.0 + @sparticuz/chromium-min 153.0.0",{"type":26,"tag":290,"props":539,"children":540},{},[541],{"type":31,"value":542},"8.18 MB",{"type":26,"tag":290,"props":544,"children":545},{},[546],{"type":31,"value":547},"34.22 MB",{"type":26,"tag":549,"props":550,"children":552},"guide-figure",{"caption":551},"Deploy zip per Chromium route, with Lambda's 50 MB direct-upload limit. Our measurement, latest version of each package (puppeteer-core 10.x for chrome-aws-lambda), zip -9, November 9, 2026.",[553],{"type":26,"tag":554,"props":555,"children":564},"svg",{"viewBox":556,"xmlns":557,"role":558,"ariaLabelledBy":559,"style":562,"fontFamily":563},"0 0 400 324","http://www.w3.org/2000/svg","img",[560,561],"lz-zip-title","lz-zip-desc","max-width:400px;display:block;margin:0 auto","DM Sans, sans-serif",[565,571,577,623,654,686,720],{"type":26,"tag":566,"props":567,"children":568},"title",{"id":560},[569],{"type":31,"value":570},"Two current Chromium routes zip past Lambda's 50 MB upload limit",{"type":26,"tag":572,"props":573,"children":574},"desc",{"id":561},[575],{"type":31,"value":576},"Horizontal bar chart of deploy zip size in MB. puppeteer-core with @sparticuz/chromium 78.14 MB; playwright-core with @sparticuz/chromium 75.77 MB; chrome-aws-lambda with puppeteer-core 10 52.28 MB; playwright-aws-lambda with playwright-core 47.54 MB; puppeteer-core with @sparticuz/chromium-min 8.18 MB. A marker shows the 50 MB direct-upload limit.",{"type":26,"tag":578,"props":579,"children":582},"g",{"style":580,"fill":581},"font-size:13px","#0A0C3D",[583,592,599,605,611,617],{"type":26,"tag":31,"props":584,"children":589},{"x":585,"y":586,"fill":587,"style":588},"193","18","#FF9D28","font-weight:500",[590],{"type":31,"value":591},"50 MB upload limit",{"type":26,"tag":31,"props":593,"children":596},{"x":594,"y":595},"0","42",[597],{"type":31,"value":598},"puppeteer-core + @sparticuz/chromium",{"type":26,"tag":31,"props":600,"children":602},{"x":594,"y":601},"98",[603],{"type":31,"value":604},"playwright-core + @sparticuz/chromium",{"type":26,"tag":31,"props":606,"children":608},{"x":594,"y":607},"154",[609],{"type":31,"value":610},"chrome-aws-lambda + puppeteer-core 10",{"type":26,"tag":31,"props":612,"children":614},{"x":594,"y":613},"210",[615],{"type":31,"value":616},"playwright-aws-lambda + playwright-core",{"type":26,"tag":31,"props":618,"children":620},{"x":594,"y":619},"266",[621],{"type":31,"value":622},"puppeteer-core + @sparticuz/chromium-min",{"type":26,"tag":578,"props":624,"children":626},{"fill":625},"#6C47FF",[627,634,639,644,649],{"type":26,"tag":628,"props":629,"children":633},"rect",{"x":594,"y":630,"width":631,"height":586,"rx":632},"48","293","2",[],{"type":26,"tag":628,"props":635,"children":638},{"x":594,"y":636,"width":637,"height":586,"rx":632},"104","284",[],{"type":26,"tag":628,"props":640,"children":643},{"x":594,"y":641,"width":642,"height":586,"rx":632},"160","196",[],{"type":26,"tag":628,"props":645,"children":648},{"x":594,"y":646,"width":647,"height":586,"rx":632},"216","178",[],{"type":26,"tag":628,"props":650,"children":653},{"x":594,"y":651,"width":652,"height":586,"rx":632},"272","31",[],{"type":26,"tag":578,"props":655,"children":659},{"stroke":587,"strokeWidth":632,"strokeDashArray":656},[657,658],"4","3",[660,667,672,677,682],{"type":26,"tag":661,"props":662,"children":666},"line",{"x1":663,"y1":664,"x2":663,"y2":665},"187.5","45","69",[],{"type":26,"tag":661,"props":668,"children":671},{"x1":663,"y1":669,"x2":663,"y2":670},"101","125",[],{"type":26,"tag":661,"props":673,"children":676},{"x1":663,"y1":674,"x2":663,"y2":675},"157","181",[],{"type":26,"tag":661,"props":678,"children":681},{"x1":663,"y1":679,"x2":663,"y2":680},"213","237",[],{"type":26,"tag":661,"props":683,"children":685},{"x1":663,"y1":684,"x2":663,"y2":631},"269",[],{"type":26,"tag":578,"props":687,"children":689},{"style":688,"fill":581},"font-size:13px;font-weight:500",[690,696,702,708,714],{"type":26,"tag":31,"props":691,"children":694},{"x":692,"y":693},"299","62",[695],{"type":31,"value":470},{"type":26,"tag":31,"props":697,"children":700},{"x":698,"y":699},"290","118",[701],{"type":31,"value":488},{"type":26,"tag":31,"props":703,"children":706},{"x":704,"y":705},"202","174",[707],{"type":31,"value":506},{"type":26,"tag":31,"props":709,"children":712},{"x":710,"y":711},"194","230",[713],{"type":31,"value":524},{"type":26,"tag":31,"props":715,"children":718},{"x":716,"y":717},"37","286",[719],{"type":31,"value":542},{"type":26,"tag":578,"props":721,"children":723},{"style":580,"fill":722},"#4C556D",[724,729,734,741,747,753],{"type":26,"tag":661,"props":725,"children":728},{"x1":594,"y1":726,"x2":726,"y2":726,"stroke":727},"300","#DBE4F2",[],{"type":26,"tag":31,"props":730,"children":732},{"x":594,"y":731},"318",[733],{"type":31,"value":594},{"type":26,"tag":31,"props":735,"children":738},{"x":736,"y":731,"textAnchor":737},"75","middle",[739],{"type":31,"value":740},"20",{"type":26,"tag":31,"props":742,"children":744},{"x":743,"y":731,"textAnchor":737},"150",[745],{"type":31,"value":746},"40",{"type":26,"tag":31,"props":748,"children":750},{"x":749,"y":731,"textAnchor":737},"225",[751],{"type":31,"value":752},"60",{"type":26,"tag":31,"props":754,"children":755},{"x":726,"y":731,"textAnchor":737},[756],{"type":31,"value":757},"80 MB",{"type":26,"tag":27,"props":759,"children":760},{},[761,763,769],{"type":31,"value":762},"The weight is one file: ",{"type":26,"tag":34,"props":764,"children":766},{"className":765},[],[767],{"type":31,"value":768},"chromium.br",{"type":31,"value":770},", 67.02 MB of Brotli-compressed Chromium. It's already compressed, so zip can't shrink it. There are four ways past the 50 MB limit:",{"type":26,"tag":132,"props":772,"children":773},{},[774,784,794,804],{"type":26,"tag":136,"props":775,"children":776},{},[777,782],{"type":26,"tag":140,"props":778,"children":779},{},[780],{"type":31,"value":781},"Upload the zip through S3.",{"type":31,"value":783}," Lambda takes larger files from Amazon S3, and the 250 MB unzipped limit still applies.",{"type":26,"tag":136,"props":785,"children":786},{},[787,792],{"type":26,"tag":140,"props":788,"children":789},{},[790],{"type":31,"value":791},"Use a layer.",{"type":31,"value":793}," Each GitHub release has a ready layer zip, and your function zip shrinks to your own code.",{"type":26,"tag":136,"props":795,"children":796},{},[797,802],{"type":26,"tag":140,"props":798,"children":799},{},[800],{"type":31,"value":801},"Use a container image.",{"type":31,"value":803}," Lambda accepts images up to 10 GB.",{"type":26,"tag":136,"props":805,"children":806},{},[807,812,814,820],{"type":26,"tag":140,"props":808,"children":809},{},[810],{"type":31,"value":811},"Use @sparticuz/chromium-min.",{"type":31,"value":813}," It ships without Chromium. You host the ",{"type":26,"tag":34,"props":815,"children":817},{"className":816},[],[818],{"type":31,"value":819},"chromium-pack",{"type":31,"value":821}," tar from the release at a URL, and the function downloads it on a cold start.",{"type":26,"tag":27,"props":823,"children":824},{},[825,827,832,834,840,842,848,850,855,857,862],{"type":31,"value":826},"The zip is only half the cost. At a cold start, ",{"type":26,"tag":34,"props":828,"children":830},{"className":829},[],[831],{"type":31,"value":47},{"type":31,"value":833}," unpacks its files into ",{"type":26,"tag":34,"props":835,"children":837},{"className":836},[],[838],{"type":31,"value":839},"/tmp",{"type":31,"value":841},": the 209.02 MB ",{"type":26,"tag":34,"props":843,"children":845},{"className":844},[],[846],{"type":31,"value":847},"chromium",{"type":31,"value":849}," binary, 7.49 MB of SwiftShader graphics libraries, 0.46 MB of fonts and, on Amazon Linux 2023, 3.53 MB of system libraries. The Node.js 22, 24 and 26 runtimes all run Amazon Linux 2023, so plan for 220.50 MB in ",{"type":26,"tag":34,"props":851,"children":853},{"className":852},[],[854],{"type":31,"value":839},{"type":31,"value":856},", which you can size from 512 MB to 10,240 MB. A warm function keeps ",{"type":26,"tag":34,"props":858,"children":860},{"className":859},[],[861],{"type":31,"value":839},{"type":31,"value":863},", so the unpack happens once per execution environment.",{"type":26,"tag":549,"props":865,"children":867},{"caption":866},"@sparticuz/chromium 153.0.0: files in the package vs what it unpacks into /tmp on Amazon Linux 2023. Our measurement, November 9, 2026.",[868],{"type":26,"tag":554,"props":869,"children":874},{"viewBox":870,"xmlns":557,"role":558,"ariaLabelledBy":871,"style":562,"fontFamily":563},"0 0 400 162",[872,873],"lz-tmp-title","lz-tmp-desc",[875,880,885,904,915,930,936],{"type":26,"tag":566,"props":876,"children":877},{"id":872},[878],{"type":31,"value":879},"70 MB in the package becomes 220.5 MB in /tmp",{"type":26,"tag":572,"props":881,"children":882},{"id":873},[883],{"type":31,"value":884},"Horizontal bar chart in MB. Brotli files in the package: 70.05 MB. Unpacked into /tmp at a cold start: 220.50 MB. A marker shows the smallest /tmp size, 512 MB.",{"type":26,"tag":578,"props":886,"children":887},{"style":580,"fill":581},[888,894,899],{"type":26,"tag":31,"props":889,"children":891},{"x":726,"y":586,"textAnchor":890,"fill":587,"style":588},"end",[892],{"type":31,"value":893},"512 MB: smallest /tmp",{"type":26,"tag":31,"props":895,"children":896},{"x":594,"y":595},[897],{"type":31,"value":898},"Files in the npm package (.br)",{"type":26,"tag":31,"props":900,"children":901},{"x":594,"y":601},[902],{"type":31,"value":903},"Unpacked into /tmp at a cold start",{"type":26,"tag":578,"props":905,"children":906},{"fill":625},[907,911],{"type":26,"tag":628,"props":908,"children":910},{"x":594,"y":630,"width":909,"height":586,"rx":632},"41",[],{"type":26,"tag":628,"props":912,"children":914},{"x":594,"y":636,"width":913,"height":586,"rx":632},"129",[],{"type":26,"tag":578,"props":916,"children":917},{"style":688,"fill":581},[918,924],{"type":26,"tag":31,"props":919,"children":921},{"x":920,"y":693},"47",[922],{"type":31,"value":923},"70.05 MB",{"type":26,"tag":31,"props":925,"children":927},{"x":926,"y":699},"135",[928],{"type":31,"value":929},"220.50 MB",{"type":26,"tag":661,"props":931,"children":935},{"x1":692,"y1":932,"x2":692,"y2":933,"stroke":587,"strokeWidth":632,"strokeDashArray":934},"26","132",[657,658],[],{"type":26,"tag":578,"props":937,"children":938},{"style":580,"fill":722},[939,943,948,953],{"type":26,"tag":661,"props":940,"children":942},{"x1":594,"y1":941,"x2":726,"y2":941,"stroke":727},"138",[],{"type":26,"tag":31,"props":944,"children":946},{"x":594,"y":945},"156",[947],{"type":31,"value":594},{"type":26,"tag":31,"props":949,"children":950},{"x":743,"y":945,"textAnchor":737},[951],{"type":31,"value":952},"256",{"type":26,"tag":31,"props":954,"children":955},{"x":726,"y":945,"textAnchor":890},[956],{"type":31,"value":957},"512 MB",{"type":26,"tag":70,"props":959,"children":961},{"id":960},"is-chrome-aws-lambda-still-maintained",[962],{"type":31,"value":963},"Is chrome-aws-lambda still maintained?",{"type":26,"tag":27,"props":965,"children":966},{},[967,969,975,977,982],{"type":31,"value":968},"No. Its last release, 10.1.0, came out July 17, 2021, with Chromium 92. Its fork, ",{"type":26,"tag":34,"props":970,"children":972},{"className":971},[],[973],{"type":31,"value":974},"@sparticuz/chrome-aws-lambda",{"type":31,"value":976},", is marked deprecated on npm with \"Please migrate to @sparticuz/chromium\". If you're still on it, your PDFs come out of a 2021 browser. Moving means swapping the package and the launch options for the ones above, and pinning a ",{"type":26,"tag":34,"props":978,"children":980},{"className":979},[],[981],{"type":31,"value":39},{"type":31,"value":983}," that matches.",{"type":26,"tag":70,"props":985,"children":987},{"id":986},"how-do-you-use-playwright-with-sparticuzchromium",[988],{"type":31,"value":989},"How do you use Playwright with @sparticuz/chromium?",{"type":26,"tag":27,"props":991,"children":992},{},[993,995,1000,1002,1008],{"type":31,"value":994},"Point Playwright's Chromium at the binary ",{"type":26,"tag":34,"props":996,"children":998},{"className":997},[],[999],{"type":31,"value":47},{"type":31,"value":1001}," unpacks, and give each call its own user data directory. Here it is for ",{"type":26,"tag":34,"props":1003,"children":1005},{"className":1004},[],[1006],{"type":31,"value":1007},"playwright-core",{"type":31,"value":1009}," 1.65.0:",{"type":26,"tag":96,"props":1011,"children":1014},{"className":1012,"code":1013,"language":101,"meta":7},[99],"import chromium from '@sparticuz/chromium';\nimport { chromium as playwright } from 'playwright-core';\nimport { randomUUID } from 'node:crypto';\nimport { rm } from 'node:fs/promises';\n\nexport const handler = async (event) => {\n    // A fresh user data dir per call, removed afterwards\n    const userDataDir = `/tmp/pw-${randomUUID()}`;\n    const browser = await playwright.launch({\n        args: [...chromium.args, `--user-data-dir=${userDataDir}`],\n        executablePath: await chromium.executablePath(),\n        headless: true,\n    });\n\n    try {\n        const page = await browser.newPage();\n        await page.setContent(event.html, { waitUntil: 'load' });\n        const pdf = await page.pdf({ format: 'A4', printBackground: true });\n        // Then write pdf to S3, as in the Puppeteer handler above\n    } finally {\n        await browser.close();\n        await rm(userDataDir, { recursive: true, force: true });\n    }\n};\n",[1015],{"type":26,"tag":34,"props":1016,"children":1017},{"__ignoreMap":7},[1018],{"type":31,"value":1013},{"type":26,"tag":27,"props":1020,"children":1021},{},[1022,1024,1029,1031,1037,1039,1046,1048,1054],{"type":31,"value":1023},"Playwright doesn't clean its user data directory between calls on a warm Lambda. Without the per-call folder, ",{"type":26,"tag":34,"props":1025,"children":1027},{"className":1026},[],[1028],{"type":31,"value":839},{"type":31,"value":1030}," fills up and you get ",{"type":26,"tag":34,"props":1032,"children":1034},{"className":1033},[],[1035],{"type":31,"value":1036},"ERR_INSUFFICIENT_RESOURCES",{"type":31,"value":1038},". Playwright's docs also say it ",{"type":26,"tag":148,"props":1040,"children":1043},{"href":1041,"rel":1042},"https://playwright.dev/docs/api/class-browsertype",[152],[1044],{"type":31,"value":1045},"\"only works with the bundled Chromium\"",{"type":31,"value":1047},", so a custom ",{"type":26,"tag":34,"props":1049,"children":1051},{"className":1050},[],[1052],{"type":31,"value":1053},"executablePath",{"type":31,"value":1055}," is \"use at your own risk\", and the same version pairing applies.",{"type":26,"tag":27,"props":1057,"children":1058},{},[1059,1061,1067,1069,1075,1077,1083],{"type":31,"value":1060},"The older ",{"type":26,"tag":34,"props":1062,"children":1064},{"className":1063},[],[1065],{"type":31,"value":1066},"playwright-aws-lambda",{"type":31,"value":1068}," was last released as 0.11.0 on July 25, 2024, and its README lists runtimes up to ",{"type":26,"tag":34,"props":1070,"children":1072},{"className":1071},[],[1073],{"type":31,"value":1074},"nodejs20.x",{"type":31,"value":1076},". For page options, timeouts and memory, see ",{"type":26,"tag":148,"props":1078,"children":1080},{"href":1079},"/guides/playwright-pdf-in-production/",[1081],{"type":31,"value":1082},"our Playwright PDF guide",{"type":31,"value":226},{"type":26,"tag":70,"props":1085,"children":1087},{"id":1086},"how-do-you-generate-pdfs-with-puppeteer-on-vercel",[1088],{"type":31,"value":1089},"How do you generate PDFs with Puppeteer on Vercel?",{"type":26,"tag":27,"props":1091,"children":1092},{},[1093,1100,1102,1107,1109,1115,1117,1123],{"type":26,"tag":148,"props":1094,"children":1097},{"href":1095,"rel":1096},"https://vercel.com/kb/guide/deploying-puppeteer-with-nextjs-on-vercel",[152],[1098],{"type":31,"value":1099},"Vercel's own guide",{"type":31,"value":1101}," uses ",{"type":26,"tag":34,"props":1103,"children":1105},{"className":1104},[],[1106],{"type":31,"value":39},{"type":31,"value":1108}," with ",{"type":26,"tag":34,"props":1110,"children":1112},{"className":1111},[],[1113],{"type":31,"value":1114},"@sparticuz/chromium-min",{"type":31,"value":1116},", because the full ",{"type":26,"tag":34,"props":1118,"children":1120},{"className":1119},[],[1121],{"type":31,"value":1122},"puppeteer",{"type":31,"value":1124}," package is too large for the 250 MB function limit. In a Next.js route, that looks like this:",{"type":26,"tag":96,"props":1126,"children":1129},{"className":1127,"code":1128,"language":101,"meta":7},[99],"// app/api/pdf/route.js\nimport chromium from '@sparticuz/chromium-min';\nimport puppeteer from 'puppeteer-core';\n\nexport async function POST(request) {\n    const { html } = await request.json();\n    const browser = await puppeteer.launch({\n        args: await puppeteer.defaultArgs({ args: chromium.args, headless: 'shell' }),\n        // The chromium-pack tar from the @sparticuz/chromium release, hosted by you\n        executablePath: await chromium.executablePath(process.env.CHROMIUM_PACK_URL),\n        headless: 'shell',\n    });\n\n    try {\n        const page = await browser.newPage();\n        await page.setContent(html, { waitUntil: 'load' });\n        const pdf = await page.pdf({ format: 'A4', printBackground: true });\n        return new Response(pdf, { headers: { 'Content-Type': 'application/pdf' } });\n    } finally {\n        await browser.close();\n    }\n}\n",[1130],{"type":26,"tag":34,"props":1131,"children":1132},{"__ignoreMap":7},[1133],{"type":31,"value":1128},{"type":26,"tag":27,"props":1135,"children":1136},{},[1137,1139,1145,1147,1152,1153,1158,1160,1166,1168,1175,1177,1183],{"type":31,"value":1138},"In ",{"type":26,"tag":34,"props":1140,"children":1142},{"className":1141},[],[1143],{"type":31,"value":1144},"next.config.js",{"type":31,"value":1146},", list ",{"type":26,"tag":34,"props":1148,"children":1150},{"className":1149},[],[1151],{"type":31,"value":39},{"type":31,"value":41},{"type":26,"tag":34,"props":1154,"children":1156},{"className":1155},[],[1157],{"type":31,"value":47},{"type":31,"value":1159}," in ",{"type":26,"tag":34,"props":1161,"children":1163},{"className":1162},[],[1164],{"type":31,"value":1165},"serverExternalPackages",{"type":31,"value":1167},". In the ",{"type":26,"tag":148,"props":1169,"children":1172},{"href":1170,"rel":1171},"https://community.vercel.com/t/sparticuz-chromium-min-working-with-vercel-for-pdf/7877",[152],[1173],{"type":31,"value":1174},"Vercel community thread",{"type":31,"value":1176}," where the function failed with ",{"type":26,"tag":34,"props":1178,"children":1180},{"className":1179},[],[1181],{"type":31,"value":1182},"The input directory \"/var/task/.next/server/bin\" does not exist",{"type":31,"value":1184},", that setting plus hosting the pack at a URL was the fix.",{"type":26,"tag":27,"props":1186,"children":1187},{},[1188],{"type":31,"value":1189},"Here's what Vercel gives that function:",{"type":26,"tag":132,"props":1191,"children":1192},{},[1193,1202],{"type":26,"tag":136,"props":1194,"children":1195},{},[1196,1200],{"type":26,"tag":140,"props":1197,"children":1198},{},[1199],{"type":31,"value":144},{"type":31,"value":1201}," 2 GB with 1 vCPU on Hobby. Up to 4 GB with 2 vCPUs on Pro and Enterprise.",{"type":26,"tag":136,"props":1203,"children":1204},{},[1205,1210],{"type":26,"tag":140,"props":1206,"children":1207},{},[1208],{"type":31,"value":1209},"Duration.",{"type":31,"value":1211}," 300 seconds by default with fluid compute, up to 800 seconds on Pro and Enterprise.",{"type":26,"tag":70,"props":1213,"children":1215},{"id":1214},"why-wont-my-pdf-come-back-from-lambda-or-vercel",[1216],{"type":31,"value":1217},"Why won't my PDF come back from Lambda or Vercel?",{"type":26,"tag":27,"props":1219,"children":1220},{},[1221,1223,1230],{"type":31,"value":1222},"Because it's bigger than the response limit. A synchronous Lambda call returns at most 6 MB, and a Vercel function body at most ",{"type":26,"tag":148,"props":1224,"children":1227},{"href":1225,"rel":1226},"https://vercel.com/docs/functions/limitations",[152],[1228],{"type":31,"value":1229},"4.5 MB",{"type":31,"value":1231},". Return it as base64 and it grows by a third first. So a 4.5 MB PDF already fills Lambda's 6 MB, and on Vercel a base64 PDF has to stay under 3.37 MB.",{"type":26,"tag":549,"props":1233,"children":1235},{"caption":1234},"Largest PDF one response can carry, from Lambda's 6 MB synchronous response limit and Vercel's 4.5 MB body limit. Base64 turns every 3 bytes into 4.",[1236],{"type":26,"tag":554,"props":1237,"children":1242},{"viewBox":1238,"xmlns":557,"role":558,"ariaLabelledBy":1239,"style":562,"fontFamily":563},"0 0 400 186",[1240,1241],"lz-resp-title","lz-resp-desc",[1243,1248,1253,1274,1290,1311],{"type":26,"tag":566,"props":1244,"children":1245},{"id":1240},[1246],{"type":31,"value":1247},"A PDF over 4.5 MB doesn't fit in one response",{"type":26,"tag":572,"props":1249,"children":1250},{"id":1241},[1251],{"type":31,"value":1252},"Horizontal bar chart of the largest PDF in MB that fits in one response. Lambda, base64 in a 6 MB response: 4.5 MB. Vercel, raw bytes in a 4.5 MB body: 4.5 MB. Vercel, base64 in a 4.5 MB body: 3.37 MB.",{"type":26,"tag":578,"props":1254,"children":1255},{"style":580,"fill":581},[1256,1262,1268],{"type":26,"tag":31,"props":1257,"children":1259},{"x":594,"y":1258},"16",[1260],{"type":31,"value":1261},"Lambda, base64 in a 6 MB response",{"type":26,"tag":31,"props":1263,"children":1265},{"x":594,"y":1264},"72",[1266],{"type":31,"value":1267},"Vercel, raw bytes in a 4.5 MB body",{"type":26,"tag":31,"props":1269,"children":1271},{"x":594,"y":1270},"128",[1272],{"type":31,"value":1273},"Vercel, base64 in a 4.5 MB body",{"type":26,"tag":578,"props":1275,"children":1276},{"fill":625},[1277,1281,1285],{"type":26,"tag":628,"props":1278,"children":1280},{"x":594,"y":1279,"width":749,"height":586,"rx":632},"22",[],{"type":26,"tag":628,"props":1282,"children":1284},{"x":594,"y":1283,"width":749,"height":586,"rx":632},"78",[],{"type":26,"tag":628,"props":1286,"children":1289},{"x":594,"y":1287,"width":1288,"height":586,"rx":632},"134","169",[],{"type":26,"tag":578,"props":1291,"children":1292},{"style":688,"fill":581},[1293,1299,1304],{"type":26,"tag":31,"props":1294,"children":1297},{"x":1295,"y":1296},"231","36",[1298],{"type":31,"value":1229},{"type":26,"tag":31,"props":1300,"children":1302},{"x":1295,"y":1301},"92",[1303],{"type":31,"value":1229},{"type":26,"tag":31,"props":1305,"children":1308},{"x":1306,"y":1307},"175","148",[1309],{"type":31,"value":1310},"3.37 MB",{"type":26,"tag":578,"props":1312,"children":1313},{"style":580,"fill":722},[1314,1318,1323,1328,1333],{"type":26,"tag":661,"props":1315,"children":1317},{"x1":594,"y1":1316,"x2":726,"y2":1316,"stroke":727},"162",[],{"type":26,"tag":31,"props":1319,"children":1321},{"x":594,"y":1320},"180",[1322],{"type":31,"value":594},{"type":26,"tag":31,"props":1324,"children":1326},{"x":1325,"y":1320,"textAnchor":737},"100",[1327],{"type":31,"value":632},{"type":26,"tag":31,"props":1329,"children":1331},{"x":1330,"y":1320,"textAnchor":737},"200",[1332],{"type":31,"value":657},{"type":26,"tag":31,"props":1334,"children":1335},{"x":726,"y":1320,"textAnchor":737},[1336],{"type":31,"value":1337},"6 MB",{"type":26,"tag":27,"props":1339,"children":1340},{},[1341],{"type":31,"value":1342},"Two ways out:",{"type":26,"tag":132,"props":1344,"children":1345},{},[1346,1356],{"type":26,"tag":136,"props":1347,"children":1348},{},[1349,1354],{"type":26,"tag":140,"props":1350,"children":1351},{},[1352],{"type":31,"value":1353},"Write it to S3 and return the URL or key",{"type":31,"value":1355},", like the Lambda handler above.",{"type":26,"tag":136,"props":1357,"children":1358},{},[1359,1364],{"type":26,"tag":140,"props":1360,"children":1361},{},[1362],{"type":31,"value":1363},"Stream it.",{"type":31,"value":1365}," Lambda's streamed responses go up to 200 MB, and Vercel's limit doesn't apply to streamed responses.",{"type":26,"tag":70,"props":1367,"children":1369},{"id":1368},"which-fonts-does-sparticuzchromium-include",[1370],{"type":31,"value":1371},"Which fonts does @sparticuz/chromium include?",{"type":26,"tag":27,"props":1373,"children":1374},{},[1375,1377,1383,1385,1391,1393,1399,1400,1406,1407,1413],{"type":31,"value":1376},"Only Open Sans, in regular, bold and italic, which covers Latin, Greek and Cyrillic. The Lambda runtime has no fonts of its own, so your brand font, or text in any other script, has to come with you. Add fonts through a Lambda layer, or in a ",{"type":26,"tag":34,"props":1378,"children":1380},{"className":1379},[],[1381],{"type":31,"value":1382},"fonts",{"type":31,"value":1384}," folder in your function. The package looks in ",{"type":26,"tag":34,"props":1386,"children":1388},{"className":1387},[],[1389],{"type":31,"value":1390},"/var/task/fonts",{"type":31,"value":1392},", ",{"type":26,"tag":34,"props":1394,"children":1396},{"className":1395},[],[1397],{"type":31,"value":1398},"/var/task/.fonts",{"type":31,"value":1392},{"type":26,"tag":34,"props":1401,"children":1403},{"className":1402},[],[1404],{"type":31,"value":1405},"/opt/fonts",{"type":31,"value":41},{"type":26,"tag":34,"props":1408,"children":1410},{"className":1409},[],[1411],{"type":31,"value":1412},"/tmp/fonts",{"type":31,"value":1414},". Emoji need their own font file, such as Noto Color Emoji.",{"type":26,"tag":70,"props":1416,"children":1418},{"id":1417},"what-does-the-same-function-look-like-without-chromium",[1419],{"type":31,"value":1420},"What does the same function look like without Chromium?",{"type":26,"tag":27,"props":1422,"children":1423},{},[1424,1426,1432],{"type":31,"value":1425},"It's one ",{"type":26,"tag":34,"props":1427,"children":1429},{"className":1428},[],[1430],{"type":31,"value":1431},"fetch",{"type":31,"value":1433}," call to a Chromium we run, and have run for PDFs since 2018. The handler below zips to under 1 KB, against 78.14 MB for the Puppeteer one, and it has no versions to match, nothing to unpack and no 50 MB limit to dodge:",{"type":26,"tag":96,"props":1435,"children":1438},{"className":1436,"code":1437,"language":101,"meta":7},[99],"// index.mjs: no dependencies\nexport const handler = async (event) => {\n    const response = await fetch('https://api.pdfshift.io/v3/convert/pdf', {\n        method: 'POST',\n        headers: {\n            'X-API-Key': process.env.PDFSHIFT_API_KEY,\n            'Content-Type': 'application/json',\n        },\n        // filename makes PDFShift return JSON with a URL instead of the file\n        body: JSON.stringify({ source: event.html, filename: 'invoice.pdf' }),\n    });\n\n    if (!response.ok) {\n        throw new Error(`PDFShift returned ${response.status}: ${await response.text()}`);\n    }\n\n    const { url } = await response.json();\n    return { url };\n};\n",[1439],{"type":26,"tag":34,"props":1440,"children":1441},{"__ignoreMap":7},[1442],{"type":31,"value":1437},{"type":26,"tag":27,"props":1444,"children":1445},{},[1446,1448,1454,1456,1461,1463,1469,1471,1477],{"type":31,"value":1447},"With ",{"type":26,"tag":34,"props":1449,"children":1451},{"className":1450},[],[1452],{"type":31,"value":1453},"filename",{"type":31,"value":1455},", the PDF never passes through your function's response, so the 6 MB and 4.5 MB limits don't apply. We keep that file for 2 days, then delete it. Without ",{"type":26,"tag":34,"props":1457,"children":1459},{"className":1458},[],[1460],{"type":31,"value":1453},{"type":31,"value":1462},", you get the raw PDF back. ",{"type":26,"tag":34,"props":1464,"children":1466},{"className":1465},[],[1467],{"type":31,"value":1468},"s3_destination",{"type":31,"value":1470}," saves it straight to your own bucket, and ",{"type":26,"tag":34,"props":1472,"children":1474},{"className":1473},[],[1475],{"type":31,"value":1476},"webhook",{"type":31,"value":1478}," makes the call async and posts you the URL when it's done.",{"type":26,"tag":27,"props":1480,"children":1481},{},[1482,1484,1490,1492,1498,1500,1507],{"type":31,"value":1483},"The free plan gives you 50 credits a month with no card, and ",{"type":26,"tag":34,"props":1485,"children":1487},{"className":1486},[],[1488],{"type":31,"value":1489},"sandbox: true",{"type":31,"value":1491}," makes watermarked test PDFs that don't use credits. ",{"type":26,"tag":148,"props":1493,"children":1495},{"href":1494},"/register/",[1496],{"type":31,"value":1497},"Create a free account",{"type":31,"value":1499}," to get a key, and check the ",{"type":26,"tag":148,"props":1501,"children":1504},{"href":1502,"rel":1503},"https://docs.pdfshift.io/api-reference/convert-to-pdf",[152],[1505],{"type":31,"value":1506},"convert endpoint reference",{"type":31,"value":1508}," for every parameter.",{"type":26,"tag":70,"props":1510,"children":1512},{"id":1511},"frequently-asked-questions",[1513],{"type":31,"value":1514},"Frequently asked questions",{"type":26,"tag":1516,"props":1517,"children":1519},"h3",{"id":1518},"does-sparticuzchromium-work-on-arm64-graviton-lambda-functions",[1520],{"type":31,"value":14},{"type":26,"tag":27,"props":1522,"children":1523},{},[1524,1526,1531],{"type":31,"value":1525},"Not from the main npm package, which includes only x64 binaries. Since Chromium 135, each GitHub release also has an arm64 Lambda layer zip and an arm64 pack tar. Use the layer, or ",{"type":26,"tag":34,"props":1527,"children":1529},{"className":1528},[],[1530],{"type":31,"value":1114},{"type":31,"value":1532}," with the arm64 pack.",{"type":26,"tag":1516,"props":1534,"children":1536},{"id":1535},"how-do-i-add-a-lambda-layer-for-sparticuzchromium",[1537],{"type":31,"value":17},{"type":26,"tag":27,"props":1539,"children":1540},{},[1541,1543,1549,1551,1556],{"type":31,"value":1542},"Take the layer zip from a GitHub release, or build it with ",{"type":26,"tag":34,"props":1544,"children":1546},{"className":1545},[],[1547],{"type":31,"value":1548},"make chromium.x64.zip",{"type":31,"value":1550}," from the repository. It's over 50 MB, so upload it to S3 and publish the layer from there. Then make ",{"type":26,"tag":34,"props":1552,"children":1554},{"className":1553},[],[1555],{"type":31,"value":47},{"type":31,"value":1557}," a dev dependency, since the layer carries the binary. Without a layer, it stays a production dependency.",{"type":26,"tag":1516,"props":1559,"children":1561},{"id":1560},"can-sparticuzchromium-make-tagged-accessible-pdfs",[1562],{"type":31,"value":20},{"type":26,"tag":27,"props":1564,"children":1565},{},[1566],{"type":31,"value":21},{"title":7,"searchDepth":1568,"depth":1568,"links":1569},2,[1570,1571,1572,1573,1574,1575,1576,1577,1578,1579],{"id":72,"depth":1568,"text":75},{"id":229,"depth":1568,"text":232},{"id":403,"depth":1568,"text":406},{"id":960,"depth":1568,"text":963},{"id":986,"depth":1568,"text":989},{"id":1086,"depth":1568,"text":1089},{"id":1214,"depth":1568,"text":1217},{"id":1368,"depth":1568,"text":1371},{"id":1417,"depth":1568,"text":1420},{"id":1511,"depth":1568,"text":1514,"children":1580},[1581,1583,1584],{"id":1518,"depth":1582,"text":14},3,{"id":1535,"depth":1582,"text":17},{"id":1560,"depth":1582,"text":20},"markdown","content:guides:puppeteer-pdf-aws-lambda.md","content","guides/puppeteer-pdf-aws-lambda.md","md",1794330363645]