Why Does a Screenshot API Return an Outdated Cached Page?
A stale screenshot can come from the screenshot service, the target site's HTTP cache, or a capture taken before JavaScript finishes. Diagnose each layer and fix the one serving old content.
A screenshot API can return an outdated-looking page for three separate reasons: the screenshot service reused an older image, its browser received cached HTML or assets from the target site, or the capture happened before the page finished updating in JavaScript. A login redirect or error page can also look like stale content. Diagnose these layers separately; there is no universal cache-bypass parameter across screenshot APIs.
Start by checking the screenshot provider’s cache controls. Then inspect the target page’s responses and confirm the browser captured the expected URL, authenticated state, and rendered content. Changing the target site’s HTTP headers will not necessarily invalidate an image already cached by the screenshot service.
1. Identify which layer is stale
There may be several independent caches between your request and the pixels you receive:
- Your application or CDN: It may be serving an old screenshot file that your application saved or proxied.
- The screenshot API: It may return an earlier screenshot for the same URL and options.
- The rendering browser and target: The browser may reuse cached HTML, scripts, images, or API responses.
- The page itself: Client-side code, a service worker, or an application API may provide old data after the document loads.
- Capture timing or access: The browser may capture before updates finish, or may see a sign-in, error, or bot-check page instead.
Change one variable at a time. Keep the URL, viewport, cookies, headers, locale, and wait conditions fixed while comparing captures. Record the response time, final URL and status if the provider exposes them, and whether the output changes when you disable its screenshot cache.
2. Check the screenshot service’s own cache
Read the specific provider’s documentation for screenshot-result caching. Look for a cache enable/disable parameter, a time-to-live (TTL), stale-while-revalidate behavior, and details about which request options are part of the cache key. A provider may cache the rendered image independently of the target site’s HTTP cache.
For example, the separate Screenshot API service documents a cache option that defaults to true, a cacheTTL default of 86,400 seconds, and a staleTTL default of 43,200 seconds. Those values and parameter names belong to that service; do not assume another API uses them. See its documentation.
If your provider supports these exact controls, this example requests a fresh capture using cache=false. Do not copy that parameter to another provider unless its documentation defines it.
curl -G 'PROVIDER_SCREENSHOT_ENDPOINT' \
--data-urlencode 'url=https://example.com' \
--data-urlencode 'cache=false' \
-o fresh.png
import requests
response = requests.get(
"PROVIDER_SCREENSHOT_ENDPOINT",
params={"url": "https://example.com", "cache": "false"},
timeout=90,
)
response.raise_for_status()
with open("fresh.png", "wb") as image:
image.write(response.content)
const endpoint = new URL('PROVIDER_SCREENSHOT_ENDPOINT');
endpoint.searchParams.set('url', 'https://example.com');
endpoint.searchParams.set('cache', 'false');
const response = await fetch(endpoint);
if (!response.ok) throw new Error(`Screenshot request failed: ${response.status}`);
const image = new Uint8Array(await response.arrayBuffer());
await Bun.write('fresh.png', image);
Replace the placeholder endpoint with the provider’s documented URL. In Node.js environments without Bun, write the returned bytes using the runtime’s filesystem API. If the provider uses a POST body, a header, a different cache parameter, or no bypass control, use its documented request format instead. A unique query parameter on the target URL can help distinguish cache entries only if the provider includes the full URL in its cache key; it is not a reliable purge method.
3. Inspect target-site HTTP caching
Even when the screenshot service creates a new image, its browser can receive an older response or old assets from a browser cache, proxy, or CDN. Inspect the HTML document and the specific scripts, stylesheets, images, or API responses that carry the changed content. Check Cache-Control, ETag, Last-Modified, Age, and any CDN-specific cache status headers available to you.
Cache-Control: no-cache means a stored response must be revalidated before reuse; it does not mean “never store.” no-store is the directive intended to prevent compliant caches from storing a response. Neither directive is a command to purge copies already stored in every intermediary. Validators such as ETag and Last-Modified let a cache ask whether a representation changed; an unchanged resource can be revalidated with a 304 Not Modified response. See MDN’s guides to HTTP caching and the Cache-Control header.
If you control the site, choose policy according to the resource:
- For HTML that should be checked for changes on reuse, use a revalidation policy such as
Cache-Control: no-cacheand supply correct validators. - For sensitive or personalized responses, review whether shared caches should store them; a private policy may be appropriate. Do not expose personalized content through a shared cache.
- For immutable, versioned assets, use a new URL when the content changes. Hashed filenames let those assets be cached for a long time without reusing the old version under the same URL.
- For content behind a CDN, check its cache rules and purge or revalidate the relevant object there when needed. Origin headers alone may not undo an existing CDN entry.
4. Do not confuse browser Fetch caching with screenshot API settings
JavaScript’s Fetch API has a cache option, but it controls that Fetch request in the browser making it. It does not automatically set the cache policy of a remote screenshot service’s rendering browser, nor does it invalidate that service’s cached screenshot. MDN documents the Fetch request cache modes.
// In your own page's JavaScript, not a screenshot API cache-bypass parameter:
const response = await fetch('/api/current-data', { cache: 'no-store' });
const data = await response.json();
Use no-store when that browser request should neither read from nor update its HTTP cache; use no-cache when a matching stored response should be revalidated. These settings only affect requests made by code you control. A screenshot provider must expose its own browser-cache controls if you need to configure its renderer this way.
5. Wait for the page’s actual update
A document’s load event does not guarantee that a single-page app has finished hydration, fetched current data, or rendered the section you need. Choose a wait condition based on the page’s behavior:
- Wait for a selector: Best when the desired content has a stable element that appears after rendering.
- Wait for a known state: Best when an element exists early but changes after data arrives; where supported, wait for its text or another state condition.
- Wait for network idle: Useful for pages that settle after requests finish, but analytics, polling, and long-lived connections can prevent a quiet network.
- Use a short delay: A fallback for known delayed changes when the API lacks a state-based wait. It adds latency and can still be too short or longer than necessary.
Screenshot providers expose different controls. For instance, Cloudflare’s screenshot API documents navigation waitUntil options and a selector wait; those are Cloudflare-specific. Consult its API reference and your own provider’s documentation for the available syntax.
Also inspect the page’s own data path. If a new screenshot still shows old content after the document and its assets are fresh, the page may be rendering stale API data or a service-worker cache. Those behaviors depend on the site’s implementation; inspect the relevant requests and service-worker rules rather than assuming the screenshot API is at fault.
6. Verify redirects, cookies, and authorization
A screenshot of a login page, access-denied screen, or bot check can be mistaken for a stale copy. Check the final URL and document status after redirects if your provider reports them. Compare a request with the required session cookies or authorization headers to one without them. Ensure any credentials are supplied through the provider’s supported secure mechanism and are scoped only as needed.
Also keep the capture context consistent: viewport, user agent, locale, timezone, geolocation, and cookies can change which version a site serves. If a page varies by these inputs, confirm the screenshot cache distinguishes them or disable that cache while diagnosing.
7. Troubleshooting checklist
| Symptom | Likely cause | What to do |
|---|---|---|
| Repeated requests return identical pixels immediately after a site update | Screenshot service cache hit | Use the provider’s documented cache bypass or lower TTL, then compare the result. Verify how its cache key is defined. |
| A fresh capture is still old, but direct browsing looks current | Renderer HTTP cache, CDN, or different request context | Inspect document and asset headers; compare final URL, cookies, user agent, viewport, and locale. Check CDN cache behavior. |
| The page shell is current but one data section is old | Stale API response, client cache, or service worker | Identify the network request feeding that section. Inspect its response and the page’s cache/service-worker behavior. |
| Only dynamic content is missing | Capture occurred before hydration or data loading | Wait for a stable selector or page state; use network idle or a measured delay only when appropriate. |
| The screenshot shows sign-in or access denied | Missing/expired cookie, authorization, redirect, or bot check | Inspect final URL/status and provide valid session context using the provider’s supported options. |
Adding Cache-Control: no-cache did not change the image |
That header governs HTTP response reuse, not necessarily screenshot-result storage | Configure the screenshot API’s cache separately; revalidate or purge relevant target/CDN responses where you control them. |
| A supposed bypass parameter has no effect | Parameter name is unsupported, misspelled, or sent in the wrong location | Check the exact provider API schema and whether it expects query parameters, JSON, or headers. |
| Disabling caching causes timeouts or much slower responses | Every request now needs a browser render and the page may be slow or unstable | Set an appropriate timeout and wait condition, reduce unnecessary page work if supported, and cache results in your application when acceptable. |
8. Performance, reliability, and cost
A screenshot cache can reduce repeated rendering work and speed up repeated requests, but it trades freshness for reuse. Bypassing it means the provider must navigate and render again, which can increase latency and make results more exposed to target-site load failures. The exact impact depends on the provider and page; there is no universal benchmark.
For mostly static pages, a longer screenshot TTL may be suitable. For pages that change frequently, shorten it or request fresh captures where supported. If the page changes at a known deployment boundary, invalidate or version the relevant result if the provider offers that mechanism. Cache keys should account for inputs that alter the rendered page, such as viewport, cookies, and headers; verify this in the provider’s documentation.
When serving screenshots from your own application, consider caching the resulting image under a key that includes the meaningful capture inputs and a version or freshness policy. Avoid sharing authenticated screenshots between users. Retry transient timeouts with a bounded retry policy and avoid retrying permanent errors such as invalid input or authorization failures. Do not interpret a successful image response alone as proof that the intended page loaded; use status or page metadata when available.
9. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. Its API supports configurable caching and returns page-verdict and billing headers so you can tell whether a capture was clean, a cache hit, or an unsuccessful page. The parameters other screenshot APIs use also work, which can make switching easier. 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}`);
const image = new Uint8Array(await res.arrayBuffer());
// Save image using your Node.js filesystem workflow.
ScreenshotNeo accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.
Sign up free for 1,000 screenshots a month, with no card required.
FAQ
Does a unique query string always force a fresh screenshot?
No. It only helps if the screenshot service includes that part of the URL in its cache key, and it may also change how the target site responds.
Can I tell from the image file whether it came from cache?
Usually not from the pixels alone. Check provider response headers or metadata, if available, and compare a documented fresh-capture request.
Should I use a long fixed delay to solve stale screenshots?
Only if you have measured that the page needs that time. A selector or state-based wait is generally more precise; long delays add cost in time and can still miss later updates.
Sources
- Screenshot API documentation for that provider’s cache options and defaults.
- MDN HTTP caching guide and Cache-Control reference.
- MDN Fetch request cache modes.
- Cloudflare screenshot API reference for Cloudflare’s wait controls.


