ScreenshotNeo

BlogGuides

Can a Website Screenshot API Render Pages Using Client-Side Routing?

Yes—if the API runs JavaScript in a browser and waits for the routed view to finish rendering. Learn how to choose a readiness condition and diagnose blank or incomplete captures.

By the ScreenshotNeo team4 October 20268 min read

Yes. A website screenshot API can capture a client-side routed page when it opens the requested URL in a JavaScript-capable browser and waits until the application has rendered the view you need. If capture starts too early, the image may show an app shell, spinner, or incomplete content.

The key is the readiness condition. Prefer waiting for a page-specific element that appears only when the target view is ready. If there is no reliable element, try a supported network-idle condition, then use a bounded delay only when you can identify work that finishes after network activity settles. These settings vary by provider, and no wait setting guarantees every route will work.

For the managed option, ScreenshotNeo is a website screenshot API and MCP server. Its API renders URLs and supports waits for a selector, a delay, or network idle; see the ScreenshotNeo API documentation.

1. Why client-side routes need a readiness condition

In a single-page application, the browser can load the initial document before the router and application have finished producing the requested view. The app may then fetch data, hydrate components, update the route, load fonts or images, and run transitions. A navigation event such as “document loaded” does not necessarily mean that the useful page content is visible.

Cloudflare’s Browser Run documentation says its screenshot endpoint processes HTML and JavaScript, and warns that default page-load behavior on JavaScript-heavy pages or SPAs may return empty or incomplete results. It documents selector waits and network-idle navigation waits as options. The exact controls and semantics depend on the API you use. See Cloudflare’s screenshot endpoint guide and API reference.

2. A reliable capture workflow

  1. Use the exact deep link. Pass the route you want captured, not just the site homepage. Check that the renderer can reach that URL without a local session, VPN, or browser-only state.
  2. Choose the viewport. Set width and height to match the intended output. Responsive layouts, menus, and content can change at different sizes.
  3. Pick a readiness signal. If the page exposes a stable element such as [data-capture-ready="true"], wait for that selector. Coordinate with the application owner to expose a marker if you control the site.
  4. Try network idle when needed. It can be useful where data fetching is the last major step, but persistent polling, analytics, or long-lived requests can keep the page from becoming idle. Network quiet also does not prove that animations or application rendering have finished.
  5. Add a bounded delay only for a known late step. Use a short delay if fonts, hydration, or an animation visibly finishes after the chosen event. Large delays add latency and still do not guarantee readiness.
  6. Inspect the result. Confirm the target route, key content, and layout in the returned image. Adjust the readiness condition based on what the screenshot actually shows.

3. DIY example with Cloudflare Browser Run

This cURL example requests a URL screenshot and waits for network idle. Replace the account ID and token with your Cloudflare values. The endpoint and option names below are Cloudflare-specific, not a universal screenshot API format.

curl -X POST 'https://api.cloudflare.com/client/v4/accounts/ACCOUNT_ID/browser-run/screenshot' \
  -H 'Authorization: Bearer API_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://example.com/products/widget",
    "viewport": {"width": 1280, "height": 900},
    "gotoOptions": {"waitUntil": "networkidle0", "timeout": 45000},
    "screenshotOptions": {"fullPage": true}
  }' \
  --output route.png

Cloudflare documents navigation waits including load, domcontentloaded, networkidle0, and networkidle2 in its API reference. The screenshot endpoint guide shows viewport, full-page capture, cookies, and authentication options. Choose a supported wait mode and timeout from the provider’s current documentation; these are not shared standards.

4. Choosing a wait mode

Condition Use it when Watch for
Selector visible or present A stable element identifies the finished route, such as a page heading or ready marker. The selector may exist before its data is complete. Choose a marker whose meaning is explicit.
Network idle Relevant API requests usually finish before capture. Polling or analytics can prevent idle; network quiet does not prove animations or rendering logic are done.
Document load event The page is mostly server-rendered or JavaScript work is not required for the target content. It can be too early for an SPA route or data loaded after navigation.
Bounded delay A known late hydration, font, image, or motion step needs a little extra time. It is a timing guess. Longer waits raise latency and do not ensure the state is correct.

A selector wait is often the clearest contract because it names the state you need. Cloudflare describes selector waits as an alternative to waiting for all network activity to stop. ScreenshotAPI also documents a waitForSelector option; its documented post-load delay range is 0–20,000 ms, which applies to that provider only. See ScreenshotAPI’s parameter reference.

