ScreenshotNeo

BlogGuides

Why Does a Website Screenshot Show a Blank Area Below the Fold?

A blank area below the fold usually means the capture is viewport-only or deferred content never loaded. Check the capture scope, then trigger and verify lazy content.

By the ScreenshotNeo team4 October 20269 min read

A blank area below the fold usually has one of two causes: the screenshot captures only the visible browser viewport, or content farther down the page has not loaded when the capture happens. A full-page option extends the capture area, but it does not guarantee that lazy images, scroll-triggered components, or delayed scripts have rendered. First confirm the capture scope, then scroll through the page and wait for the expected content before capturing again.

The right fix depends on the page and capture method. Compare the screenshot with the live page, check for missing network resources or JavaScript errors, and wait for a real page-specific readiness condition where possible.

1. Confirm whether the screenshot is full-page

A viewport screenshot shows the area currently visible in the browser window. Content below that viewport is absent by design. A full-page screenshot captures the scrollable document; an element screenshot captures only a selected element. Playwright documents these as separate capture choices, with fullPage: true selecting the full scrollable page. Playwright screenshot options

If the image ends at the bottom of the initial viewport, check the tool’s capture mode before investigating page code. Also verify that the blank region is actually part of the document: a fixed-height viewport capture, a clipped capture, or an element-only capture can look like a page with a blank bottom.

2. Why full-page captures can still have blank areas

Lazy-loaded images and components

Lazy loading defers fetching or rendering until content is near the viewport. For images, the browser may wait until an image approaches the visible area before requesting it. A full-page screenshot can measure and capture a tall document without reproducing the sequence of scroll events a person would create. If a site’s loader depends on scrolling or an intersection observer, the image or component may remain an empty placeholder. MDN: Lazy loading and MDN: the image loading attribute

Scroll-triggered scripts, animation, and delayed rendering

Some pages insert content only after a section enters view, start animations on scroll, or fetch data after a user action. A screenshot taken immediately after navigation can capture the space reserved for content before the script has filled it. A fixed delay may help diagnose a timing issue, but it cannot guarantee readiness on every page.

Page-specific failures

A failed image request, blocked third-party resource, JavaScript exception, bot challenge, or page error can also leave a blank section. If the section is blank when you scroll to it in an ordinary browser, investigate the page itself first. The capture tool may simply be recording what the browser rendered.

3. Troubleshoot in this order

  1. Check the capture mode. Confirm it is full-page, not viewport-only, clipped, or limited to one element.
  2. Open the same URL in a regular browser. Scroll to the blank region. If it is blank there too, inspect the page’s rendering and resources.
  3. Scroll through the page before capture. Move down in viewport-sized steps and pause briefly at each step so lazy loading and scroll observers can run. Return to the intended position before taking a viewport screenshot; for a full-page capture, return to the top for predictable behavior.
  4. Wait for the content itself. When automating, wait for a known image or section to become visible or complete, rather than relying only on a guessed delay.
  5. Inspect browser diagnostics. Look for failed image or script requests, console errors, blocked cross-origin content, or a bot-check page in place of the expected content.
  6. Repeat the capture and inspect the exact region. Note whether the blank area is an unloaded image, an empty component, a whole section, or just a blank tail after the document ends. Those symptoms point to different causes.

4. Reproducible fix with Playwright and Node.js

The script below opens a page, scrolls down in viewport-sized steps to trigger lazy loading, waits for images to finish or fail, returns to the top, and saves a full-page screenshot. It intentionally treats image errors as diagnostic data rather than waiting forever. Install Playwright and its Chromium browser once, then run the script with Node.js.

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

const url = process.argv[2] ?? 'https://example.com';
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });

try {
  await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
  // Let initial styles and scripts run. This is not proof that all page content is ready.
  await page.waitForTimeout(500);

  // Scroll in steps to trigger native lazy loading and scroll-based observers.
  await page.evaluate(async () => {
    const step = Math.max(300, Math.floor(window.innerHeight * 0.8));
    for (let y = 0; y < document.documentElement.scrollHeight; y += step) {
      window.scrollTo(0, y);
      await new Promise(resolve => setTimeout(resolve, 250));
    }
    window.scrollTo(0, document.documentElement.scrollHeight);
    await new Promise(resolve => setTimeout(resolve, 500));
  });

  // Wait for images that have been requested; report failures rather than hanging.
  const imageReport = await page.evaluate(async () => {
    const images = [...document.images];
    await Promise.all(images.map(img => {
      if (img.complete) return Promise.resolve();
      return new Promise(resolve => {
        img.addEventListener('load', resolve, { once: true });
        img.addEventListener('error', resolve, { once: true });
        setTimeout(resolve, 10000);
      });
    }));
    return images.map(img => ({
      src: img.currentSrc || img.src,
      loaded: img.complete && img.naturalWidth > 0,
      width: img.naturalWidth
    }));
  });

  await page.evaluate(() => window.scrollTo(0, 0));
  await page.waitForTimeout(250);
  await page.screenshot({ path: 'page.png', fullPage: true, animations: 'disabled' });
  console.log(JSON.stringify({ screenshot: 'page.png', images: imageReport }, null, 2));
} finally {
  await browser.close();
}
node capture.mjs https://example.com

