Avoiding Duplicate Capture Costs: A Simple Client-Side Caching Pattern

Avoiding Duplicate Capture Costs: A Simple Client-Side Caching Pattern

author

Snapshot Site Team

09 Feb 2026 - 03 Mins read

It's easy for the same URL, with the same parameters, to get captured multiple times in a short window without anyone noticing — a support tool that re-captures a page every time someone opens a ticket referencing it, a dashboard widget that fires a fresh request on every page load, a retry that doesn't check whether the original request actually succeeded. None of this is a bug exactly. It's just requests happening without anything checking whether the same result already exists.

A small client-side cache, keyed by the request's actual parameters, fixes this without touching anything on the API side.

The Core Idea

Before making a request, compute a cache key from everything that affects the output — the URL, the format, the dimensions, and any other parameter that changes what gets rendered — and check whether a recent result for that exact key already exists before calling the API again.

const crypto = require("crypto");

function cacheKey(params) {
  const normalized = JSON.stringify(params, Object.keys(params).sort());
  return crypto.createHash("sha256").update(normalized).digest("hex");
}

async function cachedScreenshot(params, cache, ttlMs = 15 * 60 * 1000) {
  const key = cacheKey(params);
  const cached = cache.get(key);

  if (cached && Date.now() - cached.timestamp < ttlMs) {
    return cached.result;
  }

  const response = await fetch("https://api.prod.ss.snapshot-site.com/api/v1/screenshot", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-snapshotsiteapi-key": "YOUR_API_KEY",
    },
    body: JSON.stringify(params),
  });

  const result = await response.json();
  cache.set(key, { result, timestamp: Date.now() });
  return result;
}

Object.keys(params).sort() before stringifying matters — without it, the same parameters in a different object key order would hash to a different cache key and silently defeat the cache.

Picking a TTL

The right cache lifetime depends entirely on how often the underlying page actually changes and how fresh the result needs to be. A support tool showing "what does this page look like right now" probably wants a short TTL (minutes) or none at all. A dashboard widget showing a marketing page's current state can reasonably cache for longer (an hour or more) since that page rarely changes minute to minute. There's no universal right answer — the point is picking one deliberately instead of defaulting to zero caching by not thinking about it.

Where to Put the Cache

For a single service, an in-memory Map (as shown above) works fine and resets on restart, which is usually fine for this use case. For anything running across multiple instances or processes, a shared store (Redis, or a simple database table with a TTL column) keeps the cache effective across the whole fleet instead of each instance maintaining its own blind spot.

This Is Different From Retry Logic

Caching duplicate requests is a separate concern from retrying failed requests, covered in Rate Limits, Retries, and Batching — that post is about what to do when a request fails; this is about not sending an identical request that would have succeeded fine, twice, in a short window. Both patterns are worth having, and they don't overlap: a cache check happens before a request is sent at all, while retry logic only matters once one has already failed.

When Not to Cache

Anything explicitly checking "did this page change since I last looked" — a visual diff or uptime monitor — needs a fresh capture every time by design; caching would defeat the entire point of the check. This pattern is specifically for repeated requests asking the same question the request just answered a moment ago, not for monitoring workflows.

Cutting out duplicate requests that were never going to return a different answer is a small amount of client-side bookkeeping, and it's the kind of fix that pays for itself quietly, request after request, without Snapshot Site needing to know anything changed on your side at all.

Recent Articles

Subscribe to Snapshot Site API

Snapshot Site is a powerful API that allows you to capture full-page, high-resolution screenshots of any website with pixel-perfect accuracy.
Simply send a URL to the API to generate a complete snapshot — not just the visible area — covering entire web pages, scrolling content, landing pages, blogs, news articles, social media posts, videos, and more.
Designed for developers, designers, marketers, and journalists,
Snapshot Site makes it easy to integrate web page capture into your applications, workflows, and automation tools.

Subscribe Now
bg wave