BrowserCat API Examples in Python for Capturing Website Screenshots
Connect Playwright to BrowserCat’s cloud browser from Python, capture viewport or full-page screenshots, and troubleshoot common issues.
Use Playwright’s async Python API to connect to BrowserCat’s cloud Chromium browser, navigate to a URL, and save a screenshot with page.screenshot(). The BrowserCat connection endpoint is wss://api.browsercat.com/connect; authenticate with the Api-Key header. Set full_page=True for a full-page image, or omit it to capture the current viewport.
1. Install Playwright and set your API key
BrowserCat’s [Playwright guide](https://www.browsercat.com/docs/connect-with/playwright) documents the Python connection. Install the Playwright package:
python -m pip install playwright
Get a BrowserCat API key from your BrowserCat account, then put it in an environment variable. Do not commit the key to source control.
export BROWSERCAT_API_KEY="your_api_key"
On PowerShell:
$env:BROWSERCAT_API_KEY="your_api_key"
2. Capture a website screenshot with Python
This complete async example connects to the hosted browser, navigates to a page, waits for the document load event, and writes a full-page PNG. It uses Playwright’s Python equivalent of the screenshot operation shown in BrowserCat’s [Quick Start](https://www.browsercat.com/docs/quick-start). BrowserCat’s Python guide demonstrates connecting and reading page information; the screenshot call below is Playwright’s documented page screenshot API.
import asyncio
import os
from pathlib import Path
from playwright.async_api import async_playwright
async def main() -> None:
api_key = os.environ.get("BROWSERCAT_API_KEY")
if not api_key:
raise RuntimeError("Set BROWSERCAT_API_KEY before running this script")
async with async_playwright() as p:
browser = await p.chromium.connect(
"wss://api.browsercat.com/connect",
headers={"Api-Key": api_key},
)
try:
page = await browser.new_page(viewport={"width": 1440, "height": 900})
response = await page.goto(
"https://example.com",
wait_until="load",
timeout=60_000,
)
if response is not None and response.status >= 400:
raise RuntimeError(f"Page returned HTTP {response.status}")
await page.screenshot(
path="screenshot.png",
full_page=True,
type="png",
)
print(f"Saved {Path('screenshot.png').resolve()}")
finally:
await browser.close()
if __name__ == "__main__":
asyncio.run(main())
Save it as capture.py and run python capture.py. The browser is closed in a finally block even if navigation or capture raises an exception. In BrowserCat’s Python sample, the imported Playwright object is bound to p; use p.chromium.connect consistently.
3. Choose what the screenshot waits for
The right navigation wait depends on the site. A load event waits for page resources that participate in the load event. It does not guarantee that data fetched afterward, animations, or lazy-loaded images are finished.
wait_until="domcontentloaded": use when the initial HTML is enough and you will wait for a specific element afterward.wait_until="load": a practical default for ordinary pages.wait_until="networkidle": consider for pages that settle after network activity, but some analytics, polling, or streaming pages never become idle.
For a known page element, wait for it explicitly after navigation:
await page.goto("https://example.com", wait_until="domcontentloaded")
await page.locator("main article").wait_for(state="visible", timeout=20_000)
await page.screenshot(path="article.png", full_page=True)
Use a selector that means the content you need is ready. A fixed delay can help with a known delayed transition, but it is less reliable than waiting for a selector:
await page.wait_for_timeout(1_000)
4. Screenshot options and page setup
Playwright’s Python page.screenshot() supports these commonly useful options. Check the [Playwright Python screenshot API](https://playwright.dev/python/docs/api/class-page#page-screenshot) for the installed release’s full option set.
| Option | What it does | Example |
|---|---|---|
path |
Writes the image to a file; the extension can determine the format. | path="shot.png" |
full_page |
Captures the full scrollable page, not just the viewport. | full_page=True |
type |
Selects png or jpeg. |
type="jpeg" |
quality |
Sets JPEG quality from 0 to 100; applies to JPEG, not PNG. | quality=80 |
omit_background |
For supported formats, makes the default background transparent. | omit_background=True |
animations |
Controls CSS animations and transitions during capture. | animations="disabled" |
caret |
Controls whether a blinking text caret is visible. | caret="hide" |
scale |
Uses CSS-pixel or device-pixel dimensions. | scale="css" |
clip |
Captures a specified rectangle instead of the whole viewport. | clip={"x": 0, "y": 0, "width": 800, "height": 600} |
style |
Applies CSS for the duration of capture in supported Playwright versions. | style="* { animation: none !important; }" |
Viewport size is configured when creating a page or browser context, not as a screenshot argument. Set it before navigation so responsive layouts render at the intended dimensions:
page = await browser.new_page(viewport={"width": 1280, "height": 800}, device_scale_factor=1)
A viewport screenshot is the default:
await page.screenshot(path="viewport.png")
For a JPEG with a chosen quality:
await page.screenshot(path="page.jpg", type="jpeg", quality=85, full_page=True)
Full-page screenshots can be large, and extremely long pages can exceed practical image dimensions or memory limits. If only one region is needed, use clip or scroll and capture sections. For PDFs, use Playwright’s page.pdf() in Chromium rather than screenshotting a long page into one image.
5. BrowserCat connection configuration
The minimal connection uses the documented WebSocket URL and API key header. BrowserCat also documents configuration through query parameters and a BrowserCat-Opts JSON header; its configuration guide says header keys take precedence over query parameters. Use the documented names and values for the option you need, and keep credentials on secure wss/https connections.
BrowserCat’s configuration documentation also describes proxy and browser launch settings. The current overview says Chromium and Chrome are available, with Firefox and WebKit listed on the roadmap, and explicit region routing listed on the roadmap. These service details can change, so check the [current configuration overview](https://www.browsercat.com/docs/browser-config/overview) before depending on a particular browser or routing option.
Do not put the API key in a URL query string where it can be recorded in logs or monitoring. If a deployment system injects secrets, read the environment variable at runtime and avoid printing connection headers or credentials in exception logs.
6. cURL, Python, and Node.js examples
The BrowserCat session is a browser automation connection, so the actual screenshot action requires a browser client such as Playwright. cURL can check that the BrowserCat site is reachable, but it cannot perform a Playwright screenshot through the WebSocket endpoint by itself.
For a direct screenshot API call that returns an image in one HTTP request, ScreenshotNeo is an option; its API documentation lists the supported screenshot parameters.
cURL with ScreenshotNeo
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
Python with ScreenshotNeo
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js with ScreenshotNeo
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 import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));
7. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| Authentication or connection rejected | Missing, invalid, or incorrectly named API key header. | Confirm BROWSERCAT_API_KEY is set and pass it as headers={"Api-Key": api_key}. Do not include the word Bearer unless the current BrowserCat docs specifically require it. |
| WebSocket connection fails | Wrong endpoint, blocked outbound WebSocket traffic, or an intermediary terminating the connection. | Use wss://api.browsercat.com/connect, check network egress and proxy rules, and retain TLS. |
| Variable name error at connect | Using pw.chromium.connect when the context was assigned to p. |
Call p.chromium.connect or consistently rename the context variable. |
| Navigation times out | Slow site, never-ending requests, or an overly strict wait condition. | Raise the navigation timeout where appropriate, use domcontentloaded, and wait for the specific content selector. Avoid treating network idle as universal. |
| Screenshot is blank or incomplete | Capture happened before client-rendered content appeared, or the site requires interaction. | Wait for a visible content selector, complete any required navigation or consent step allowed for your use, then capture. |
| Full-page image is unexpectedly tall or clipped | Page layout changes while scrolling, lazy content was not loaded, or the page exceeds image limits. | Wait for content, inspect the page dimensions, and capture a viewport or smaller clipped regions for very long pages. |
| File is empty or missing | Capture raised before it completed, the path is not writable, or code inspected the file too early. | Await page.screenshot, verify the destination directory permissions, and catch the original exception. |
| Local Python hangs at shutdown | The browser connection was not closed after an error. | Keep await browser.close() in finally and ensure the Playwright context exits. |
8. Performance, reliability, and cost
Cloud browser capture adds a remote connection and transfers the resulting image over the network. The actual time depends on the target page, chosen wait condition, image size, and service/network conditions; BrowserCat’s documentation does not establish a universal screenshot speed or success rate. For a fair comparison, measure your own target pages and workload.
Use bounded timeouts, close each browser session, and retry only transient errors. A retry should use a limit and backoff, since repeating a slow page request immediately can amplify load. If screenshots are part of a job queue, record the target URL, capture settings, duration, and error category without logging secrets.
Local Playwright runs the browser in your own environment; BrowserCat provides a managed cloud browser connection that can reduce the need to host browser infrastructure. BrowserCat recommends local development until automation becomes a bottleneck. Compare the infrastructure and service costs for your workload instead of assuming that hosted capture is faster or cheaper.
Or skip the browser setup
ScreenshotNeo takes a website URL in one GET request and returns PNG, JPEG, WebP, or PDF. Its API supports full-page captures, viewport and device settings, waits, custom CSS and JavaScript, cookies and headers, caching, bulk calls, async jobs, and other capture options; 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
ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture. 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 screenshots. Learn about ScreenshotNeo, then sign up for 1,000 free screenshots a month with no card.
FAQ
Can I capture only the visible browser area?
Yes. Call page.screenshot(path="viewport.png") and leave full_page unset or set it to False.
Does BrowserCat’s Python documentation show the screenshot line?
The Python connection guide demonstrates Playwright connectivity and page access. BrowserCat’s Quick Start shows the screenshot operation in JavaScript; the Python snippet here uses Playwright’s equivalent async page.screenshot() method.
Should I use BrowserCat or run Playwright locally?
Use local Playwright while it meets your development and deployment needs. Consider a hosted browser when managing browser infrastructure becomes a bottleneck; compare the operational requirements and costs for your use case.
Can this Python example capture PDF?
For Chromium, use Playwright’s await page.pdf(path="page.pdf") after navigation. PDF generation has its own page size, margins, and print styling options; it is separate from a raster screenshot.


