On this page

    Get the right capture

    Fix Blank or Incomplete Screenshots

    A spinner instead of data, grey boxes instead of images, or a timeout: find the cause in your logs and fix it with the right wait or scroll option.

    Time
    15 minutes
    Plan
    Free
    You need
    • An API key in RS_API_KEY
    • The URL that gives the bad screenshot

    What you will have at the end

    The same page that first showed only a spinner, captured after its report appeared.

    By default the API takes the screenshot when the browser fires its load event. Many pages are not finished at that moment: they still fetch data, or they load images only when you scroll. You will find which case you have and add the option that fixes it.

    The examples use two small test pages, so the result is the same every time you run them.

    Find the cause

    You see Cause Fix
    A spinner, "Loading…" or empty cards The page fetches its data after load Step 2: wait for a selector
    Grey boxes where images should be (full page) Images load when they scroll into view Step 3: simulate scrolling
    Error timeout (422) The page never reached the wait condition Step 4
    A cookie banner, an ad or a sign-up box Not a timing problem Remove cookie banners and ads
    "Access denied" or a challenge page The site blocks automated browsers Capture sites with bot protection

    For a failed request, open Logs, click the request, and read the error message:

    A timeout costs no credits. The message shows the timeout the API used, in milliseconds.

    Wait for the content

    Find an element that exists only when the content is ready: the chart, the first row of a table, the product price. Open the page in your browser, inspect that element and copy a selector for it.

    Then ask the API to wait for it:

    {
      "url": "https://app.example.com/reports/weekly",
      "wait": { "for_selector": "#report", "for_selector_mode": "visible" }
    }
    
    Default (load)
    wait.for_selector
    The test page loads its report 2.5 seconds after load. The default captures the spinner. With for_selector, the API waits for #report.

    Node.js

    const image = await client.take(
      TakeOptions.url('https://app.example.com/reports/weekly').waitForSelector('#report')
    );
    

    Python

    image = client.take(
        TakeOptions.url('https://app.example.com/reports/weekly').wait_for_selector('#report')
    )
    

    Ruby

    image = client.take(
      RenderScreenshot::TakeOptions.url('https://app.example.com/reports/weekly').wait_for_selector('#report')
    )
    

    CLI

    rs take https://app.example.com/reports/weekly --wait-selector "#report" -o report.png
    

    If you own the page, the most reliable signal is one you add yourself: set an attribute when the page is done, for example document.documentElement.dataset.screenshotReady = 'true', and wait for html[data-screenshot-ready="true"].

    No good selector? Two other options:

    Option Use when
    "wait": { "until": "networkidle" } The page stops making requests when it is done. Not good for pages with live chat, analytics beacons or polling.
    "wait": { "delay": 2000 } You know the page needs a fixed time. Adds the delay to every request, up to 10,000 ms.

    Load lazy images

    A full-page capture takes the whole page in one image, but the browser does not scroll. Images that load on scroll stay grey. Turn on scroll simulation:

    {
      "url": "https://shop.example.com/collections/spring",
      "capture": { "mode": "full_page", "scroll": { "simulate": true, "delay": 400 } }
    }
    
    full_page
    + scroll.simulate
    The test gallery loads each tile when it scrolls into view.

    The full_page preset turns scroll simulation on for you. Raise scroll.delay (milliseconds between scroll steps) for pages with slow images.

    Fix timeouts

    A timeout means the page did not reach the wait condition within wait.timeout (30 seconds by default). Try these in order:

    1. Wait for a selector instead of networkidle. Pages with chat widgets or analytics never become idle.
    2. Block what you do not need. Ads, trackers and chat widgets are often the slowest part of a page:
       { "block": { "ads": true, "trackers": true, "chat_widgets": true } }
    
    1. Raise the timeout, up to 60 seconds. Also raise your HTTP client timeout above it, or your code gives up first:
       { "wait": { "for_selector": "#report", "timeout": 45 } }
    

    A timeout costs no credits, and retryable is true, so one retry is fine. If the same URL times out again with 45 seconds, the page needs one of the other fixes.

    Next steps

    Try RenderScreenshot free

    150 free credits every month, no credit card required.