Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesRun Puppeteer inside a Node.js Netlify Function, but deploy a compatible Chromium binary with it: production functions cannot rely on Chrome installed on your computer. A common serverless setup uses puppeteer-core with @sparticuz/chromium, passing the latter’s launch arguments and executable path to Puppeteer and closing the browser in a finally block. The example below returns a page title; the same browser setup can capture screenshots or PDFs.
Choose how the function gets Chromium
Puppeteer is the automation library; Chrome or Chromium is a separate runtime dependency that must be present wherever the function runs. Puppeteer’s documentation describes the browser automation library, while its package choice determines how you supply the browser.
Use a bundled serverless Chromium for a controlled deployment
This guide uses puppeteer-core and @sparticuz/chromium. puppeteer-core does not download Chrome: your application must provide an executable path. The Chromium package supplies a serverless-oriented binary and launch arguments, and its project documentation includes Netlify examples. Choose releases compatible with one another; compatibility is version-sensitive, so do not copy a version number from an old code sample without checking the current package guidance. See the Puppeteer installation guide, configuration guide, and @sparticuz/chromium project.
Use Puppeteer’s downloaded browser only if it will be deployed
The puppeteer package downloads a compatible Chrome for Testing by default. That route can work if the browser download actually runs during installation and the browser is included in the function deployment. Some package managers block install scripts; if that happens, Puppeteer may fail at runtime with “Could not find Chrome.” A local cache or locally installed browser does not prove the deployed function has one.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstall#1 Best Overall
Create a Netlify Function
Netlify’s default JavaScript function directory is netlify/functions/ under the project base directory. The function’s source directory should be outside the publish directory. Netlify’s official function setup guide describes the handler model: it receives a Request and returns a Response. If your project uses a different function directory, configure it in project settings or netlify.toml; see function configuration.
Install production dependencies
Install compatible current releases of both packages as production dependencies, using your package manager. For example, with npm:
npm install puppeteer-core @sparticuz/chromium
This command intentionally does not pin versions. Check the Chromium project’s current compatibility notes before selecting releases, then commit the lockfile so your build resolves the same package versions. The example assumes the dependencies are installed from the project’s normal dependency manifest and available to Netlify’s function bundler.
Rank #2
Implement the handler
Create netlify/functions/page-info.mjs:
import puppeteer from "puppeteer-core";
import chromium from "@sparticuz/chromium";
export default async function handler() {
let browser;
try {
browser = await puppeteer.launch({
args: chromium.args,
defaultViewport: chromium.defaultViewport,
executablePath: await chromium.executablePath(),
headless: true,
});
const page = await browser.newPage();
page.setDefaultNavigationTimeout(20000);
await page.goto("https://example.com", {
waitUntil: "domcontentloaded",
timeout: 20000,
});
const title = await page.title();
return new Response(JSON.stringify({ title }), {
headers: { "content-type": "application/json; charset=utf-8" },
});
} catch (error) {
console.error("Puppeteer function failed", error);
return new Response(JSON.stringify({ error: "Unable to load the page" }), {
status: 500,
headers: { "content-type": "application/json; charset=utf-8" },
});
} finally {
if (browser) await browser.close();
}
}
The URL is a fixed example to keep the handler focused. If you accept a URL from a request, validate it and restrict allowed destinations as appropriate for your application; otherwise the function could be abused to make requests to unintended hosts or internal addresses. Set navigation and action timeouts to fit the function’s overall execution window. Adjust waitUntil when the target requires more than initial DOM readiness, but note that waiting for every network request to finish can be unreliable on pages with persistent connections or ongoing analytics.
The try/finally arrangement closes Chromium even if navigation or extraction throws. The Chromium project specifically recommends closing the browser, and its arguments and executable path should be used rather than a developer machine’s Chrome path.
Deploy the browser with the function
Browser packaging is part of the implementation, not an afterthought. Put @sparticuz/chromium in production dependencies when not using a layer, and confirm the Netlify build includes its browser files alongside the function. Netlify’s function and CLI documentation explains dependency and bundling behavior; in particular, the build system does not recursively install dependencies inside every unbundled function folder. If your layout keeps dependencies within function folders, follow Netlify’s guidance for a prebuild or postinstall install step rather than assuming deployment will populate them. See Netlify CLI function management and CLI deployment guidance.
- Confirm the function directory is configured and outside the publish directory.
- Ensure both packages are declared as deployment dependencies and the lockfile is committed.
- Check that the function bundle contains the Chromium runtime files, not merely the JavaScript package.
- Run the function locally with Netlify CLI, then deploy and test the deployed endpoint. Local success cannot establish that the production Linux binary and bundle are correct.
Use the Netlify CLI function guide for current local invocation and log commands; CLI supports netlify dev and standalone function serving. Netlify documents browser invocation for GET requests and netlify functions:invoke for other request types. Function logs are available in the Netlify UI or through CLI streaming.
Choose synchronous or background execution
A synchronous function is suitable when browser work is bounded and the caller needs a result immediately. Netlify currently documents default function settings of 1024 MB memory and a 60-second synchronous execution limit; scheduled functions have a 30-second default limit. These are platform defaults, not estimates of Puppeteer startup time or page throughput. Check your project’s configured limits and plan before relying on them. Netlify also lists default buffered request and response payload limits of 6 MB and streamed response payload limits of 20 MB on its configuration page. A large screenshot or PDF may therefore need to be stored elsewhere rather than returned in the function response.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Use a Background Function for work that should outlast the request
Netlify Background Functions run asynchronously and initially return HTTP 202. Netlify documents a maximum run time of up to 15 minutes for this function type and identifies scraping and slower processing as suitable examples. A background function does not stream its eventual result back to the original caller. Save the output to a database or object store, or deliver it to another destination, then expose a result location or job identifier to the caller. See the Background Functions overview.
Rank #4
Moving a task to the background does not by itself make it reliable. Browser memory use, function bundle size, cold starts, target-site behavior, and output size still affect whether the design works. Keep the browser task bounded and make failure or completion visible to the system that requested the job.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Capture a screenshot or PDF instead of page information
Once the browser has navigated to a page, Puppeteer can produce an image or PDF. Replace the title extraction and JSON response with an output flow appropriate to the file’s size:
const image = await page.screenshot({ type: "png", fullPage: true });
// Or create a PDF in a headless Chromium context:
const pdf = await page.pdf({ format: "A4", printBackground: true });
These calls produce binary data. For a small response, return bytes with an accurate content type, such as image/png or application/pdf. For larger files, write the result to a storage destination and return a reference or job identifier; Netlify’s documented payload limits make returning a large capture directly unsuitable in some cases. Any filesystem or storage strategy must work in the deployed function environment, not depend on a persistent developer-machine path.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Best Value
- Used Book in Good Condition
Troubleshoot common deployment failures
- “Could not find Chrome.” With
puppeteer, check whether the browser install script ran and whether its downloaded browser made it into the deployment. Withpuppeteer-core, supply a browser explicitly. The installation guide explains the install-script issue. - Executable path error. Use
await chromium.executablePath()from the serverless Chromium package, not a path copied from a workstation. - Chromium exits immediately. Verify the selected binary is suitable for the deployed Linux runtime, that its release is compatible with Puppeteer, and that you pass the package’s launch arguments.
- Function bundle or module resolution error. Confirm both packages are production dependencies and that Netlify includes the browser files. For unbundled function-folder layouts, follow Netlify’s dependency installation guidance rather than assuming recursive installation.
- Works locally, fails after deployment. Treat the difference as a runtime or bundle mismatch to investigate. A local Chrome installation does not establish that the production function contains a compatible binary.
- Timeout or memory failure. Reduce page work, avoid unnecessary waits and assets, and check the configured limits and logs. Use a Background Function only when asynchronous delivery fits the caller’s needs.
- Screenshot or PDF response fails or is too large. Check the applicable buffered or streamed payload limit and store large output externally instead of returning it inline.
Puppeteer’s troubleshooting guide covers browser installation and runtime issues; Netlify’s function documentation covers local invocation and logs.
Or skip the browser setup
If the goal is simply a website screenshot or PDF rather than custom in-browser automation, ScreenshotNeo is a screenshot API and MCP server for developers. One GET request can return PNG, JPEG, WebP, or PDF, and its response identifies page verdict and billing status. Its clean-shot behavior accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; individual steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. AI agents can use its MCP server tools, including take_screenshot, get_page_info, and capture_pdf.
For example, save a WebP capture with cURL:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for setup and options. Its Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month, with no card required.
Frequently Asked Questions
Can I use Puppeteer in a Netlify Function?
Yes. Use a Node.js function and deploy a compatible Chromium binary with it; the browser must exist in the production function environment.
Why does Puppeteer work locally but fail on Netlify?
The deployed function may lack the browser files or use a binary, package version, or launch configuration incompatible with its Linux runtime. Local Chrome is not automatically deployed.
Can a Netlify Function return a Puppeteer PDF?
It can return a small PDF if it fits the applicable response limits. For larger files or longer jobs, store the PDF and return a reference through an asynchronous workflow.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




