ScreenshotNeo

BlogGuides

Can a Screenshot API Capture Pages Rendered by a React App?

Yes. A screenshot API can capture a React page when it runs the page in a JavaScript-capable browser and waits for the content you need.

By the ScreenshotNeo team4 October 20268 min read

Yes. A screenshot API can capture a page rendered by React if its renderer opens the URL in a browser that runs JavaScript. To get the intended image, capture after the relevant React content is ready. A page-load event alone may happen before asynchronous data, images, or other late updates finish.

The practical test is simple: choose a browser-rendering API, point it at the fully qualified page URL, set the desired viewport, and wait for a page-specific element that appears when the content you need is ready. If the service offers a bounded delay, it can cover small follow-up updates. Verify the resulting image against the state you expected.

Why React pages need a browser-rendering screenshot API

A React page can arrive as an HTML document and then be updated by JavaScript in the browser. Saving only the initial HTTP response does not guarantee a screenshot of the final interface. A browser-rendering API loads the page and runs its scripts before capturing; the exact behavior varies by service, so check its documentation.

React can also be used with server rendering. In that case, some content may already be present in the initial HTML, while browser-side code may still update the page afterward. The capture should target the state your use case needs: for example, the initial rendered view, a loaded dashboard, or a result after an interaction.

How to capture a React page reliably

  1. Use the full page URL. Include the scheme, such as https://, and any route or query parameters needed to reach the right view.
  2. Set the viewport. Choose width and height to match the layout you want to represent. Responsive React layouts can change substantially between desktop and mobile widths.
  3. Wait for a meaningful selector. Pick an element that appears only after the specific data or component you need is ready. This is usually more precise than relying on a generic load event.
  4. Add a bounded delay only if needed. A short delay can allow small follow-up animations or updates to settle after the selector appears. It is not proof that every asynchronous task has completed.
  5. Use network-idle selectively. It may help when a page makes a finite set of requests, but polling or long-lived connections can prevent the page from becoming idle.
  6. Check the output. Confirm the intended content, viewport, image dimensions, and output format. An authentication page, bot check, application error, or missing selector may produce an image that is valid but not useful.

Full-page capture and lazy-loaded content need extra care. Some APIs offer scrolling before capture to trigger lazy loading; confirm the service’s behavior and check the resulting image for missing sections.

Choose the readiness condition

Condition Useful when Watch for
Page load You need a basic initial page state. React data fetching and later updates may still be in progress.
Selector appears A particular component indicates the desired content is ready. The selector might appear before its data or animation is finished. Choose a selector tied to the state you need.
Selector becomes visible The element exists in the DOM but visibility matters. Visibility semantics differ between services; check the endpoint documentation.
Network idle Requests settle after navigation. Polling, analytics, streaming, and long-lived connections can keep a page active.
Fixed delay A small, predictable amount of work remains after another readiness signal. Too short captures too early; too long wastes time. Delay limits vary by API and endpoint.

ScreenshotAPI documents selector waits, delay, full-page capture, and scrolling options; Cloudflare’s browser rendering documentation describes selector waits and related capture controls. These examples show the kinds of controls available, not that every API has identical behavior or limits. Check the current documentation for the specific endpoint you use: documented delay ranges can differ across endpoints and change over time.

DIY example with Playwright

If you operate the browser yourself, Playwright can navigate to a React page, wait for a page-specific element, and save a screenshot. This runnable Node.js example uses Playwright’s Chromium browser. Replace the URL and selector with values from your own application.

npm install playwright
npx playwright install chromium
// capture.mjs
import { chromium } from 'playwright';

const url = process.env.TARGET_URL ?? 'https://example.com/dashboard';
const readySelector = process.env.READY_SELECTOR ?? '[data-testid="dashboard-ready"]';

const browser = await chromium.launch({ headless: true });
try {
  const page = await browser.newPage({
    viewport: { width: 1440, height: 1000 },
    deviceScaleFactor: 1
  });

  await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30_000 });
  await page.locator(readySelector).waitFor({ state: 'visible', timeout: 20_000 });
  await page.screenshot({ path: 'react-page.png', fullPage: true });
} finally {
  await browser.close();
}

Run it with TARGET_URL and READY_SELECTOR set for your page, or use the example defaults:

node capture.mjs

