ScreenshotNeo

BlogHow-to

How to Capture a Website Screenshot After It Finishes Loading with BrowserCat

Connect Playwright to BrowserCat, wait for the page condition that matters, and capture a screenshot without relying on a fixed delay.

By the ScreenshotNeo team4 October 20268 min read

To capture a website after it finishes loading with BrowserCat, connect Playwright to BrowserCat’s hosted Chromium browser, navigate to the URL, wait for the readiness signal that matches the page, and then call page.screenshot(). For a normal document navigation, a load-state wait may be enough. For a JavaScript-heavy page, wait for a meaningful content element to become visible; use network idle when network activity settling is an appropriate signal.

BrowserCat documents Playwright connections to wss://api.browsercat.com/connect using an API key in the connection headers. Its quick start demonstrates navigating, waiting for a load state, and taking a screenshot. See the BrowserCat quick start and BrowserCat Playwright guide for the provider-specific connection pattern.

1. Connect to BrowserCat and capture after a load state

Install Playwright, set your BrowserCat API key in the environment, and run this JavaScript module. The flow follows BrowserCat’s documented endpoint and API-key header. The screenshot uses Playwright’s fullPage option to capture the full page; remove that option if you only need the viewport.

npm install playwright

# Set BROWSERCAT_API_KEY in your shell before running this script.
import * as pw from 'playwright';

const browser = await pw.chromium.connect('wss://api.browsercat.com/connect', {
  headers: { 'Api-Key': process.env.BROWSERCAT_API_KEY },
});

try {
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.waitForLoadState();
  await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
  await browser.close();
}

Save it as capture.mjs and run node capture.mjs. Make sure BROWSERCAT_API_KEY is set; do not put a real key into source code that may be committed. BrowserCat’s examples run sessions on Chromium in new headless mode.

Wait after an action

If a click triggers a document navigation, wait for the resulting load state before capturing. BrowserCat’s quick start uses this sequence after clicking a Pricing link:

await page.getByRole('link', { name: 'Pricing' }).click();
await page.waitForLoadState();
await page.screenshot({ path: 'pricing.png' });

If the click updates a single-page app without navigating, a load-state wait may not represent the content change. Wait for the element or state that confirms the new content is visible.

2. Choose the readiness signal for the page

“Finished loading” can mean different things. A browser navigation event tells you about document loading; network idle observes traffic; a selector wait observes the actual content you need. Use the narrowest signal that matches the screenshot requirement.

Page behavior Useful wait Tradeoff
Ordinary navigation or a click that opens a new document page.waitForLoadState() Simple, but the page may still render client-side content afterward.
Known dynamic content Wait for a stable, meaningful selector to become visible Directly represents the content needed; the selector must exist and be stable.
Page content is ready after requests settle Wait for a network-idle condition Can be unsuitable when analytics, polling, streaming, or other persistent requests keep traffic active.

A document load event can happen before a single-page application finishes rendering its visible content. Cloudflare’s screenshot guidance separately recommends network-idle or a known selector for cases where a basic page-load wait can capture empty or incomplete content. That guidance is general browser screenshot advice; Cloudflare’s HTTP screenshot endpoint is a different interface from BrowserCat’s Playwright connection. See Cloudflare Browser Run screenshot documentation.

Wait for a meaningful selector

When the page has a stable element that appears only after the needed content is rendered, wait for it before capturing:

await page.goto('https://example.com');
await page.locator('[data-testid="main-content"]').waitFor({ state: 'visible' });
await page.screenshot({ path: 'page.png', fullPage: true });

Replace the example selector with one from the page you are capturing. A selector that matches a generic shell, hidden template, or unrelated element does not prove that the desired content is ready. If the selector is missing, hidden, or renamed, the wait will fail rather than silently confirming readiness.

Wait for network idle

BrowserCat’s Playwright guide demonstrates the network-idle wait state in its .NET example using WaitUntilState.NetworkIdle. Playwright also provides load-state waiting in its JavaScript workflow. Use the option supported by your Playwright language binding and version, and handle the possibility that a page’s background traffic prevents the condition from being reached. Network-idle is a signal about traffic, not a guarantee that every visual detail or delayed widget has rendered.

3. Capture a full page or a single element

Playwright’s page screenshot call is the core capture pattern. Use a page screenshot for the page or viewport, and a locator screenshot when the requirement is one element. BrowserCat’s MCP server also describes captures of a full page or selected CSS element, but its MCP tool inputs are not the same as Playwright’s API.

