How to Generate Website Thumbnails for a Shopify Store Directory in India
Build consistent Shopify directory thumbnails with Playwright screenshots, predictable crops, and Shopify-ready files. Includes code and a ScreenshotNeo option.
To make thumbnails that show how a Shopify store actually looks, open each storefront in a browser at a fixed viewport, capture the visible page or a chosen element, then crop and resize every image to the same aspect ratio and output size. Shopify-hosted product images are a better source when the directory card should show a product or collection photo rather than the storefront design.
For a repeatable workflow, use Playwright to render each public store, write a viewport screenshot, and normalize the resulting files before uploading them. Shopify’s Storefront API image resources can provide and transform Shopify-hosted images, but they do not create screenshots of an entire storefront. Shopify Storefront API Image documentation
1. Choose what each directory thumbnail represents
| Thumbnail goal | Use | Why |
|---|---|---|
| Preview the store’s design | Browser screenshot of its storefront | Shows the rendered theme, layout, colors, and visible content. |
| Show a representative product or collection | An authorized Shopify-hosted image URL | Uses an existing image resource and Shopify’s image transformations. |
Do not treat a product image URL as a storefront screenshot. They are different assets with different purposes. If you collect and publicly display screenshots or store images, check applicable store terms, image rights, privacy issues, and jurisdiction-specific legal requirements. The technical documentation does not determine whether a particular use is permitted.
2. Set a consistent capture specification
Choose these values before processing the directory. Keeping them stable matters more than choosing one universal thumbnail size, because the right dimensions depend on the directory’s card layout.
- Page target: use the home page, a relevant landing page, or a specific product page consistently.
- Viewport: select a fixed width and height that reflects the intended preview. A viewport image is usually easier to scan in a directory grid than a very tall full-page image.
- Capture region: use a viewport screenshot for a page preview, an element screenshot for a hero or header, or a full-page screenshot when long-page content is important.
- Aspect ratio and crop: specify one ratio and crop position, such as centered, for every card. Consistent ratios help image grids align. Shopify gives this guidance for product and collection imagery; applying it to directory cards is a design recommendation.
- Pixel scale: Playwright’s
cssscale produces one output pixel per CSS pixel.devicescale uses device pixels and can create larger files. Choose based on display size, legibility, and file weight. - Output: standardize the final width, image format, quality if lossy, and filename convention. Use neutral descriptive filenames; avoid suffixes such as
thumb,small, orlarge, which Shopify says its CDN may interpret as image transformation requests.
Playwright supports viewport, element, and full-page screenshots, plus CSS-pixel and device-pixel scales. Playwright screenshot guide and Page screenshot API
3. Generate a storefront thumbnail with Playwright
The following runnable Node.js example captures one visible viewport per URL. It uses a fixed viewport, waits for the page to reach a usable load state, and saves PNG files. Start with a small number of stores and validate the results before processing a large directory.
npm init -y
npm install playwright
npx playwright install chromium
// capture.mjs
import { chromium } from 'playwright';
import { mkdir } from 'node:fs/promises';
const stores = [
{ name: 'example-store', url: 'https://example.com' },
];
const outputDir = './thumbnails';
await mkdir(outputDir, { recursive: true });
const browser = await chromium.launch({ headless: true });
try {
for (const store of stores) {
const page = await browser.newPage({
viewport: { width: 1280, height: 800 },
deviceScaleFactor: 1,
});
try {
await page.goto(store.url, {
waitUntil: 'domcontentloaded',
timeout: 45_000,
});
// Give client-rendered storefront content a short chance to appear.
await page.waitForTimeout(1_000);
await page.screenshot({
path: `${outputDir}/${store.name}.png`,
fullPage: false,
scale: 'css',
animations: 'disabled',
});
console.log(`Saved ${store.name}`);
} catch (error) {
console.error(`Failed ${store.name} (${store.url}):`, error.message);
} finally {
await page.close();
}
}
} finally {
await browser.close();
}
Run it with node capture.mjs. Replace the sample URL with stores you are authorized to capture. The example continues after a per-store failure so one inaccessible site does not abort the batch.
Capture only a specific element
If the card should show a hero region rather than the top of the page, wait for a stable selector and screenshot that element. Selector names vary by theme, so inspect each site’s markup or define a fallback strategy.
const hero = page.locator('main').first();
await hero.waitFor({ state: 'visible', timeout: 10_000 });
await hero.screenshot({ path: `${outputDir}/${store.name}.png` });
Capture a full page when the whole layout matters
await page.screenshot({
path: `${outputDir}/${store.name}-full.png`,
fullPage: true,
scale: 'css',
});
Full-page captures can be very tall and are often harder to read when reduced into a small card. If you use them, resize and crop deliberately rather than relying on an automatic thumbnail crop.
4. Get existing Shopify images through the Storefront API
When a listing represents a product or collection rather than the website’s layout, use an image resource supplied through an authorized Shopify Storefront API workflow. The Image object exposes fields such as its URL, dimensions, alt text, and placeholder data. Its URL supports transformations for resizing, cropping, scale, and preferred output type; Shopify describes those transformations as best-effort, so validate the returned asset.
This GraphQL query requests an image URL and metadata from a product. It assumes you already have a Storefront API access token and product handle:
query ProductImage($handle: String!) {
product(handle: $handle) {
title
featuredImage {
url(transform: { maxWidth: 640, maxHeight: 400, crop: CENTER, preferredContentType: WEBP })
altText
width
height
}
}
}
Send it to your store’s Storefront API endpoint using your authorized token. The endpoint and token are store-specific; obtain them through Shopify’s documented app and API setup rather than guessing credentials. See the Image object and transformation arguments. Unsupported transformations can be ignored, so inspect the returned URL and image dimensions.
5. Normalize, validate, and upload the files
- Crop to the directory’s chosen aspect ratio and focal point.
- Resize to the actual card display dimensions, with enough pixels for the largest expected display.
- Choose a format supported by your delivery path and verify the resulting file opens correctly.
- Use stable, neutral filenames, for example
store-example-homepage-2026-10.webp. Avoid ambiguous size words in filenames. - Check that the image is not blank, blocked, dominated by a modal, or captured before key content appears.
- If uploading to Shopify Files, confirm size, dimensions, format, and alt text before publishing.
Shopify Files guidance lists a maximum file size of 20 MB and maximum image resolution of 25 megapixels, with JPEG, PNG, WebP, HEIC, and GIF accepted. Product and collection media guidance separately lists maximum dimensions of 5000 × 5000 pixels and under 20 MB. These limits apply to different Shopify guidance contexts; validate against the destination you use. Shopify Files image requirements · Shopify product media guidance
Keep useful alt text where the image conveys store identity or content. For a purely decorative thumbnail in a card that already names and links the store, the site’s accessibility design may call for empty alt text instead. Decide based on how the image functions in your directory.
6. Batch capture safely and keep results repeatable
- Use a queue: process a bounded number of pages at a time rather than opening an unlimited number of browser contexts.
- Set timeouts: sites may be slow, offline, or blocked. Record failures and retry them separately with a limit.
- Record provenance: keep the source URL, capture date, viewport, and status alongside each image so you can reproduce or refresh it.
- Make retries idempotent: write to a temporary file and replace the prior thumbnail only after a new capture validates.
- Refresh intentionally: storefronts change. Choose a refresh schedule based on how quickly your directory needs to reflect theme changes, rather than recapturing on every page view.
- Check output cost: self-hosting screenshots uses browser compute, storage, and transfer. Reuse a prior image when the target has not changed enough to justify recapture.
Page-load strategy affects completeness and latency. domcontentloaded returns sooner but can precede late images or client-rendered content; load waits for load events but can be delayed by third-party resources. Network-idle waiting can be unreliable on pages with ongoing requests. Use a stable selector or a short bounded delay when a particular region must be ready, and keep an overall timeout.
7. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. For a directory thumbnail, request the target storefront and choose the output settings you need. 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);
Replace the sample target URL with a storefront URL you are authorized to capture. ScreenshotNeo accepts cookie and consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.
Sign up for 1,000 free screenshots per month, with no card required.
8. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| Screenshot is blank or shows a browser error | Navigation failed, the site is inaccessible, or a bot check prevented rendering. | Check the URL and network access, log the navigation error, and retry with a bounded policy. Do not silently publish a blank file. |
| Hero image or text is missing | Client rendering or lazy loading completed after the screenshot. | Wait for a relevant visible selector; use a short delay only as a fallback and keep a timeout. |
| Screenshot includes an unexpected dialog | A consent prompt, newsletter overlay, or chat widget appeared. | For self-hosted capture, identify whether the prompt can be handled consistently and capture under a documented policy. Do not bypass access controls. |
| Element screenshot times out | The selector is absent, hidden, or different on that theme. | Use a per-site selector map, verify visibility, and fall back to a viewport capture if the directory specification allows it. |
| Cards look inconsistent | Viewport, crop, scale, or focal point varies. | Fix those parameters and regenerate outliers; store the capture specification with the asset. |
| Uploaded file is rejected | File size, pixel count, dimensions, or format violates the destination’s requirements. | Resize or recompress, convert to an accepted format, and verify the exact Shopify destination’s limits. |
| Shopify image URL behaves unexpectedly | A filename suffix may be parsed as a transformation request, or a best-effort transform was ignored. | Use a neutral filename and inspect the final URL and returned image dimensions. |
9. Performance, reliability, and cost
Browser capture cost is mainly the compute and storage required to render and retain files. Fixed viewports and CSS-pixel scale keep outputs more predictable; device-pixel scale and full-page captures can create larger images. Limit concurrency to the resources available, use timeouts, and cache validated results so directory traffic does not trigger a new browser capture each time.
Reliability comes from treating each store as an independent job: capture, validate, then publish. Keep failures separate from successful images, retry transient failures sparingly, and leave the previous valid thumbnail in place until a replacement passes checks. Monitor file dimensions and bytes, not just whether the browser call returned.
ScreenshotNeo offers cache TTL control, bulk capture of up to 100 URLs per call, async jobs with signed webhooks, and a usage API. Its plans are Free: 1,000 shots per month; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; Business: $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan. Clean shots are billed; failed or unclean outcomes and cache hits are not. Review the current documentation for request parameters and response details before integrating.
10. Frequently asked questions
Should directory cards use a screenshot or the store’s logo?
Use a screenshot when the card should preview the storefront experience. Use a logo or product image when the listing’s purpose is identification or merchandise discovery.
Should every thumbnail show the same page?
Usually choose one page type, such as each store’s home page, for comparability. If some stores need a different page, document that rule and keep the crop and viewport consistent.
Does Shopify’s image transformation API screenshot storefronts?
No. It transforms Shopify-hosted image resources. Use a browser capture workflow for a rendered website preview.
Do India-based directories need a special screenshot size?
The reviewed Shopify and Playwright documentation does not establish an India-specific thumbnail size. Set dimensions from your directory’s card design and validate rights and obligations for your use case.