5. Route, authentication, and rendering edge cases

  • Direct navigation versus in-app navigation: Test the actual deep link directly. Some deployments serve the SPA fallback for client-side navigation but return a 404 when the same path is requested from a new browser session. The renderer starts with a fresh navigation.
  • Authentication: A route may redirect to a login page or render an access-denied screen without the right session. Check whether the provider supports cookies, HTTP Basic authentication, or authorization headers. Cloudflare documents these methods for its endpoint.
  • App state: A route may depend on local storage, a prior interaction, account data, or a feature flag. A screenshot request does not automatically reproduce a user’s existing browser state. Use supported session setup, or make the state addressable and reproducible.
  • Network access: The renderer must reach the page and its scripts, stylesheets, fonts, and data endpoints. A blocked third-party request can leave part of the view incomplete.
  • Animations and lazy content: Wait for a stable state or use a suitable delay when motion or scrolling triggers content. Full-page capture and lazy loading behavior differ by service.
  • Hash routes: A route such as /#/settings may be interpreted by the browser-side router after document load. Confirm the API passes the complete URL, including the fragment.
  • Responsive behavior: A route that works at desktop width may show a different navigation or content state on mobile. Capture using the viewport you intend to deliver.

6. Or skip the browser setup

ScreenshotNeo accepts a URL in one GET request and returns an image. Use its selector, network-idle, or delay options when the routed view needs extra time. See the API docs for the supported parameters.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.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())));
  • Cookie banners, popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed. Response headers say which page verdict and billing status applied.
  • An MCP server gives AI agents tools for screenshots, page information, and PDF capture.
  • 1,000 screenshots a month are free with no card. Paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo’s free 1,000 screenshots per month.

7. Troubleshooting blank or incomplete captures

What you see Likely cause What to check
App shell, spinner, or skeleton Capture happened before the routed view was ready. Wait for a page-specific ready selector. If unavailable, try a supported network-idle condition and inspect again.
Login page or access denied The route requires authentication, or the renderer lacks the expected session. Check redirects and provider support for session cookies, Basic authentication, or authorization headers.
Blank page or navigation error The URL may be unreachable, the server may not serve the deep link, or scripts/data requests may fail. Open the exact URL in a fresh browser session; check the route fallback, DNS/access restrictions, and required network resources.
Wait timed out The selector never appeared, or network activity did not become idle before the timeout. Verify the selector exists at that route and is spelled correctly. Check for polling or persistent requests; choose a more specific selector if appropriate.
Correct content, wrong layout The capture viewport differs from the intended device or responsive breakpoint. Set the viewport explicitly and retry.
Missing images or styles Resources did not load in the capture browser, or lazy loading was not triggered. Check resource accessibility and the provider’s full-page/lazy-loading behavior. Do not assume every API scrolls or loads content identically.
Route works only after clicking through the site The route depends on transient client state or navigation setup. Make the page state reproducible from a deep link or configure supported cookies/headers. A screenshot service cannot infer missing application state.

8. Performance, reliability, and cost

Every wait adds time to the capture. A selector tied to the actual content can avoid waiting for unrelated background traffic; network idle may be slower or time out on pages that keep connections open. A fixed delay trades predictability for wasted time on fast loads and possible early captures on slow ones.

For reliability, use a meaningful readiness marker, an explicit viewport, and a timeout suited to the route. Retry only transient failures and keep retries bounded; repeated captures of a consistently broken route will not repair its routing or authentication. Validate a sample of returned images because successful HTTP responses do not necessarily mean the expected application view was captured.

Cost depends on the provider’s plan and billing rules. Do not assume a wait mode, failed navigation, or cache hit is free across providers. ScreenshotNeo states that only clean shots are billed: bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, with the result indicated in response headers. Its plans are Free (1,000 per month), Starter ($5 for 3,000), Growth ($15 for 15,000), Pro ($39 for 60,000), Scale ($99 for 250,000), and Business ($249 for 1,000,000); yearly billing gives two months free, and every feature is on every plan.

9. Frequently asked questions

Does client-side routing require a special screenshot format?

No. The important capability is a JavaScript-enabled browser plus a wait condition that matches when the route is ready. The output format is a separate choice.

Can a screenshot API capture a route that is not linked from the homepage?

Usually, if the route is directly reachable and the server supports loading it as a fresh URL. Test the deep link itself; a route that only works after in-app navigation may depend on server fallback or application state.

Does network idle mean the screenshot is fully rendered?

No. It indicates a network condition. The application may still be rendering, animating, or waiting on work that is not represented by ongoing network requests.

Should I use a longer timeout to fix a blank screenshot?

Only if the page is progressing and needs more time. A timeout increase does not fix a bad route, missing authentication, blocked scripts, or an invalid readiness selector.

Will every screenshot API support the same wait options?

No. Check the chosen provider’s documentation for its wait modes, selector behavior, timeout limits, authentication support, and viewport controls.