ScreenshotNeo

BlogHow-to

How to Capture Screenshots of JavaScript-Rendered Pages with ScreenshotAPI.net

Capture JavaScript-rendered pages with ScreenshotAPI.net: choose a reliable wait strategy, capture the right page area, and troubleshoot missing content.

By the ScreenshotNeo team4 October 202610 min read

To capture a JavaScript-rendered page with ScreenshotAPI.net, send a GET request to https://screenshot-api.net/v1/screenshot with the target url, authenticate with an Authorization: Bearer header, and choose a readiness wait that matches the page. The endpoint returns image bytes. A fixed delay is the documented wait control in the reviewed v1 reference; selector and network-idle waits are described on the feature page, so check the documentation for the exact endpoint and parameter names before using them.

This distinction matters because a browser can finish navigating before a JavaScript app has fetched data, rendered a chart, or mounted a widget. A screenshot taken too early can be blank or incomplete even though the page eventually looks correct in a normal browser.

1. Make a basic authenticated request

Set your API key in an environment variable and download the response directly to a file. The example includes a two-second delay as a starting point; tune it to the target page rather than assuming every site is ready after the same interval.

export SCREENSHOT_API_KEY='YOUR_API_KEY'
curl -G 'https://screenshot-api.net/v1/screenshot' \
  -H "Authorization: Bearer $SCREENSHOT_API_KEY" \
  --data-urlencode 'url=https://example.com' \
  --data-urlencode 'delay=2000' \
  -o screenshot.png

The required parameter is url. The response body contains the image, with a content type matching the selected format. Keep the API key out of source control and public client-side code. ScreenshotAPI.net also accepts a ?key= query parameter for embedding a capture as an image, but its documentation warns that query keys can appear in page source or server logs. Use the bearer header for ordinary application requests.

See the ScreenshotAPI.net documentation for current endpoint details and available parameters. Use only parameter names supported by the version of the endpoint you call.

2. Choose when the screenshot should happen

There is no single wait strategy that fits every JavaScript page. Identify the event that means the particular content you need is ready, then choose the matching control.

Strategy Waits for Good fit Trade-off
Fixed delay An elapsed interval after load A page with predictable, short client-side rendering Too short misses content; too long adds time to every capture
Selector wait A chosen CSS element to appear A widget or result container that signals readiness Depends on a stable selector and on that element meaning the content is actually ready
Network idle Network activity to fall quiet Content loaded through a wave of asynchronous requests Long polling, analytics, or persistent connections may keep activity from becoming idle

The ScreenshotAPI.net v1 API reference reviewed for this guide documents delay from 0 to 10,000 milliseconds. Its feature page also describes waiting for a CSS selector or network activity to become idle. Those descriptions may refer to a different endpoint version: the separately surfaced v3 documentation is not the /v1/screenshot reference. Confirm that your chosen wait option is supported by the exact endpoint and version in your account documentation.

When a fixed delay is enough

Use delay when the page has a reasonably consistent render time and you do not have a reliable readiness element. Start with a small value, inspect the saved image, and increase it only if required content is still missing. The documented range is 0–10,000 ms.

When to wait for a selector

If the page renders a known element only after data arrives, a selector wait can express the real requirement more directly than a guessed pause. Choose a selector that appears when the content is ready, such as the result container, and verify that an empty shell does not appear before its data. The feature page describes this strategy; verify its exact parameter spelling and availability for your endpoint version before adding it.

When network idle helps

Network-idle waiting can fit pages that populate themselves through several asynchronous requests. It can be a poor match for pages that keep requests open or continuously send analytics. If idle never arrives, use a readiness selector or a bounded delay if supported by the endpoint you use. Confirm the supported option and timeout behavior in that endpoint’s reference.

3. Decide which part of the page to capture

By default, the documented viewport is 1280 × 800 CSS pixels. Choose the capture scope based on what the screenshot needs to show.

Scope Setting or method Use it for Watch for
Viewport Default; set width and height if needed A visible screen, above-the-fold check, or responsive layout Content outside the viewport is omitted
Full page full_page=true A complete document or long page review Full-page height is capped at 4320 pixels; output can be large
Selected element Use the documented selector capture option for your endpoint version A chart, widget, card, or specific component An unmatched selector returns an error; confirm the element has rendered

