Recommended Free Tools
Use Puppeteer’s Page.screenshot() after navigating to the page, and run the script in a container with Chrome’s dependencies, a writable output mount, and the sandbox configuration its image expects. Puppeteer’s supplied Docker image includes Chrome for Testing and its required dependencies; its documented run setup uses Docker’s --init and SYS_ADMIN. The examples below show a full-page PNG capture and how to handle readiness, permissions, and common launch failures.
Capture a webpage screenshot with Puppeteer in Docker
The capture sequence is: launch Puppeteer, open a page, navigate to the target URL, save the screenshot, and close the browser even if a step fails. This CommonJS script writes a full-page PNG to /output/page.png:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({ path: '/output/page.png', fullPage: true });
} finally {
await browser.close();
}
})();
The Puppeteer screenshot guide demonstrates networkidle2 as a navigation condition, not as proof that every page’s images, animations, or application data have finished rendering. For pages with a known ready state, wait for a page-specific selector as described below. Puppeteer screenshot guide
Run the script in Puppeteer’s Docker image
Puppeteer’s Docker image includes Chrome for Testing, its required dependencies, and a preinstalled Puppeteer version. The documentation says the image is intended to run Chrome sandboxed and requires SYS_ADMIN; its documented invocation also uses --init to manage browser child processes. Puppeteer Docker guide
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errors#1 Best Overall
-
Save the script as
screenshot.jsin a directory containing anoutputsubdirectory. The output directory must be writable by the container user. -
From that directory, run the image and mount the host output folder:
docker run --init --cap-add=SYS_ADMIN --rm -v "$PWD/output:/output" ghcr.io/puppeteer/puppeteer:latest node /app/screenshot.js -
Adapt
node /app/screenshot.jsto the actual script path in your image. The image tag shown islatest, which can change; for repeatable builds, pin a tag matching the Puppeteer release you intend to use. Check the current Docker guide for available tags and instructions because it is labeled “Next.”Rank #2
When the container exits successfully, the screenshot should be available at output/page.png on the host. A container path such as /output/page.png is not automatically visible outside Docker; it must be in a mounted directory.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Choose what to capture and when
Viewport or full page
By default, a page screenshot captures the current viewport. Set fullPage: true to capture the full document, as in the example. Full-page capture can produce a much taller image than the viewport, so use it only when the whole document is the intended output.
Wait for the page’s actual ready state
Navigation lifecycle events are useful starting points, but sites can continue rendering after navigation. If a specific element indicates that the content you need is ready, wait for it explicitly:
Rank #3
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('[data-screenshot-ready]');
await page.screenshot({ path: '/output/page.png', fullPage: true });
Replace the selector with one that exists on the target page and appears only when the relevant content is available. Puppeteer’s screenshot guide uses networkidle2 as an example; pages with persistent network activity may not reach network idle, while a quiet network does not necessarily mean a client-rendered component is ready. Puppeteer screenshot guide
Capture one element
For a card, chart, or other component, locate it and use its element screenshot method rather than capturing the whole page:
const element = await page.waitForSelector('.report-card');
await element.screenshot({ path: '/output/report-card.png' });
Puppeteer’s ElementHandle.screenshot() scrolls a hidden element into view by default. Puppeteer screenshot guide
Build a custom Docker image
If the supplied image does not fit your deployment, base the image on Puppeteer’s Docker setup or install the shared libraries required by the Chrome build in your chosen Linux environment. Puppeteer normally downloads a compatible Chrome for Testing browser during installation. If a package manager blocks install scripts, the browser may not be present; allow the Puppeteer install script or install the browser explicitly with npx puppeteer browsers install. Use puppeteer-core when you manage the browser separately, and configure an explicit executable path or channel. Puppeteer troubleshooting Puppeteer installation guide
Give the runtime user ownership of the screenshot output directory and writable browser state directories. In read-only container environments, configure writable locations for browser cache, configuration, and user data; otherwise Chrome may fail while creating its profile or crashpad files. The installation guide estimates the Linux Chrome for Testing download at approximately 282 MB; that is an installation download estimate, not a runtime memory requirement. Puppeteer installation guide Puppeteer troubleshooting
Keep Chrome’s sandbox enabled where possible
Prefer the sandbox configuration expected by the selected image, including its documented SYS_ADMIN capability. Puppeteer’s troubleshooting guidance discusses --no-sandbox only for cases where page content is trusted and explicitly discourages treating it as a general configuration. A screenshot worker that visits arbitrary URLs is processing untrusted content; do not disable the sandbox without assessing the security implications. Puppeteer Docker guide Puppeteer troubleshooting
Best Value
- Docker, Docker Swarm, Docker Compose, Programmer, Developer, Coding, Programming, Software Engineer, Code, DevOps, Deploy, Deployment, Kubernetes, Salt, Puppet, Chef, Terraform, Container, AWS, Azure, Cloud, Geek, Funny, Computer, Software, Tech, IT
- Integration, Scrum, Compile, Compilation, Science, Bug, Debug, Python, Linux, Java, Javascript, Scala, Dotnet, Kotlin
- Lightweight, Classic fit, Double-needle sleeve and bottom hem
Troubleshoot common Docker failures
| Symptom | Likely cause | What to check or change |
|---|---|---|
| Chrome fails to launch because a shared library is missing | The custom image lacks a Linux dependency required by that Chrome build. | Install the libraries required by the selected browser and base image, following Puppeteer’s troubleshooting guidance. |
| “Could not find Chrome” | The package manager may have blocked Puppeteer’s postinstall browser download. | Permit the Puppeteer install script or run npx puppeteer browsers install. |
| Read-only filesystem, profile, or crashpad startup error | Chrome cannot write its browser state or user profile. | Provide writable cache and configuration paths, set userDataDir to a writable directory, or mount writable browser directories owned by the runtime user. |
| Chrome sandbox error | The container may not provide the sandbox setup expected by the selected image. | Check the image’s sandbox requirements and container capabilities before changing browser flags. Avoid defaulting to --no-sandbox. |
| Zombie Chrome processes after a run | Child processes are not being reaped by the container’s process setup. | Use Docker’s --init option or an appropriate init entrypoint. |
| Chrome does not run on Alpine | Chrome does not work on Alpine out of the box; compatibility depends on system dependencies and browser versions. | Validate the exact current browser and image combination, or choose a supported Linux environment. Do not rely on a historical version-specific workaround without checking it. |
For version-specific launch and dependency details, consult Puppeteer’s troubleshooting guide.
Or skip the browser setup
If you need an API instead of maintaining a browser container, ScreenshotNeo captures a URL in one request. Cookie banners and consent notices, newsletter popups, and chat widgets are removed before the shot; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed. Its MCP server provides screenshot tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots.
Example request (replace the target URL as needed):
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 request options and response details. Sign up for ScreenshotNeo’s free plan.
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.

