DEV Community

eracconseil
eracconseil

Posted on

How I handle lazy-loaded full-page screenshots in a Chrome Extension (MV3)

Most full-page screenshot tools have a dirty secret: they miss content that loads on scroll.

Here's why — and how I fixed it.

The problem

Modern websites use lazy loading: images, sections, and components only render when they enter the viewport. A naive screenshot tool captures the page once, missing everything below the fold that hasn't loaded yet.

The pre-scroll algorithm

Before capturing anything, I scroll the entire page in steps:

async function preScrollPage() {
  const totalHeight = document.body.scrollHeight;
  const step = window.innerHeight * 0.8;
  let currentPos = 0;

  while (currentPos < totalHeight) {
    window.scrollTo(0, currentPos);
    await sleep(150); // wait for lazy-load to trigger
    currentPos += step;
  }

  // Scroll back to top before capturing
  window.scrollTo(0, 0);
  await sleep(300);
}
Enter fullscreen mode Exit fullscreen mode

The 150ms delay per step gives images time to start loading. After the full pre-scroll, I scroll back to top and start the actual capture.

MV3 service worker gotcha

Chrome MV3 killed persistent background pages. My service worker goes idle between captures. The fix: use chrome.scripting.executeScript with a content script that handles the entire capture loop, not the background script.

Stitching 30+ screenshots

Each capture segment is a base64 PNG. To stitch them:

  1. Create an offscreen canvas of totalWidth × totalHeight
  2. Draw each segment at its y offset
  3. Export as a single PNG blob

The tricky part: the last segment often overlaps with the previous one if the page height isn't a perfect multiple of the viewport. I track capturedHeight and clip the last segment accordingly.

Result

Full Page Screenshot Pro — now handles any page regardless of length, with lazy-loaded content fully captured.

Happy to answer questions about Chrome extension development or the MV3 migration.

Top comments (0)