If you run an e-commerce business, you already know the pain: hundreds of product pages to keep track of, competitor sites that change prices overnight, and a constant need for visual assets across marketing channels. Manually screenshotting all of this is not realistic.
A website screenshot API lets you automate all of it. In this guide, we will walk through practical use cases for e-commerce teams and build working examples you can deploy today.
Before diving into code, here are the scenarios where a screenshot API pays for itself:
Let's start simple. Here is how to capture a website screenshot of any product page using the GrabShot API:
curl "https://grabshot.dev/api/screenshot?url=https://example-store.com/products/widget-pro&width=1440&height=900&format=png" \
-H "X-Api-Key: YOUR_API_KEY" \
--output product-screenshot.png
const fs = require('fs');
async function captureProductPage(productUrl, outputPath) {
const params = new URLSearchParams({
url: productUrl,
width: '1440',
height: '900',
format: 'png',
full_page: 'false'
});
const response = await fetch(
`https://grabshot.dev/api/screenshot?${params}`,
{ headers: { 'X-Api-Key': process.env.GRABSHOT_KEY } }
);
if (!response.ok) throw new Error(`API error: ${response.status}`);
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync(outputPath, buffer);
console.log(`Saved: ${outputPath}`);
}
// Capture a single product page
captureProductPage(
'https://example-store.com/products/widget-pro',
'./screenshots/widget-pro.png'
);
import requests
import os
def capture_product_page(product_url, output_path):
response = requests.get(
"https://grabshot.dev/api/screenshot",
params={
"url": product_url,
"width": 1440,
"height": 900,
"format": "png",
"full_page": "false"
},
headers={"X-Api-Key": os.environ["GRABSHOT_KEY"]}
)
response.raise_for_status()
with open(output_path, "wb") as f:
f.write(response.content)
print(f"Saved: {output_path}")
capture_product_page(
"https://example-store.com/products/widget-pro",
"./screenshots/widget-pro.png"
)
Most stores have hundreds or thousands of product pages. Here is a Node.js script that reads a list of product URLs and captures them all, with built-in rate limiting to stay within API quotas:
const fs = require('fs');
const path = require('path');
const PRODUCTS = [
{ slug: 'widget-pro', url: 'https://store.com/products/widget-pro' },
{ slug: 'gadget-xl', url: 'https://store.com/products/gadget-xl' },
{ slug: 'sensor-mini', url: 'https://store.com/products/sensor-mini' },
// ... load from your database or CSV
];
async function captureAll(products) {
const outputDir = './catalog-screenshots';
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
for (const product of products) {
const params = new URLSearchParams({
url: product.url,
width: '1440',
height: '900',
format: 'webp', // smaller file size for catalogs
quality: '85'
});
try {
const res = await fetch(
`https://grabshot.dev/api/screenshot?${params}`,
{ headers: { 'X-Api-Key': process.env.GRABSHOT_KEY } }
);
if (res.ok) {
const buffer = Buffer.from(await res.arrayBuffer());
const filename = `${product.slug}-${Date.now()}.webp`;
fs.writeFileSync(path.join(outputDir, filename), buffer);
console.log(`✓ ${product.slug}`);
} else {
console.error(`✗ ${product.slug}: ${res.status}`);
}
} catch (err) {
console.error(`✗ ${product.slug}: ${err.message}`);
}
// Rate limit: wait 1 second between requests
await new Promise(r => setTimeout(r, 1000));
}
}
captureAll(PRODUCTS);
For larger catalogs, consider using the webp format with quality set to 80-85. This cuts file sizes by 30-50% compared to PNG with minimal visible difference, which matters when you are storing thousands of images.
This is where screenshot automation gets really powerful for e-commerce. Instead of manually checking competitor sites, set up a daily job that captures their product pages and stores them for comparison.
import requests
import os
from datetime import datetime
COMPETITORS = [
{"name": "competitor-a", "products": [
{"slug": "similar-widget", "url": "https://competitor-a.com/widget"},
{"slug": "pro-gadget", "url": "https://competitor-a.com/pro-gadget"},
]},
{"name": "competitor-b", "products": [
{"slug": "widget-deluxe", "url": "https://competitor-b.com/widget-deluxe"},
]},
]
def monitor_competitors():
today = datetime.now().strftime("%Y-%m-%d")
for competitor in COMPETITORS:
output_dir = f"./competitor-snapshots/{competitor['name']}/{today}"
os.makedirs(output_dir, exist_ok=True)
for product in competitor["products"]:
response = requests.get(
"https://grabshot.dev/api/screenshot",
params={
"url": product["url"],
"width": 1440,
"height": 1200,
"format": "png",
"full_page": "true", # capture the entire page
"delay": 3000 # wait for dynamic content
},
headers={"X-Api-Key": os.environ["GRABSHOT_KEY"]}
)
if response.status_code == 200:
filepath = f"{output_dir}/{product['slug']}.png"
with open(filepath, "wb") as f:
f.write(response.content)
print(f"✓ {competitor['name']}/{product['slug']}")
monitor_competitors()
Run this as a daily cron job and you will build a visual history of competitor pricing and layouts. Pair it with an image diffing tool (like visual regression testing) to get automatic alerts when a competitor changes their pricing or page layout.
More than 60% of e-commerce traffic comes from mobile. After every deployment, you should verify that product pages look correct on phone-sized viewports:
curl "https://grabshot.dev/api/screenshot?url=https://your-store.com/products/bestseller&width=390&height=844&format=png&device=mobile" \
-H "X-Api-Key: YOUR_API_KEY" \
--output mobile-check.png
You can extend this to test multiple viewport sizes (375px for iPhone SE, 390px for iPhone 14, 412px for Pixel, 768px for iPad) and flag any pages where content overflows or buttons are cut off. See our full page screenshot guide for more details on viewport configuration.
Need a quick product image for an Instagram ad or email newsletter? Instead of manually cropping screenshots, use the API with specific dimensions:
// Generate OG-image-sized screenshots for social sharing
async function generateSocialAsset(productUrl) {
const configs = [
{ name: 'og-image', width: 1200, height: 630 }, // Open Graph
{ name: 'twitter-card', width: 1200, height: 600 }, // Twitter/X
{ name: 'instagram', width: 1080, height: 1080 }, // Instagram square
{ name: 'email-banner', width: 600, height: 300 }, // Email header
];
for (const config of configs) {
const params = new URLSearchParams({
url: productUrl,
width: String(config.width),
height: String(config.height),
format: 'png'
});
const res = await fetch(
`https://grabshot.dev/api/screenshot?${params}`,
{ headers: { 'X-Api-Key': process.env.GRABSHOT_KEY } }
);
if (res.ok) {
const buffer = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync(`./social/${config.name}.png`, buffer);
}
}
}
generateSocialAsset('https://your-store.com/products/summer-sale');
This is especially useful if you need to generate assets for dozens of products during a seasonal sale. For more advanced OG image generation, check out our guide on automated OG images.
If you sell on Amazon, eBay, Etsy, or other marketplaces, you know that listings can sometimes display incorrectly: wrong images, broken formatting, or missing descriptions. Schedule a weekly screenshot of your marketplace listings to catch issues before customers do:
LISTINGS = [
"https://amazon.com/dp/B0EXAMPLE1",
"https://ebay.com/itm/123456789",
"https://etsy.com/listing/987654321",
]
for url in LISTINGS:
response = requests.get(
"https://grabshot.dev/api/screenshot",
params={"url": url, "width": 1440, "height": 900, "format": "png", "delay": 3000},
headers={"X-Api-Key": os.environ["GRABSHOT_KEY"]}
)
# save and review...
The delay parameter is important here since marketplace pages often load content dynamically. A 3-second delay ensures all product images and pricing data are rendered before the screenshot is taken.
GrabShot gives you 25 free screenshots per month. No credit card required.
Try It Free →Here is a practical setup that combines everything above into a single daily workflow:
All of this can run on a single server with cron jobs and the GrabShot API. No headless browser infrastructure to maintain, no Puppeteer memory leaks to debug, no Chrome version conflicts to resolve.
| Factor | Self-Hosted Puppeteer | GrabShot API |
|---|---|---|
| Server cost | $20-100/mo (needs 2-4GB RAM) | $0-29/mo |
| Setup time | Hours to days | Minutes |
| Maintenance | Chrome updates, memory leaks, crashes | None |
| Scaling | Add servers manually | Automatic |
| Reliability | You handle restarts | 99.9% uptime |
For most e-commerce teams, the API approach wins on both cost and time. You can read a more detailed breakdown in our Puppeteer vs. API comparison.
Ready to automate your e-commerce screenshot workflow?
For the full API reference including all parameters, check the GrabShot documentation.