The API reference says full-page capture scrolls through the page to activate off-screen content. The feature page also describes lazy-image loading during full-page capture. Treat that as a provider feature description, not a guarantee for every site: inspect the resulting image for images or content that load only under a particular interaction.

The v1 reference documents a maximum width of 3840 pixels, maximum height of 4320 pixels, and scale up to 3. Larger dimensions or scale can increase image size and render work. The default format is PNG and scale is 1. The reference gives a default timeout of 25 seconds and a configurable range of 1–30 seconds. Set only the dimensions, format, scale, and timeout needed for your use case, and check the current reference for exact parameter names.

4. Capture a JavaScript page reliably

  1. Open the target normally. Identify what appears only after JavaScript runs and whether the relevant content is above the fold.
  2. Pick a readiness signal. Use a delay for a predictable render, a selector for a known ready element, or network idle for request-driven rendering, where the endpoint supports that option.
  3. Choose viewport, full-page, or element scope. Consider the documented 4320-pixel full-page cap and whether the component needs to be captured separately.
  4. Authenticate without exposing secrets. Send the API key in the bearer header. For a protected target page, use the documented target cookies, target-host request headers, or HTTP basic authentication as appropriate.
  5. Inspect both the bytes and status information. Check the saved image and the final document status. The documented X-Page-Status header reports the final document status after redirects.
  6. Adjust one variable at a time. If content is missing, first verify status and URL, then adjust the readiness condition or capture scope.

5. Python example

This example uses requests, keeps the API key in an environment variable, and saves the response bytes. Install the dependency with python -m pip install requests.

import os
import requests

api_key = os.environ["SCREENSHOT_API_KEY"]
response = requests.get(
    "https://screenshot-api.net/v1/screenshot",
    headers={"Authorization": f"Bearer {api_key}"},
    params={
        "url": "https://example.com",
        "delay": 2000,
        "full_page": "true",
    },
    timeout=35,
)
response.raise_for_status()

page_status = response.headers.get("X-Page-Status")
content_type = response.headers.get("Content-Type", "")
if not content_type.startswith("image/"):
    raise RuntimeError(f"Expected image bytes; received Content-Type: {content_type}")

with open("screenshot.png", "wb") as image_file:
    image_file.write(response.content)

print("Final page status:", page_status)
print("Saved screenshot.png")

The client timeout here is 35 seconds to allow for the documented API timeout of up to 30 seconds plus some response overhead. The API’s full_page default is false; this example enables it explicitly. Remove that parameter for a viewport-only capture.

6. Node.js example

With Node.js 18 or later, built-in fetch is available. This example uses URLSearchParams so the target URL is encoded correctly and writes the returned bytes to disk.

import { writeFile } from 'node:fs/promises';

const apiKey = process.env.SCREENSHOT_API_KEY;
if (!apiKey) throw new Error('Set SCREENSHOT_API_KEY first');

const query = new URLSearchParams({
  url: 'https://example.com',
  delay: '2000',
  full_page: 'true',
});

const response = await fetch(
  `https://screenshot-api.net/v1/screenshot?${query}`,
  {
    headers: { Authorization: `Bearer ${apiKey}` },
    signal: AbortSignal.timeout(35_000),
  },
);

if (!response.ok) {
  throw new Error(`Screenshot request failed: HTTP ${response.status}`);
}

const contentType = response.headers.get('content-type') ?? '';
if (!contentType.startsWith('image/')) {
  throw new Error(`Expected image bytes; received Content-Type: ${contentType}`);
}

console.log('Final page status:', response.headers.get('x-page-status'));
await writeFile('screenshot.png', Buffer.from(await response.arrayBuffer()));

For older Node.js versions without built-in fetch, use a maintained HTTP client and preserve the same endpoint, bearer header, encoded query parameters, response checks, and binary output handling.

7. Protected pages, redirects, and authentication

A successful API response does not necessarily mean the target page showed the intended content. The target can redirect to a login screen, return an authorization error page, or present a bot check. Inspect X-Page-Status, which reports the final document status after redirects. A 401 or 403 can mean the screenshot is an authentication or access-denied page.

