ScreenshotNeo

BlogHow-to

How to Fix Selenium Screenshots Showing a White Page Before Content Loads

Wait for the page content your screenshot needs, not just navigation or document readiness. See runnable Selenium examples, diagnostics, and a browser-free option.

By the ScreenshotNeo team4 October 20267 min read

A Selenium screenshot can show a white page because the screenshot command ran before the page’s useful content appeared. After navigation, explicitly wait for a visible page element, expected text, or application-specific loaded marker that corresponds to what the image must contain. Then take the screenshot.

Waiting for navigation to return or for document.readyState to become complete is not always enough: JavaScript can continue rendering or updating a page after that point. Selenium’s waiting strategies explain this readiness race. Put the content-specific wait immediately before the capture.

1. Wait for the content you want to capture

Here is a runnable Python example. Install Selenium with pip install selenium, set PAGE_URL to the page you control or are authorized to access, and ensure the browser driver is available for your setup. Replace main with a stable locator that becomes visible when the screenshot’s meaningful content is ready.

import os
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

url = os.environ.get("PAGE_URL", "https://example.com")
driver = webdriver.Chrome()

try:
    driver.get(url)

    # Wait for the content required in the image, not just navigation.
    WebDriverWait(driver, 20).until(
        EC.visibility_of_element_located((By.CSS_SELECTOR, "main"))
    )

    driver.save_screenshot("page.png")
finally:
    driver.quit()

The 20-second timeout is an example, not a universal setting. Choose a stable locator for the actual page. If main appears before the relevant data or text, wait for that text, a loaded-state marker, or another observable condition that matches the desired image. Selenium’s Expected Conditions include visibility and text checks.

Wait for expected text

If a heading appears only after the content has loaded, wait for its text. This can be more meaningful than waiting for a broad container:

WebDriverWait(driver, 20).until(
    EC.text_to_be_present_in_element(
        (By.CSS_SELECTOR, "h1"),
        "Account overview"
    )
)
driver.save_screenshot("account.png")

Use text that is stable and specific to the state you need. If the page can legitimately show different text, wait for a reliable marker instead.

Wait after an action that triggers rendering

For a page that loads its content after a click or form submission, put the explicit wait after that action:

driver.find_element(By.CSS_SELECTOR, "button.load-results").click()
WebDriverWait(driver, 20).until(
    EC.visibility_of_element_located((By.CSS_SELECTOR, ".results-table"))
)
driver.save_screenshot("results.png")

The same pattern applies after navigation, a tab change, or another action that updates the page: perform the action, wait for the resulting state, then capture.

2. Choose the right wait condition

Condition Use it when Watch for
Visible element A known content element should be displayed in the image. Presence in the DOM alone does not mean the element is visible.
Expected text A particular heading, status, or result proves the required content arrived. Use text that is stable for the scenario.
Application loaded marker The application exposes a reliable marker for the ready state you need. Confirm the marker corresponds to the screenshot content, not merely initial page setup.
Fixed delay As a temporary diagnostic to see whether extra time changes the result. A delay can be too short on a slow run and waste time on a fast one.

Selenium explicit waits poll a condition until it succeeds or times out. Prefer a condition tied to the expected page state over a permanent fixed sleep. Do not combine implicit and explicit waits: Selenium warns that mixing them can cause unpredictable wait times. See the official wait documentation.

3. Understand page-load strategies

Page-load strategy controls when a navigation command returns. It does not establish that a JavaScript application has finished rendering the content required in a screenshot.

Strategy Navigation readiness What to do before a screenshot
normal (default) Waits for document readiness to reach complete. Still add an explicit wait for dynamic or application-rendered content.
eager Returns when readiness reaches interactive; some resources may still be loading. Use an explicit wait for the content needed in the image.
none Does not block navigation on document readiness. Synchronize subsequent actions with an explicit wait.

For Selenium 4 with Python, set the strategy when creating browser options:

from selenium import webdriver

options = webdriver.ChromeOptions()
options.page_load_strategy = "eager"  # "normal", "eager", or "none"
driver = webdriver.Chrome(options=options)