Use an actual selector when the page exposes a stable readiness target. For example, after navigation you can add await page.locator('[data-loaded="true"]').waitFor({ state: 'attached', timeout: 15000 }); if that attribute accurately indicates that the section is populated. Replace the example selector with one from the target page; there is no universal selector for “everything is finished.”

Useful Playwright capture options

Option What it changes When it helps
fullPage: true Captures the full scrollable page rather than the viewport. Content exists below the initial viewport.
page.locator(selector).screenshot() Captures a specific element. You need to isolate a section or component.
clip Limits the screenshot to a rectangle. You need a defined region; make sure it does not exclude the missing area.
animations: 'disabled' Disables CSS animations and transitions during capture. Animations make the result inconsistent; it does not trigger content loading by itself.
scale: 'css' Uses one output pixel per CSS pixel. Large full-page images need a smaller output size.
timeout Sets the screenshot operation timeout. A capture itself is taking too long; it does not wait for missing page content before capture.

Playwright’s screenshot API also supports image type, quality for JPEG/WebP, caret handling, background transparency, masks, and a stylesheet applied during capture. Those options affect the output or presentation; none guarantees that deferred page content has loaded. Check the official screenshot API reference for the current option details.

5. Edge cases to account for

  • Infinite scrolling: The page grows as you scroll. A full-page capture taken before the desired items are loaded cannot include them. Decide on a stopping condition, such as a target item count or an end-of-results marker, and stop after that condition is met.
  • Virtualized lists: Some frameworks render only items near the viewport and recycle DOM nodes as you scroll. A single very tall screenshot may not contain every item because offscreen rows may not exist at capture time. Capture sections separately or use the application’s export/data path.
  • Lazy background images: The image may be a CSS background, not an <img>; checking document.images will not report it. Inspect computed styles and the network panel.
  • Embedded frames: An iframe can load later or fail independently. Wait for a stable frame locator or verify its own network and permissions.
  • Consent screens and bot checks: A page may show an overlay or challenge instead of the content. Determine whether it is a site access requirement or an automated-traffic check before treating the blank region as a screenshot defect.
  • Responsive layout: Changing viewport width can alter content flow, image sources, and whether a component loads. Reproduce the target device dimensions and device scale factor.
  • Very tall documents: Browser and image-size limits can affect enormous captures. Capture smaller sections if a full-page output is too large or unstable.

6. Reliability, speed, and cost considerations

Scroll-and-wait improves coverage for scroll-dependent content, but it adds time proportional to page height and the chosen pauses. Waiting for every image can also slow down pages with trackers or broken third-party resources. Prefer waiting for the content that matters and use bounded timeouts so a failed request does not hold the job indefinitely.

For repeatable captures, keep viewport, browser, device scale, locale, authentication state, and page state consistent. Log the URL, capture mode, wait condition, failed image URLs, and timestamp when a capture is blank. This makes intermittent network failures distinguishable from a reproducible page behavior.

With a self-hosted browser, account for browser installation, runtime, concurrency, retries, and storage for large images. A managed API replaces much of that browser setup with per-request pricing; compare whether its wait controls, full-page behavior, output formats, and failure reporting match the pages you capture. Do not treat a larger delay as a universal fix.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its full-page capture loads lazy images, and its wait options include a selector, delay, or network idle. The parameters other screenshot APIs use also work, which can make switching easier. See the ScreenshotNeo API documentation.

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

Cookie banners, popups, and chat widgets are removed before the shot, and each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed; response headers report the page verdict and billing status. An MCP server lets AI agents using Claude, Cursor, or another MCP client take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up free for ScreenshotNeo.

Common errors and fixes

Symptom Likely cause Fix
Screenshot ends at the initial viewport Viewport capture is enabled. Enable full-page capture, or capture the specific element you need.
Full-page image has an empty block where images belong Lazy images were not requested, or image requests failed. Scroll through the page, wait for the images, then inspect currentSrc, naturalWidth, and failed network requests.
Text section remains empty despite waiting Scroll observer, delayed script, API request, or script error. Trigger the section by scrolling; wait for a page-specific selector; inspect console and network errors.
Only the bottom of the screenshot is blank The document may be taller than its rendered content, or a reserved placeholder remains. Compare document height and visible content in the live page; inspect the layout and the element occupying that space.
Capture times out Navigation, a resource, or the screenshot operation exceeded its timeout. Use a bounded navigation/readiness condition, investigate slow requests, and avoid waiting for all network activity if the page keeps connections open.
Works locally but not in automation Different viewport, cookies, authentication, browser state, or automated-traffic response. Match the intended context and inspect the rendered page for login, consent, or bot-check screens.

FAQ

Does full-page capture automatically scroll the page?

It requests a full-page image, but that does not guarantee the page’s own scroll-triggered code ran for every section. If content depends on scroll events, scroll the page before capture.

Should I wait for network idle?

It can be useful for pages whose important requests settle, but analytics, polling, and persistent connections can prevent idle. A selector or resource-specific condition is often more reliable.

Why is the screenshot blank but the page looks fine after I scroll?

The scrolling likely triggered lazy loading or a scroll observer after the capture had already taken its snapshot. Reproduce that scroll-and-wait sequence in the capture workflow.

Can I fix this by setting every image to eager loading?

Only if you control the site and accept loading all those images up front. For capturing a third-party page, scrolling and waiting is usually the practical diagnostic.

Sources