How to capture a Chromium screenshot with a transparent background
Capture Chromium screenshots with transparent pixels using CDP or Puppeteer, with viewport and full-page examples, troubleshooting, and format notes.
To capture a Chromium screenshot with transparent pixels, use the Chrome DevTools Protocol (CDP): set the default background override to RGBA alpha 0, then capture as PNG. Saving an ordinary screenshot as PNG alone does not make an opaque page background transparent.
First decide what you need: the current viewport, a clipped region, or the whole document. The examples below cover viewport and full-page capture. The transparent override affects the page’s default background; it does not erase background colors or images deliberately painted by the site.
1. Capture a transparent screenshot with CDP
CDP is Chromium’s browser debugging protocol. Send the commands to the page target in this order:
- Navigate to the page and wait until it is ready for your capture.
- Set a transparent default background override.
- Capture a PNG.
- Clear the override, especially if you will reuse the target.
For a viewport screenshot, the essential protocol calls are:
// Set the default page background to transparent.
await cdp.send('Emulation.setDefaultBackgroundColorOverride', {
color: { r: 0, g: 0, b: 0, a: 0 }
});
// Capture the current viewport as PNG.
const result = await cdp.send('Page.captureScreenshot', {
format: 'png',
fromSurface: true
});
// Clear the override before reusing this page target.
await cdp.send('Emulation.setDefaultBackgroundColorOverride', {});
Here, cdp means a CDP session attached to the page. The commands are protocol calls, not standalone JavaScript APIs available in an ordinary web page. The runnable Puppeteer example below creates and attaches that session.
Capture the whole document
For a full-page capture using CDP, set captureBeyondViewport: true and fromSurface: true, without a clip:
const result = await cdp.send('Page.captureScreenshot', {
format: 'png',
fromSurface: true,
captureBeyondViewport: true
});
With a surface capture and no clip, Chromium takes its beyond-viewport capture path. Full-page screenshots can consume substantially more memory than viewport captures on long or image-heavy pages. If you want only a region, use the protocol’s clip option and specify the rectangle you need; ensure the rectangle and scale match the content you intend to include.
2. Complete runnable example with Puppeteer
Puppeteer’s omitBackground option wraps the same transparent-background protocol behavior. It is the shortest practical approach when you already use Puppeteer.
// Save as transparent-shot.mjs
// Install with: npm install puppeteer
import puppeteer from 'puppeteer';
const url = process.argv[2] ?? 'https://example.com';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 1
});
await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000 });
await page.screenshot({
path: 'transparent.png',
type: 'png',
omitBackground: true
});
console.log('Saved transparent.png');
} finally {
await browser.close();
}
Run it with node transparent-shot.mjs https://example.com. To capture the full page, add fullPage: true to the screenshot options. Puppeteer resets the background override after its capture operation; if you issue CDP commands yourself, clear the override explicitly.
Puppeteer option choices
| Need | Setting | Notes |
|---|---|---|
| Transparent viewport PNG | omitBackground: true |
PNG is the simplest alpha-preserving choice. |
| Whole document | fullPage: true |
May be tall and memory intensive. |
| Specific element | page.locator('selector').screenshot(...) |
Element screenshots are clipped to that element; check the selected element’s own background. |
| Different viewport | page.setViewport(...) or viewport at page creation |
Responsive layout can change the result. |
| Higher pixel density | deviceScaleFactor |
Increases output dimensions and memory use. |
Use a current Puppeteer version and consult its screenshot options documentation for the API version you have installed.
3. Chrome Headless CLI: useful, but not enough by itself
Chrome’s official Headless command-line reference documents --screenshot to save screenshot.png and recommends --window-size to set the viewport. It also documents --timeout to bound the wait before capture. Those flags alone do not document a transparent-background switch, so do not assume that CLI PNG output has alpha transparency.
chrome --headless --no-sandbox \
--window-size=1440,900 \
--timeout=5000 \
--screenshot=screenshot.png \
https://example.com
For transparent output, use CDP or Puppeteer’s omitBackground. The Chromium headless shell source parses a --default-background-color value as eight hexadecimal digits (red, green, blue, alpha), but that is a shell-specific implementation detail. Confirm that the exact binary and version you run supports it before relying on that flag.
4. What transparency does and does not change
- The page’s default background: the zero-alpha override makes the default background transparent.
- Explicit CSS backgrounds: a body, root element, or component with a painted background color or image can still appear opaque. Remove or change that styling if you control the page and need it transparent.
- Overlays: cookie banners, dialogs, and other visible elements remain part of the screenshot unless your page or automation dismisses or hides them.
- Image format: JPEG has no alpha channel. Use PNG for the straightforward transparent result. CDP also lists WebP; verify alpha handling in the exact browser and downstream image tools if you choose it.
- Extent: viewport capture is the default. Full-page capture and clipping need their respective options.
Viewport, clip, and full page
| Capture | How | Watch for |
|---|---|---|
| Viewport | Call Page.captureScreenshot without a clip or beyond-viewport option. |
Content below the visible viewport is omitted. |
| Clip | Pass a CDP clip rectangle or capture an element with Puppeteer. |
Coordinates, scale, and element backgrounds affect the crop. |
| Full document | CDP: captureBeyondViewport: true, fromSurface: true, no clip. Puppeteer: fullPage: true. |
Very long pages can use considerable memory and take longer. |
5. Waiting for the page and handling dynamic content
Choose a readiness condition that matches the page. networkidle2 is convenient for many static pages, but analytics, streaming connections, polling, and other persistent requests can prevent network idle. Conversely, a page can reach network idle before delayed content or lazy-loaded images are ready.
- Wait for a meaningful selector when the required content has a stable element.
- Use a bounded delay only when the page has known delayed rendering and no better readiness signal.
- For lazy images on a long page, scroll through the document before full-page capture so the page has a chance to load them.
- Set explicit navigation and operation timeouts, and capture only after fonts and critical content are ready when visual completeness matters.
Be aware that scrolling or changing the viewport can trigger responsive layout changes and lazy loading. The page state at capture time determines the result.
6. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| PNG background is still white or colored | The override was not set, or the page paints an explicit background. | Set alpha to zero before capture. Inspect the root and body backgrounds; remove explicit paint if you control the page. |
| Image looks opaque in a viewer | The viewer displays transparency against a solid matte, or the image was converted to JPEG. | Inspect the PNG alpha channel or composite it over a checkerboard. Keep PNG through the pipeline. |
| Full page is cut off | Only the viewport was captured, or the page had not laid out its full content. | Use Puppeteer fullPage: true or CDP captureBeyondViewport: true with fromSurface: true and no clip. Wait for content first. |
| Capture times out waiting for network idle | The page keeps requests open or continually sends traffic. | Wait for a specific selector or use another bounded readiness condition suited to the page. |
| Lazy images are missing | They load only when scrolled into view. | Scroll through the page before full-page capture and wait for image loading to finish. |
| Later screenshots unexpectedly have transparent backgrounds | The CDP override remained active on the reused target. | Send Emulation.setDefaultBackgroundColorOverride without a color after capturing, or restore the prior emulation state. |
| Behavior differs on Android | Chromium’s own transparent-capture tests flag Android-specific coverage limitations, including a semi-transparent viewport scrollbar issue. | Validate the precise Chromium build and platform used in production; use a supported desktop Chromium environment if consistent output is required. |
7. Performance, reliability, and cost
Local Chromium capture has no per-request screenshot API charge, but it uses your compute, memory, browser maintenance, and operational time. Full-page images, large device scale factors, and concurrent browser sessions raise resource use. Keep a browser process warm for repeated jobs if startup latency matters, while isolating page state and reliably closing pages and browsers.
For repeatable output, pin a Chromium/Puppeteer version, set the viewport and device scale explicitly, use a deliberate readiness condition, and clear CDP overrides between captures. Validate transparency on the actual platform and image-processing path. The official Chromium test source includes transparent cases for viewport and beyond-viewport output, while noting Android-specific caveats.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its API returns an image or PDF from one GET request; its MCP tools let Claude, Cursor, and other MCP clients take screenshots. It can set a transparent background and supports PNG, JPEG, and WebP output. See the ScreenshotNeo API documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-d format=png \
-d transparent=true \
-o shot.png
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={
"access_key": "YOUR_API_KEY",
"url": "https://stripe.com",
"format": "png",
"transparent": "true",
},
timeout=90,
)
r.raise_for_status()
open("shot.png", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com',
format: 'png',
transparent: 'true'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(({ writeFile }) =>
writeFile('shot.png', Buffer.from(await res.arrayBuffer()))
);
ScreenshotNeo removes cookie banners, popups, and chat widgets 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. Transparent output changes the default background; explicit backgrounds painted by a site may still be visible.
Sign up for 1,000 free screenshots a month, with no card required.
FAQ
Does PNG automatically make a Chromium screenshot transparent?
No. PNG can store alpha, but Chromium needs a transparent background override or an equivalent wrapper option such as Puppeteer’s omitBackground.
Can I use JPEG for a transparent screenshot?
No. JPEG does not support an alpha channel. Use PNG, or validate a WebP workflow if you need that format.
Will the override remove a colored background from the website?
It overrides the default background. CSS backgrounds that the page explicitly paints can remain visible.
Should I clear the override?
Yes when reusing a page target. Omitting the color in Emulation.setDefaultBackgroundColorOverride clears the active override.