The selector in this example is a placeholder, not a selector guaranteed to exist on a target site. Add a small explicit delay only if your application needs settling time after the ready element appears. For full-page shots, make sure content loaded only after scrolling is actually present; a full-page screenshot does not necessarily cause every site to load its lazy content.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its browser capture supports React pages, and its options include selector waits, delays, viewport controls, full-page capture, and more. See the ScreenshotNeo API documentation for parameters and examples.

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 Bun.write('shot.webp', res);

Replace https://stripe.com with your React app URL. The examples use the documented API request shape; add the relevant capture parameters from the docs for your required selector, viewport, or output.

  • Cookie banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
  • Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are never billed. Response headers identify the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
  • 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 plan to get 1,000 screenshots each month with no card.

Configuration choices that affect the image

When comparing or configuring screenshot APIs, check these capabilities and their exact endpoint-level names and limits:

  • JavaScript rendering: confirm the service renders in a browser that executes page scripts.
  • Readiness: selector waits, selector visibility, load events, network-idle, fixed delays, and request timeouts.
  • Page dimensions: viewport width and height, device emulation, device scale or retina output, and full-page capture.
  • Page actions: scrolling to trigger lazy content, clicking a control, or waiting for a specific state.
  • Authentication: cookies, custom headers, user agent, or authorization if the route requires access. Do not expose secrets in publicly visible URLs or logs.
  • Output: image format and quality, or PDF if the use case requires a document.
  • Content control: whether custom CSS, hidden selectors, or blocked resource types can remove elements or reduce unnecessary loading.
  • Failure behavior: timeout semantics, missing-selector errors, and whether the API returns a structured error or an image of the page’s failure state.

Do not assume support for a particular option from another vendor’s docs. Confirm it for the product and endpoint you are calling.

Performance, reliability, and cost

  • Use the narrowest reliable wait. A page-specific selector avoids waiting for unrelated background activity. Set finite timeouts so a broken route does not hold a worker indefinitely.
  • Keep the viewport and capture area appropriate. Very tall full-page captures and high device scale can increase image size and capture work. Use them when the content is needed.
  • Be deliberate about network-idle. Pages with polling or streaming may never reach it. Prefer an application-specific readiness signal when you control the app.
  • Make retries selective. Retry transient navigation or service failures with a limit and backoff. A missing selector caused by an application bug will not be fixed by repeated immediate requests.
  • Check the billing model. APIs differ in how they charge for failed captures, cache hits, or retries. ScreenshotNeo states that only clean shots are billed and identifies outcomes in response headers; its monthly plans range from 1,000 free shots to paid tiers.

Troubleshooting

Symptom Likely cause Fix
Screenshot shows a blank shell or loading spinner Capture occurred before React content was ready, or the app’s data request failed. Wait for a selector tied to the finished content; inspect the target page and its network-dependent state.
Selector wait times out The selector is wrong, only appears after an action, or the application never reached the expected state. Verify the selector in a normal browser, wait for the correct state, and check whether a click or login is required.
Image shows a login page or access denied The route needs authentication or the target blocks the rendering environment. Use supported cookies or authorization controls where appropriate, and check the target and API’s access rules. A screenshot API cannot guarantee access to every protected page.
Some images or sections are missing Lazy loading has not been triggered or image requests are still pending. Use a documented scroll-before-capture option if available, wait for the relevant images, or capture after the page has loaded the required sections.
Network-idle never completes Polling, analytics, streaming, or another persistent request keeps the page active. Switch to a selector wait or a bounded delay rather than requiring global network silence.
Layout differs from the browser you expected Viewport, device emulation, scale, fonts, or browser environment differ. Set the desired viewport and device settings; validate the returned image at those dimensions.
Capture request times out The page is slow, the wait condition is too strict, or the service timeout is too short. Check that the URL is reachable, use a page-specific readiness signal, and adjust the timeout within the endpoint’s documented limits.
The image is an application error or bot check The app returned an error state or the target presented an anti-bot challenge. Check the page verdict or error response if the API exposes one, and investigate whether the target permits automated access.

Frequently asked questions

Does React need to be server-rendered for an API screenshot?

No. A renderer that runs browser-side JavaScript can capture a client-rendered React page. It still needs to wait for the state you want.

Will every screenshot API capture every React app?

No. Browser behavior, authentication support, timeouts, and target-site restrictions vary. Test the exact endpoint against the intended route.

Is a fixed sleep enough?

Only when the page’s timing is predictable for your use case. A selector that represents the required content is generally a more targeted readiness signal.

Can I capture a page behind login?

Sometimes, if the service supports the needed authentication method and the site allows the request. Confirm those details for both the API and the target.

Sources