// Viewport screenshot
await page.screenshot({ path: 'viewport.png' });

// Full-page screenshot
await page.screenshot({ path: 'full-page.png', fullPage: true });

// Screenshot one element
await page.locator('main article').screenshot({ path: 'article.png' });

The examples use Playwright screenshot options. For full-page images, pages with very long content can produce large files and take longer to capture or transfer. If the output is blurry at unusually large dimensions, check the viewport and pixel density settings supported by the browser automation API in use; Cloudflare’s separate screenshot endpoint documents device scale factor as one factor in image clarity. Do not assume that Cloudflare endpoint parameters are BrowserCat parameters.

4. Handle timeouts and make the capture reliable

Set explicit navigation and readiness timeouts for the behavior of the site and job. There is no universal timeout that BrowserCat’s cited examples establish for every page. A useful production flow catches failures, logs which wait timed out, and closes the remote browser in a finally block, as in the first example.

  • Wait for the specific content that must appear, when a reliable selector exists.
  • Use network idle only when network settling is meaningful for that page.
  • Use a fixed delay only as a bounded fallback for a known delayed animation or widget; a delay does not prove readiness.
  • For repeated captures, keep the API key in a secret store or environment variable and make sure the browser is closed after success or failure.
  • Record the URL, chosen wait condition, and error when a job fails so you can distinguish navigation problems from readiness problems.

When a click starts navigation, waiting for a page load state after the click follows BrowserCat’s documented quick-start pattern. If it is an in-page action, identify a page-specific condition instead. For concurrent capture jobs, account for remote session limits and the cost model of the BrowserCat plan you use; the reviewed research does not establish a universal concurrency limit or price.

5. Troubleshooting

Symptom Likely cause Fix
Screenshot is blank or misses the main content The document load event fired before client-side rendering finished, or the wait targeted the wrong state. Wait for a selector representing the required content, or use an appropriate network-idle wait.
Network-idle wait times out Persistent requests, polling, streaming, or analytics keep network activity going. Prefer a meaningful selector when possible. Set a bounded timeout suited to the capture job.
Selector wait times out The selector is wrong, the element is not rendered on that route, or it remains hidden. Inspect the page structure and choose a stable element that becomes visible when the required content is ready.
Browser connection fails The remote endpoint, key, or connection setup is incorrect. Use wss://api.browsercat.com/connect, provide the Api-Key header, and confirm the environment variable is set.
Screenshot is blurry at large dimensions Viewport and pixel density may not suit the desired output. Check the device scale factor controls of the API or browser automation layer actually in use; do not copy Cloudflare endpoint parameters into BrowserCat code.
Screenshot occurs before a post-click update The action changed the app in place rather than navigating to a new document. Wait for the updated element or other state that confirms the new view is ready.

6. Performance, reliability, and cost

The readiness condition affects both completion time and failure behavior. A selector wait can finish as soon as the relevant content is ready, while a network-idle wait may take longer or time out on pages with continuous background traffic. These are consequences of what each wait observes; the cited sources establish no universal fastest or most reliable choice.

Keep captures within the time budget of the surrounding job, use explicit timeouts, and avoid capturing an unnecessarily long page if the task needs only a viewport or one element. Retry only failures that may be transient, and avoid unbounded retries for a broken selector or invalid credentials. BrowserCat usage cost and availability depend on its current plan and service terms; check its current documentation and account details before estimating production spend. No prices, uptime figures, or benchmark results are established by the research for this article.

Or skip the browser setup

ScreenshotNeo takes a URL in one GET request and returns an image or PDF. Cookie banners are accepted like a visitor and more than 60 known consent platforms, newsletter popups, and chat widgets can be removed before capture; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server lets AI agents use screenshot, page-info, and PDF tools.

See the ScreenshotNeo API docs for the request options. Example using the requested URL:

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()));

1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000. Learn about ScreenshotNeo or sign up for the free plan.

FAQ

Does BrowserCat use a local browser in this workflow?

No. The documented cloud workflow connects Playwright to BrowserCat’s hosted browser endpoint.

Is a fixed sleep the best way to wait?

No. A fixed sleep only waits for a duration; it does not confirm that the content needed for the screenshot is ready. Prefer a load state, selector, or network condition that matches the page.

Are BrowserCat and Cloudflare screenshot options interchangeable?

No. BrowserCat’s documented flow uses Playwright connected to its cloud browser. Cloudflare’s screenshot endpoint is a separate API with its own options.