Is Puppeteer Free for Commercial Website Screenshot Automation?
Yes. Puppeteer is Apache-2.0 licensed, but browser terms and permission to automate a target website are separate questions.
Yes. Puppeteer is distributed under the Apache License 2.0, which generally permits commercial use subject to the license’s conditions. That covers the Puppeteer software; it does not settle the terms for the browser binary or give permission to automate every website. This is a practical reading of the published license, not individualized legal advice. See the Puppeteer license and official project README.
What “free for commercial use” covers
The Puppeteer project and the puppeteer-core package metadata specify Apache-2.0. You can generally use the library in commercial screenshot automation, subject to that license. If you redistribute covered software, review the license and meet its applicable license, notice, and attribution requirements.
Keep three separate questions in view:
| Component | What to check |
|---|---|
| Puppeteer library | Apache-2.0 terms for the version you use, including obligations that apply if you redistribute it. |
| Browser binary | The terms for the specific Chrome or Firefox distribution and how it is installed or deployed. |
| Target website | The site’s terms and applicable rules for automated access, screenshots, and any customer work. |
The Puppeteer license does not grant rights to access or automate a third-party website. The project says the calling code is responsible for using Puppeteer safely and as intended; review the Puppeteer security policy and the target site’s terms.
Install Puppeteer and capture a website screenshot
The following is a minimal Node.js example. It launches a browser, navigates to a page, writes a full-page PNG, then closes the browser even if navigation or capture fails.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'shot.png', fullPage: true });
} finally {
await browser.close();
}
Save this as screenshot.mjs, install the package with npm install puppeteer, and run node screenshot.mjs. Puppeteer’s screenshot guide documents Page.screenshot() and element screenshots; consult the official screenshots guide and Page.screenshot() API for current options.
Capture one element instead of the whole page
const card = await page.waitForSelector('.pricing-card');
if (!card) throw new Error('Pricing card was not found');
await card.screenshot({ path: 'pricing-card.png' });
ElementHandle.screenshot() captures the selected element. Make sure the selector identifies the intended element and that it is present before capture.
Choose the package and browser setup
The official README distinguishes the two common packages:
| Package | Browser installation | Choose it when |
|---|---|---|
puppeteer |
Downloads a compatible Chrome during installation by default. | You want the package to manage its compatible browser download. |
puppeteer-core |
Installs the automation library without downloading Chrome. | You manage the browser installation and launch configuration yourself. |
For the second option, install puppeteer-core and point launch at a browser executable available in your environment:
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.launch({
executablePath: '/path/to/chrome',
headless: true
});
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: 'shot.png', fullPage: true });
} finally {
await browser.close();
}
Replace the executable path with the browser path for your deployment. Check the terms for that browser build separately from Puppeteer’s Apache-2.0 license. Package managers may block dependency install scripts; because Puppeteer’s browser download runs during installation, follow the project’s documented browser installation steps if the download was skipped.
Options and practical capture choices
- Navigation readiness: choose a
waitUntilcondition appropriate to the page. The example usesnetworkidle2; pages with ongoing requests may not reach network idle reliably. For such pages, wait for a meaningful selector or an application-specific ready signal before capturing. - Full page versus viewport: set
fullPage: truewhen the output should include content below the viewport. Omit it for a viewport capture. - Output: the examples write PNG files. Consult the screenshot API documentation for supported capture options in the version installed.
- Element capture: wait for the target element and call its
screenshot()method when only one component is needed. - Resource and page behavior: pages may load content after initial navigation, require authentication, or behave differently with automation. Account for those conditions in the page flow and ensure the access is authorized.
Do not infer that every browser option or deployment component shares Puppeteer’s license. Verify the exact package version, its license files, and the browser distribution used by your application.
Reliability, runtime, and cost considerations
The research sources establish the package licensing and browser-installation distinction; they do not provide benchmarks or a cost comparison. In practice, the setup choice affects what your deployment must supply: puppeteer downloads a compatible Chrome during install, while puppeteer-core leaves browser installation to you. Make sure your runtime has the expected browser available and that installation scripts have not been blocked.
Screenshot success also depends on navigation completing and the page reaching the state you intend to capture. A full-page capture can include much more content than a viewport capture, while element capture depends on a matching element being present. Add handling for navigation and selector failures, close the browser in cleanup code, and check the license and terms for the library, browser, and target site independently.
Common errors and fixes
| Symptom | Likely cause | What to do |
|---|---|---|
| Browser executable not found | The compatible browser download did not run, or puppeteer-core has no browser path configured. |
Install the browser using the project’s documented steps, or set executablePath to the installed browser. |
| Install succeeds but launch fails | A package manager blocked install scripts, preventing Puppeteer’s browser download. | Use the project’s manual browser installation instructions, then confirm the browser is available to the runtime. |
| Navigation waits indefinitely or times out | The site keeps network requests open, is slow, or does not reach the selected readiness condition. | Choose a readiness condition suited to the page and wait for a specific selector or application-ready state where appropriate. |
| Screenshot omits expected content | Content was not rendered or loaded before capture, or the capture is limited to the viewport. | Wait for the relevant content and use fullPage: true if the entire page is required. |
| Element screenshot fails | The selector did not match an element at capture time. | Wait for the selector, verify it matches the intended element, and handle the missing-element case. |
Or skip the browser setup
If you need a screenshot endpoint instead of managing a browser install and capture flow, ScreenshotNeo is a website screenshot API and MCP server. Its API accepts a URL and returns an image or PDF. The API parameters other screenshot APIs use also work, which can make switching easier. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed; and its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for free and get 1,000 screenshots a month with no card.
FAQ
Can I use Puppeteer to take screenshots for clients?
Generally, the Puppeteer library can be used commercially under Apache-2.0, subject to its conditions. Also check the browser’s terms, the target website’s terms, and any applicable rules for the client’s use case.
Does Apache-2.0 mean every dependency is free for commercial use?
No. Check the license for each dependency and component you distribute or deploy, including the browser build.
Should I use puppeteer or puppeteer-core?
Use puppeteer when you want installation to download compatible Chrome. Use puppeteer-core when you will provide and manage the browser yourself. Review the official README for version-specific installation details.
Does Puppeteer’s license authorize automated access to any site?
No. The software license does not grant permission from a website. Check the site’s terms and use the automation responsibly.


