How to Capture Lazy-Loaded Images on a Shopify Collection Page
Inspect Shopify’s live image markup, trigger below-the-fold loading, and verify the actual image request in Chrome DevTools.
To capture a lazy-loaded image on a Shopify collection page, inspect the live page in Chrome DevTools, scroll the product card into view, then verify the selected image URL and request in the Network panel. The HTML’s initial src may not be the URL the browser ultimately downloads: responsive markup can offer several candidates, and JavaScript or a theme app may change the live element after scrolling.
This method helps you identify and document the image the storefront actually loaded. If you need a screenshot of the rendered collection page, you can capture it after triggering lazy loading; the optional ScreenshotNeo route appears below.
1. Inspect the product image in Chrome
- Open the Shopify collection page in Chrome and open DevTools (F12 or Ctrl+Shift+I on Windows/Linux; ⌘+Option+I on macOS).
- In Elements, activate Inspect mode and select the product image. Chrome’s Inspect mode highlights the corresponding DOM element, and the Styles panel shows its applicable styles. See Chrome’s Inspect mode documentation.
- Record the live
<img>attributes:src,srcset,sizes,loading, andalt. Also note whether the image is inside a<picture>element. - With the element selected in Elements, use the Console to inspect
$0.currentSrc.$0refers to the selected element in Chrome DevTools. If you prefer, select the image in the console withdocument.querySelector('img'), but a collection page may have many images, so selecting the specific element is safer. - Open Network, enable the image filter, and reload or scroll the product card into view. Click the image request to inspect its requested URL, status, and response details. The Network request is the evidence of what the browser requested; Elements shows the current markup.
Shopify documents responsive image markup and recommends using its image_url and image_tag filters rather than constructing CDN URLs manually. Its guidance says to use srcset and sizes with image_tag so the browser can select appropriately sized images for each viewport. See Shopify’s responsive image guidance and Shopify’s image filter guidance.
2. Trigger lazy loading below the fold
For an offscreen product card, scroll until it approaches or enters the viewport, wait for loading, then check Network for an image request. Shopify recommends using Chrome DevTools Network to verify which image sizes download at different viewport widths. Do not conclude that an image is missing just because it was not requested at initial page load.
You can use this read-only snippet in the DevTools Console to scroll the page in viewport-sized steps and then report image elements currently in the DOM. It does not download or save image files; use Network to verify the actual requests. It may trigger other scroll-based page behavior as well.
async function scanCollectionImages() {
const pause = ms => new Promise(resolve => setTimeout(resolve, ms));
const step = Math.max(300, window.innerHeight * 0.8);
const originalY = window.scrollY;
const maxY = Math.max(0, document.documentElement.scrollHeight - window.innerHeight);
for (let y = 0; y <= maxY; y += step) {
window.scrollTo(0, y);
await pause(350);
}
window.scrollTo(0, maxY);
await pause(1000);
const images = [...document.images].map(img => ({
alt: img.alt,
loading: img.loading,
src: img.getAttribute('src'),
srcset: img.getAttribute('srcset'),
sizes: img.getAttribute('sizes'),
currentSrc: img.currentSrc,
complete: img.complete,
naturalWidth: img.naturalWidth,
naturalHeight: img.naturalHeight
}));
window.scrollTo(0, originalY);
console.table(images);
return images;
}
scanCollectionImages();
For the element you selected in Elements, inspect it directly after scrolling:
({
src: $0.getAttribute('src'),
srcset: $0.getAttribute('srcset'),
sizes: $0.getAttribute('sizes'),
loading: $0.getAttribute('loading'),
currentSrc: $0.currentSrc,
complete: $0.complete,
naturalWidth: $0.naturalWidth,
naturalHeight: $0.naturalHeight
})
A non-empty currentSrc indicates the source selected for that element after layout. Confirm it against the Network panel rather than treating it as proof of a successful download: check that a request occurred and completed. If the theme uses a script-based loader, inspect the live attributes again after scrolling or performing the interaction that triggers it.
3. Interpret the URL and responsive candidates
| Evidence | What it tells you |
|---|---|
src |
The current fallback or declared source attribute. It may not be the selected responsive candidate. |
srcset and sizes |
The candidate URLs and layout information the browser can use to choose a source for the viewport. |
currentSrc |
The source selected by the browser for the image after layout and source selection. |
| Network request URL | The URL the browser requested. Check its status and response when diagnosing whether loading succeeded. |
naturalWidth and naturalHeight |
The intrinsic dimensions of the loaded image; zero can indicate that no image has loaded successfully. |
The selected URL can vary with viewport and layout because the browser chooses among responsive candidates. When documenting the behavior, keep both the candidate attributes and the actual requested URL. Shopify’s responsive image documentation also recommends sizes: 'auto' for images with loading="lazy"; eager images need explicit sizes because the browser selects a source before layout.
4. Distinguish lazy loading from a missing image
- Image loads after scrolling: this is consistent with deferred loading for an offscreen image. Record the trigger, selected URL, and Network result.
- Markup changes after scrolling: a theme script or app may update the element or its attributes. Inspect the live DOM after the trigger; the initial response may differ.
- No request appears: scroll the specific card into view and wait. If still absent, check whether the image is represented by another element, whether interaction is required, and whether the theme uses a script-based loader.
- A request appears but fails: inspect the request’s status and response details. The cause depends on the page and its theme or apps; the request record is more useful than guessing from markup alone.
- The image is visually absent despite a successful request: inspect the live element and applicable styles, and check whether the image dimensions or presentation changed.
5. Keep above-the-fold images separate
Lazy loading is intended for images outside the initial viewport. Shopify advises against lazy-loading the Largest Contentful Paint (LCP) image or another critical image visible at initial load, because deferring it delays discovery and download. A collection can show multiple product cards, so a card’s position in a section alone does not establish whether it is initially visible. Evaluate the actual viewport and the page’s LCP candidate. See Shopify’s guidance on not lazy-loading the LCP image and its theme performance best practices.
6. Save a screenshot after lazy images load
If your goal is a visual record rather than the source image file, trigger loading first, then capture the page with Chrome’s screenshot tools or another browser capture workflow. A screenshot records the rendered view; it does not preserve the original responsive candidate list or prove which URL was requested. Keep the DevTools evidence when you need to troubleshoot image delivery.
Or skip the browser setup
For a rendered capture, ScreenshotNeo accepts a URL in one GET request and returns an image or PDF. Its clean capture steps accept cookie or consent banners like a visitor and remove 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. ScreenshotNeo also has an MCP server with take_screenshot, get_page_info, and capture_pdf tools for AI agents.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://YOUR-STORE.myshopify.com/collections/YOUR-COLLECTION -o collection.webp
See the ScreenshotNeo API documentation for request options. The same endpoint can be called from Python or Node.js:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={
"access_key": "YOUR_API_KEY",
"url": "https://YOUR-STORE.myshopify.com/collections/YOUR-COLLECTION",
},
timeout=90,
)
r.raise_for_status()
open("collection.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://YOUR-STORE.myshopify.com/collections/YOUR-COLLECTION'
});
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('collection.webp', res);
Replace the example store and collection path with the public collection URL. ScreenshotNeo offers 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 shots. Create a free account and capture your first 1,000 screenshots.
7. Troubleshooting checklist
| Symptom | Likely explanation | Next step |
|---|---|---|
| Image not in initial HTML | JavaScript may insert or update it later, or the page may use a script-based loader. | Inspect the live DOM after scrolling or after the relevant interaction. |
src is empty or looks like a placeholder |
The loader may populate the source only when the card approaches the viewport. | Scroll the card into view, wait, and inspect src, srcset, and currentSrc again. |
currentSrc differs from src |
The browser selected a responsive candidate from srcset. |
Record srcset and sizes, then verify the selected URL in Network. |
| No image request after scrolling | The wrong card may be selected, more scrolling or an interaction may be needed, or the loader may work differently. | Confirm the selected DOM element and inspect the page’s live markup after the trigger. |
| Request fails or returns an unexpected result | The request did not complete as expected; the specific reason varies by storefront and its theme or apps. | Open the Network entry and review its status and response, then compare with the live element. |
| Image loads at a different size on another screen | Responsive source selection can vary by viewport and layout. | Repeat the capture at the relevant viewport and compare the candidate list and request URL. |
| Initial hero or first product image appears late | A critical above-the-fold image may have been deferred. | Check whether it is the LCP candidate; Shopify recommends that critical initial-viewport images load eagerly. |
8. Reliability, performance, and cost notes
- For reliable evidence: use Elements and Network together. Mark the viewport, scroll trigger, selected URL, and request result. Initial HTML alone may not reflect the rendered page.
- For repeatable comparisons: keep the viewport and scroll position consistent. Different responsive candidates can be selected when layout or viewport changes.
- For performance diagnosis: distinguish offscreen lazy images from the LCP or other critical images visible at initial load. Shopify’s guidance is not to lazy-load the LCP image.
- For cost: DevTools inspection and the console snippet use your browser. ScreenshotNeo’s free plan includes 1,000 shots per month without a card; paid tiers are Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is available on every plan.
FAQ
Does currentSrc prove that the image downloaded?
No. It identifies the selected source. Check Network for the request and its result; complete and intrinsic dimensions can provide additional clues about the element’s loading state.
Can I save the original product image from a screenshot?
A screenshot is a rendered visual record, not the original image file. Use the image URL and Network response when you need to identify the delivered asset.
Should every product image on a collection page be lazy-loaded?
Shopify advises against lazy-loading the LCP image and other critical images in the initial viewport. Evaluate which images are actually visible at the viewport size in question.
Why does the downloaded image vary between viewport sizes?
Responsive markup can provide multiple candidates, and the browser selects based on layout and viewport. Compare srcset, sizes, currentSrc, and the Network URL at each size.