The v1 reference describes target cookies, target-host request headers, and HTTP basic authentication for protected pages. Supply only credentials that the capture is authorized to use, and keep both target credentials and the ScreenshotAPI.net API key private. Avoid placing production API keys in query strings, HTML, or client-visible source.

8. Troubleshooting

Symptom Likely cause What to do
Blank image or missing app content Capture happened before asynchronous rendering, the URL is wrong, or the final page is an error page Verify the target URL and X-Page-Status. Select a wait condition that matches the page’s render behavior, then inspect the new image.
Widget is absent despite a long delay The widget failed, requires an interaction, or the chosen page state differs from the one expected Check the page itself and use a selector that signals the widget is ready if supported for this endpoint. A longer delay cannot fix a failed script or blocked request.
Selector capture returns an error No element matched the selector, often because it had not rendered or the selector changed Verify the selector against the rendered page, wait for the element when supported, and retry with viewport capture to diagnose.
Full-page image ends early The requested page exceeds the documented 4320-pixel full-page height cap Capture a particular element or split the page into useful sections if the API workflow allows it.
Lazy images are missing The site loads images only after scrolling, interaction, or other site-specific events Try full-page capture, which the feature page says scrolls to activate off-screen content, then inspect the result. For unusual lazy-loading behavior, use a supported wait or site-specific capture approach.
401 or 403 page appears in the image The target requires authentication or blocks the request Use documented target cookies, target-host headers, or HTTP basic authentication when appropriate. Check the final status and whether the destination after redirects is expected.
Request times out The page or render took longer than the API timeout, or the client ended its request first Use a client timeout longer than the API timeout, simplify the capture scope or dimensions, and set an API timeout within its documented 1–30 second range where supported.
Downloaded file is not a usable image An error response or unexpected body was saved as an image Check HTTP status and Content-Type before writing bytes; review response headers and the API’s error details.
API key appears in logs or source Credential was put in a URL or exposed to a browser Use the bearer header from a server-side request and rotate an exposed key according to the provider’s account controls.

9. Performance, reliability, and cost considerations

Wait only as long as the page needs. A fixed delay adds its full duration even when rendering finishes early, while a wait that is too short produces an incomplete image. A selector can avoid guessing when it reliably represents readiness. Network idle may not be suitable for pages with persistent traffic. Record the target, wait choice, dimensions, format, and final page status with your own capture metadata so recurring failures are easier to diagnose.

Full-page captures and larger dimensions or scale create more image data and can require more rendering work than a viewport capture. Use PNG for crisp interface details by default; select another supported format only after confirming it is available in the endpoint reference and fits your output needs. The reviewed documentation provides parameter limits but no independent performance benchmark, uptime figure, or cost comparison, so do not infer those from the settings. Check ScreenshotAPI.net’s current plan and usage terms before estimating production cost.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. A single GET request captures a URL as PNG, JPEG, WebP, or PDF. Its [documentation](https://screenshotneo.com/docs/) lists the available options, including waits, full-page capture, element capture, and custom headers.

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}`);

ScreenshotNeo accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms along with newsletter popups and chat widgets; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.

Frequently asked questions

Why is my screenshot blank before the page finishes loading?

The screenshot can be taken after document navigation but before JavaScript has populated the visible content. Wait for the event that means your target content is ready, then verify the final document status and image.

Can I capture a full page after JavaScript loads?

Yes. Request full_page=true and choose an appropriate readiness wait. The documented full-page height limit is 4320 pixels, and the resulting image should be checked for content that loads only after interactions.

Should I use a delay or wait for a selector?

Use a delay when render time is predictable and a selector wait when a stable element indicates readiness, if that option is supported by your endpoint version. Network idle can fit request-driven rendering but may not settle on pages with persistent requests.

Does ScreenshotAPI.net’s v1 endpoint support the selector and network-idle settings?

The reviewed v1 reference documents delay; the feature page describes selector and network-idle waits. Because documentation also surfaces a separate v3 endpoint, confirm the exact options and parameter names for the endpoint version you are using.