Take Website Screenshots with Pyppeteer in Python
Capture a website with Pyppeteer, save a viewport or full-page screenshot, and configure formats, readiness, and Chromium without common setup errors.
Use Pyppeteer’s asynchronous API to launch Chromium, open a page, navigate to a URL, and save a screenshot. The default capture shows the current viewport; set fullPage: true to capture the full scrollable page. Pyppeteer is an unofficial Python port of Puppeteer, and its project currently describes it as unmaintained, so consider Playwright Python when starting a new browser automation project.
1. Install Pyppeteer and Chromium
Pyppeteer requires Python 3.8 or later. Install it with pip:
python -m pip install pyppeteer
On first use, Pyppeteer downloads its bundled Chromium if it is not already available. The project README estimates this download at about 150 MB. To download it ahead of time, run:
pyppeteer-install
You can also configure a suitable Chrome or Chromium binary explicitly, but Pyppeteer works best with its bundled Chromium and does not guarantee compatibility with other Chrome versions.
2. Capture a website screenshot
This complete script saves a PNG from the example URL. Include the URL scheme, such as https://. Close the browser after the capture so the Chromium process does not linger.
import asyncio
from pyppeteer import launch
async def main():
browser = await launch()
try:
page = await browser.newPage()
await page.goto("https://example.com")
await page.screenshot({"path": "screenshot.png"})
finally:
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
Save it as screenshot.py and run python screenshot.py. The flow is asynchronous: launch, create a page, navigate, capture, close. The try/finally ensures the browser is closed even if navigation or capture fails.
3. Choose what to capture
Viewport or full page
Without additional options, a screenshot captures the visible viewport. To capture the full scrollable document, pass fullPage: true:
await page.screenshot({"path": "full-page.png", "fullPage": True})
Full-page screenshots can be much taller and larger than viewport captures. Pages that load images or other content while scrolling may need additional readiness handling; see the next section.
A clipped rectangle
Use clip when you need a rectangular region of the page. Coordinates and dimensions are in CSS pixels:
await page.screenshot({
"path": "region.png",
"clip": {"x": 0, "y": 0, "width": 800, "height": 500}
})
A clip must describe a valid region for the page. If it falls outside the rendered content or has unsuitable dimensions, adjust the coordinates and size. The Pyppeteer API documents clipping rectangles; it does not provide the Playwright element-screenshot call shape.
PNG, JPEG, and transparency
PNG is the default. Select JPEG and set its quality from 0 to 100 when smaller lossy output is acceptable:
await page.screenshot({
"path": "page.jpg",
"type": "jpeg",
"quality": 80
})
JPEG quality applies to JPEG output, not PNG. To omit the browser’s default white background and allow transparency in a supported output, use omitBackground:
await page.screenshot({
"path": "transparent.png",
"omitBackground": True
})
Pyppeteer uses the option names fullPage and omitBackground. Do not substitute Playwright’s Python spelling full_page in a Pyppeteer script.
Save to a file or use the returned data
Set path to write the image to disk. Pyppeteer also supports binary or base64 screenshot output when you need to keep the result in memory or pass it elsewhere; omit path and use the API’s encoding option as appropriate. Consult the Pyppeteer screenshot API reference for the documented return and encoding details.
4. Wait for the page to be ready
page.goto() requires a URL with its scheme. Its documented default navigation timeout is 30 seconds, and its default waitUntil condition is load. A page can still update after that event, for example when an application renders content asynchronously. In that case, wait for a meaningful selector before capturing:
await page.goto(
"https://example.com",
{"waitUntil": "networkidle0", "timeout": 60000}
)
await page.waitForSelector("main article")
await page.screenshot({"path": "article.png", "fullPage": True})
Choose the readiness condition based on the site. Waiting for network idle can be inappropriate for pages with continuous network activity; waiting for a selector is often more directly tied to the content you need. A fixed sleep is not a universal readiness solution.
For pages that lazy-load images as they enter the viewport, a full-page setting alone may not guarantee every image has loaded. If missing images matter, use a page-specific readiness condition or scroll through the page and wait for its images before capture.
5. Configure Chromium for your environment
For ordinary local use, launch() uses Pyppeteer’s bundled Chromium. If you need to choose a browser binary, pass its path with executablePath:
browser = await launch({"executablePath": "/path/to/chrome"})
The actual path depends on your operating system and installation. A system Chrome version that differs from the version Pyppeteer expects can cause launch or protocol errors; the project does not guarantee compatibility with other Chrome versions. Prefer the bundled Chromium when possible.
In a container or restricted environment, Chromium may also need launch arguments or system libraries provided by that environment. Configure those based on the error and the container’s security requirements rather than copying broad flags blindly.
6. Troubleshoot common failures
| Problem | Likely cause | What to do |
|---|---|---|
| Chromium download fails or is unexpectedly slow | First use needs to download the browser, approximately 150 MB according to the project README. | Run pyppeteer-install during setup, check network access and available disk space, or configure a suitable browser binary. |
| Browser fails to launch | The browser binary is missing, incompatible, or cannot start in the current environment. | Use the bundled Chromium first. If selecting a system browser, verify executablePath and compatibility; check that the environment has the dependencies Chromium requires. |
| Navigation reports an invalid URL | The URL lacks a scheme. | Use a full URL such as https://example.com, not just example.com. |
| Navigation times out | The page did not reach the requested readiness event before the timeout, or the site is slow or continuously active. | Check the URL and network access. Increase the timeout when justified, or choose a readiness condition suited to the page and wait for the required selector. |
| Screenshot misses content that appears later | The capture happened after navigation completed but before the relevant client-side content appeared. | Wait for a page-specific selector or condition before calling screenshot(). |
| Full-page screenshot has missing lazy images | Images may load only after scrolling or another page-specific trigger. | Scroll through the page and wait for the relevant images or content before capture. |
full_page or another option appears to do nothing |
That spelling may belong to a different library. Pyppeteer uses camelCase for options such as fullPage. |
Use the Pyppeteer option names and verify the installed library and its API reference. |
| Browser process remains after an error | The script exited before reaching browser.close(). |
Put browser cleanup in a finally block, as in the runnable example. |
7. Performance, reliability, and maintenance
- Browser startup: Launching Chromium has setup and process-start costs. For repeated captures in one process, reuse a browser where appropriate and close it cleanly when the work ends.
- Capture size: Full-page output can consume more memory and disk than a viewport capture. Choose JPEG with an appropriate quality when lossy output is acceptable; retain PNG when lossless output or transparency is needed.
- Readiness: Waiting for the right page condition improves consistency. A long fixed delay wastes time on fast pages and can still be too short on slow ones.
- Compatibility: Pyppeteer works best with its bundled Chromium; using another Chrome build adds version-compatibility risk.
- Maintenance: The Pyppeteer project README labels the repository unmaintained and recommends considering Playwright Python. This is relevant when choosing a library for new work.
Playwright’s official Python screenshot guide covers ordinary screenshots, full-page captures, buffers, and element screenshots. Evaluate it for new automation projects, while accounting for its different API and setup rather than assuming Pyppeteer code will transfer unchanged: Playwright Python screenshot documentation.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request takes a URL and returns an image or PDF. Its clean-shot flow accepts cookie and consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture.
See the ScreenshotNeo API documentation for parameters and options.
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', new Uint8Array(await res.arrayBuffer()));
Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card required.
FAQ
Does Pyppeteer capture a full page by default?
No. The default is the current viewport. Set fullPage: true for the full scrollable page.
Can Pyppeteer save screenshots as JPEG?
Yes. Set type to jpeg; the optional quality setting controls JPEG quality.
Is Pyppeteer maintained?
The project README currently labels it unmaintained and suggests considering Playwright Python. Pyppeteer remains the subject of this guide, but that status is worth weighing for new projects.


