Menu
cachingperformancetutorial

Screenshot API Caching: How It Works and How to Use It

SnapSharp Team·April 15, 2026·6 min read

Screenshot generation is expensive — a full browser render takes 500ms to 3 seconds depending on the page. Caching is what makes it feel instant on repeat requests and keeps your bill reasonable.

This guide explains how SnapSharp's built-in cache works, how to control it, and when to bypass it.

How the cache works

SnapSharp caches screenshot results in Redis. The cache key is a hash of all request parameters — URL, width, height, format, dark mode flag, and every other option. If any parameter changes, it's a cache miss.

When you get a cached response:

  • Response time drops to under 50ms (serving from Redis)
  • The X-Cache: HIT header is set on the response
  • No browser is launched — zero Chromium cost

Cache misses (X-Cache: MISS) trigger a full browser render.

Default TTL

By default, cached screenshots expire after 1 hour (3600 seconds). After that, the next request triggers a fresh render and the cache is repopulated.

Controlling cache TTL

Pass cache_ttl to set a custom expiry:

# Cache for 24 hours (86400 seconds)
curl "https://api.snapsharp.dev/v1/screenshot?url=https://example.com&cache_ttl=86400" \
  -H "Authorization: Bearer $SNAPSHARP_API_KEY" \
  --output screenshot.png
// Node.js — cache for 6 hours
const img = await snap.screenshot('https://example.com', {
  cache_ttl: 21600,
});
# Python — cache for 30 minutes
image = snap.screenshot('https://example.com', cache_ttl=1800)

The maximum supported TTL is 86400 seconds (24 hours).

Disabling the cache

For monitoring jobs, CI pipelines, or any time you need fresh data, bypass the cache entirely:

curl "https://api.snapsharp.dev/v1/screenshot?url=https://example.com&cache=false" \
  -H "Authorization: Bearer $SNAPSHARP_API_KEY" \
  --output screenshot.png
# Always fresh — never cached
image = snap.screenshot('https://example.com', cache=False)

cache=false forces a fresh render every time and does not write the result back to cache. Use this for:

  • Visual monitoring — you need to detect changes, stale data defeats the purpose
  • CI/CD pipelines — capturing the live state after a deploy
  • User-triggered screenshots — when the user expects the result to reflect the page right now

Reading cache headers

Every response includes cache state in headers:

X-Cache: HIT         # Served from cache
X-Cache: MISS        # Fresh render
X-Response-Time: 48ms
X-Request-Id: 550e8400-e29b-41d4-a716-446655440000

You can inspect these in curl:

curl -I "https://api.snapsharp.dev/v1/screenshot?url=https://example.com" \
  -H "Authorization: Bearer $SNAPSHARP_API_KEY"

In code:

const response = await fetch(
  `https://api.snapsharp.dev/v1/screenshot?url=https://example.com`,
  { headers: { Authorization: `Bearer ${apiKey}` } }
);

console.log(response.headers.get('X-Cache'));          // HIT or MISS
console.log(response.headers.get('X-Response-Time'));  // e.g. "48ms"

Cache strategy patterns

Pattern 1: Long TTL for static pages

Marketing pages, docs, and landing pages rarely change. Cache for 12-24 hours:

screenshot('https://yourapp.com', cache_ttl=86400)        # Homepage
screenshot('https://yourapp.com/pricing', cache_ttl=86400) # Pricing
screenshot('https://yourapp.com/docs', cache_ttl=43200)    # Docs (12h)

Pattern 2: Short TTL for dynamic content

Dashboards, feeds, and user-generated content change frequently. Use 5-30 minute TTLs:

// Product page — changes when inventory updates
snap.screenshot(`https://shop.com/products/${id}`, { cache_ttl: 300 });

// News article — fresh for 30 minutes
snap.screenshot(articleUrl, { cache_ttl: 1800 });

Pattern 3: Disable cache for monitoring

# monitoring.py — runs every 5 minutes via cron
def check_all_sites():
    for site in MONITORED_SITES:
        image = snap.screenshot(site.url, cache=False)
        compare_with_baseline(site, image)

Pattern 4: Warm the cache on deploy

After deploying, pre-render your key pages so the first real user gets a cache hit:

#!/bin/bash
# scripts/warm-screenshots.sh

PAGES=(
  "https://yourapp.com"
  "https://yourapp.com/pricing"
  "https://yourapp.com/docs"
  "https://yourapp.com/blog"
)

for page in "${PAGES[@]}"; do
  curl -s -o /dev/null \
    "https://api.snapsharp.dev/v1/screenshot?url=${page}&cache_ttl=86400" \
    -H "Authorization: Bearer $SNAPSHARP_API_KEY"
  echo "Warmed: $page"
done

Add to your deploy script after health check passes.

Cache and cost

Cached requests count against your monthly quota but at reduced cost because no browser was launched — the request is pure Redis overhead. In practice, a healthy cache hit rate (>60%) cuts your effective render cost significantly.

You can see your cache hit rate on the Usage page:

  • Cache Hit Rate stat card shows the percentage of requests served from cache
  • The breakdown chart shows hits vs misses over time

If your cache hit rate is low:

  • Check that repeat requests use identical parameters (URL, dimensions, options)
  • Increase cache_ttl if the target pages don't change often
  • Avoid appending random query strings to URLs (each unique URL is a cache miss)

Cache invalidation

SnapSharp does not support manual cache invalidation by URL. If a page changes and you need fresh screenshots immediately, use cache=false on your next request — this bypasses the cache and renders fresh, but does not write back to cache either. The old cached version expires naturally at its TTL.

For use cases where you need deterministic freshness (e.g. after publishing a page), build a cache-bypass trigger into your CMS or deploy workflow.

Summary

ScenarioSetting
Marketing pages (rarely change)cache_ttl=86400
Blog postscache_ttl=43200
Product pagescache_ttl=1800
Dashboardscache_ttl=300
Visual monitoringcache=false
Post-deploy CI capturecache=false
Cache warm-up after deploycache_ttl=86400 (explicit warm request)

Related: Screenshot API docs · Usage dashboard · Visual regression testing

Screenshot API Caching: How It Works and How to Use It — SnapSharp Blog