Changing this setting changes navigation timing; it does not replace the content wait. The default normal strategy is often a sensible starting point. Consider another strategy when navigation blocking itself is relevant to your workflow, and keep a page-specific explicit wait either way. Selenium documents these browser options.

4. Diagnose a screenshot that is still white

  1. Check where the browser actually navigated. Inspect driver.current_url and the page title. A redirect, error page, or unexpected destination changes what the screenshot can show.
  2. Check the wait target. Make sure the selector identifies the content in the intended state. A hidden element can exist without being visible, and a broad container can become visible before its data arrives.
  3. Inspect the page and browser diagnostics. Look at page source and browser or driver logs for navigation errors, JavaScript failures, or an intentional empty state. These checks help distinguish synchronization from a page that did not render successfully.
  4. Use a longer delay only as a diagnostic. If waiting longer changes the image, timing is likely involved. Replace the diagnostic sleep with an explicit wait for the content state.
  5. Compare browsers. If the same command behaves unexpectedly, reproduce it in another browser if available. Selenium’s troubleshooting guidance recommends comparing browsers to help identify underlying driver issues.

A timeout means the condition did not become true within the allotted time. It does not by itself prove the page is blank: the locator may be wrong, the expected content may not have loaded, or the timeout may be too short for the environment.

5. Common errors and fixes

Symptom Likely cause Fix
Screenshot is blank immediately after get() Dynamic content was still rendering when capture ran. Wait for a visible content element or expected text immediately before capture.
Wait times out although the page looks loaded The selector or text does not match the rendered page, or the target is hidden. Inspect the page, verify the locator, and use a visibility or text condition that matches the intended state.
Wait passes but the screenshot still lacks data The chosen marker appears before the relevant data is ready. Wait for the specific data, result, or application marker represented in the screenshot.
Fixed sleeps work inconsistently Load time varies between runs. Use a condition-based explicit wait with a suitable timeout.
Wait durations seem unexpectedly long Implicit and explicit waits may be combined. Use one synchronization approach for element waits; Selenium cautions against mixing the two.
White page persists across conditions The browser may be at an unexpected destination, the page may have failed, or browser/driver behavior may be involved. Check URL, title, source, and logs, then compare behavior in another browser.

6. Keep screenshot runs fast and reliable

  • Wait for the smallest meaningful condition. A stable page-specific marker avoids waiting for unrelated content and makes the capture point easier to reason about.
  • Set a finite timeout. A timeout gives a clear failure path when the expected state never appears. Choose it for the page and environment rather than assuming one value fits all sites.
  • Capture after state-changing actions. A wait before a click does not synchronize the update caused by the click; wait for the resulting state.
  • Keep diagnostic evidence. When a wait times out, record the URL and relevant browser or driver diagnostics so the failure can be distinguished from a selector mismatch.
  • Account for environment differences. Browser and driver behavior can affect results; compare browsers when the page and wait condition appear correct.

There is no one timeout or readiness strategy that guarantees every site is ready. The reliable signal is the condition that represents the content this screenshot needs.

Or skip the browser setup

ScreenshotNeo takes a screenshot with one API request. See the API documentation for options and response details.

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 and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Learn about ScreenshotNeo or sign up for 1,000 free screenshots a month, no card required.

FAQ

Does document.readyState == "complete" mean a screenshot is ready?

No. It describes document loading, but JavaScript can still change the page afterward. Wait for the visible content or state the image requires.

Should I use eager or none to fix a white screenshot?

Those strategies change when navigation returns. They do not guarantee that dynamic content is ready. Keep an explicit wait for the page-specific condition.

Is a fixed sleep ever useful?

As a temporary diagnostic, yes: it can show whether timing is contributing. For ongoing automation, a condition-based wait is more responsive and tied to the expected state.

What if the website has no obvious loaded marker?

Choose a stable visible element or expected text that appears only when the content needed in the screenshot is present. If no such signal exists, inspect the page’s behavior and identify an observable condition before relying on a delay.