Free tools Windows power users keep installed
One-click scans. No signup required.
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use three deliberately separated cache layers: preserve the browser’s own HTTP cache for safe, read-heavy resources; manage service-worker Cache Storage as application data; and add an agent cache for stable observations. Keep BrowserContext boundaries aligned with identity and tenant boundaries, put authentication and content revision in every key, and make misses, revalidation, and invalidation explicit. This avoids paying repeatedly for deterministic work without serving one user’s data to another.
The three caches an automation agent can encounter
“The cache” is not one mechanism. Each layer has a different owner and different invalidation behavior.
Browser HTTP cache
Chromium, Firefox, and WebKit maintain an HTTP cache for responses and assets. Servers control freshness with Cache-Control, ETag, and Last-Modified. When those headers are trustworthy, letting the browser reuse static JavaScript, stylesheets, fonts, and immutable API responses is the lowest-maintenance option because normal browser validation remains in charge.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Service-worker Cache Storage
A service worker can intercept requests and store responses in the Cache Storage API. Chrome’s Workbox documentation states that “The Cache interface is a caching mechanism entirely separate from the HTTP cache.” Application code chooses cache names, update rules, and deletion timing. A service worker can therefore return a deliberately stale response even when the HTTP cache would revalidate, or bypass the HTTP cache entirely.
#1 Best Overall
Playwright’s service-worker support is limited to Chromium-based browsers. Treat this layer as part of the site’s application behavior, not as a transparent extension of browser caching.
Agent-level response and observation cache
An AI agent can cache information above the browser: page schemas, navigation metadata, extracted tables, public API responses, or downloaded static assets. This cache is owned by your agent service, so it must carry scope and provenance that a browser cache does not expose to the planner. Return the cached value’s age, source URL, content revision, and whether it was served stale so the planner can decide whether to refresh.
Preserve the browser HTTP cache in Playwright
The most important Playwright behavior is easy to miss: its API reference says, verbatim, “Enabling routing disables http cache.” Calling browserContext.route() therefore changes the cache behavior of that context, even when the route matches only one endpoint. Routing also has special limitations around service-worker requests.
Use an unrouted context for normal work
Create a normal context and allow the browser to honor response headers. Reuse that context only for tasks that intentionally share its identity and cached state.
import { chromium } from 'playwright';
const browser = await chromium.launch();
const context = await browser.newContext(); // no routing: HTTP cache can operate
const page = await context.newPage();
await page.goto('https://example.com/catalog', { waitUntil: 'networkidle' });
const title = await page.title();
console.log(title);
await browser.close();
Do not add a catch-all route merely to log requests. If diagnostics, fixtures, request blocking, or response rewriting are required, create a separate diagnostic context and accept that HTTP caching is disabled there. Keep production capture and diagnostic interception from sharing the same context.
Trust headers selectively
Let normal caching handle immutable assets and responses with coherent validators. Be more conservative with endpoints that return account-specific, rapidly changing, or improperly cacheable data. A browser cache cannot correct a server that marks personalized content as public; identity isolation remains your responsibility.
Use service-worker Cache Storage deliberately
When a site installs a service worker, inspect its policy before deciding that a fast response proves the HTTP cache is working. Cache Storage is application-owned and commonly implements one of three patterns:
Rank #2
- Cache-first: return a stored response and update it later. This suits versioned static assets and offline shells.
- Network-first: try the network, then fall back to a stored response. This is safer for content that must be fresh when connectivity exists.
- Stale-while-revalidate: return the stored response immediately while refreshing it in the background. The agent must know that the observation is stale.
Version names and activation cleanup
Use versioned cache names such as catalog-v7 rather than silently changing the meaning of an existing name. During service-worker activation, delete old versions after the new worker is ready. MDN notes that cache lifetime is browser-dependent and that scripts are responsible for updates; do not assume the browser will evict an obsolete entry on your schedule.
Do not confuse a service-worker hit with a network hit
For debugging, log whether the service worker supplied the response, whether the response was revalidated, and which cache name was used. A page can show new HTML while still serving an old image or API response from a different layer.
Make BrowserContext an identity boundary
Playwright BrowserContexts are isolated, incognito-like profiles with separate cookies and storage. They are fast and cheap to create, but the decision to reuse one is a security and correctness decision as much as a performance decision.
Reuse when state sharing is intentional
A single context is appropriate for a sequence such as logging in once, visiting several pages for the same user, and reusing that user’s cookies and browser cache. It can avoid repeated authentication and warm static assets.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Create separate contexts for separate scopes
Use a new context for different tenants, user identities, experiments, or tests that must not observe one another. Never let a cache hit from one authentication or tenant scope satisfy another. Include the scope in the agent cache key even if each scope already has a separate BrowserContext; defense in depth catches configuration mistakes.
Be cautious with persistent profiles
A persisted profile can reduce login cost, but it also keeps credentials, storage, service-worker data, and cached responses longer. Stale credentials and cross-task contamination become more likely. Define a rotation or rebuild policy based on your risk, and discard a profile after authentication changes, tenant changes, or an isolation test failure.
Design an agent-level cache key
A useful key identifies both the request and the meaning of the result. At minimum, store:
Rank #3
- Canonical origin, URL, HTTP method, query string, and request body.
- Authentication or tenant scope, never a raw secret.
- Locale, timezone, geolocation, and relevant feature flags.
- Browser engine and application version when rendering can differ.
- Content revision, API version, or another explicit producer revision.
Hash the serialized structure for a compact storage key, but retain the structured fields as metadata for auditing and invalidation. Two URLs that differ only by tenant, locale, or an authorization scope are different resources.
Recommended Free Tools
Good candidates
- Public documentation pages and navigation metadata.
- Stable page schemas used by the planner to locate controls.
- Read-only catalog data with a known revision.
- Downloaded static assets whose URLs are content-addressed or versioned.
Keep these uncached or very short-lived
- Mutations and their results.
- CSRF tokens, login challenges, and one-time links.
- Payment flows, account balances, inventory, and permission checks.
- Any response whose freshness or confidentiality is security-sensitive.
Attach a timestamp, TTL, producer revision, and provenance to every entry. The planner can then choose a refresh rather than blindly trusting a value that merely exists.
Choose TTLs and refresh behavior by resource class
| Resource class | Default policy | Why |
|---|---|---|
| Versioned static assets | Long TTL or cache until URL revision changes | The URL identifies the content; browser validation is inexpensive. |
| Public, read-only metadata | Bounded TTL with revalidation | Fast planner decisions while limiting stale navigation. |
| Tenant-scoped reports | Short TTL; key includes tenant and authorization scope | Freshness and isolation matter more than maximum hit rate. |
| Balances, inventory, permissions | Network-first or no agent cache | A stale value can cause an unsafe action. |
| Mutations and security tokens | Do not cache | Replay and confidentiality risks outweigh latency savings. |
These are policy categories, not universal durations. Set numerical TTLs from the application’s freshness requirement and document who owns invalidation.
Handle misses, stale entries, and invalidation explicitly
- Namespace by version and scope. Include application or content revisions in the namespace so a deployment can invalidate a whole family without scanning every key.
- Check scope before lookup. Reject an entry whose authentication, tenant, locale, or browser version does not match the current task.
- Serve a valid hit with provenance. Return age, expiry, and source metadata to the planner.
- Fetch on a miss. Retrieve from the network and atomically replace the entry only after validation succeeds.
- Revalidate boundedly. If validation fails, discard the entry and retry once under a defined budget. Do not loop indefinitely while an agent is waiting.
- Record outcomes. Emit hit, miss, stale-use, revalidation, eviction, validation-failure, and cross-scope-denial events.
Atomic replacement prevents a failed or partial page load from poisoning a previously good value. Bounded retries give the agent a deterministic failure path instead of hiding outages behind repeated requests.
A small Playwright observation cache
The following Node.js example keeps a per-scope observation cache while leaving the browser HTTP cache enabled. In a production agent, replace the in-memory map with a process-safe store and encrypt or omit sensitive metadata.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsimport { chromium } from 'playwright';
import crypto from 'node:crypto';
const observations = new Map();
function makeKey({ origin, url, method, query, scope, locale, browserVersion, revision }) {
const value = JSON.stringify({ origin, url, method, query, scope, locale, browserVersion, revision });
return crypto.createHash('sha256').update(value).digest('hex');
}
async function readObservation(page, request) {
const key = makeKey(request);
const cached = observations.get(key);
const now = Date.now();
if (cached && cached.expiresAt > now && cached.scope === request.scope) {
return { ...cached.value, cache: 'hit', ageMs: now - cached.createdAt };
}
await page.goto(request.url, { waitUntil: 'networkidle' });
const value = { title: await page.title(), url: page.url() };
observations.set(key, {
value,
scope: request.scope,
createdAt: now,
expiresAt: now + request.ttlMs
});
return { ...value, cache: 'miss', ageMs: 0 };
}
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
const result = await readObservation(page, {
origin: 'https://example.com',
url: 'https://example.com/catalog',
method: 'GET',
query: '',
scope: 'public',
locale: 'en-US',
browserVersion: 'chromium',
revision: 'catalog-v7',
ttlMs: 60_000
});
console.log(result);
await browser.close();
For Python agents, the same boundary applies with async_playwright(): create one context per intentional identity, avoid context.route() in the cache-preserving context, and build the observation key from the same fields before reading or writing your store.
Measure more than hit rate
A cache that increases hits but leaks tenant data is a failure. Track these dimensions together:
Rank #4
| Metric | What it reveals |
|---|---|
| Hit rate and p50/p95 latency | Whether reuse actually improves agent responsiveness. |
| Bandwidth and origin request count | Whether browser and agent caches reduce upstream work. |
| Freshness-error rate | How often stale data causes a wrong decision or requires a retry. |
| Isolation leakage | Any cross-user, cross-tenant, or cross-locale response. |
| Invalidation effort | Operational cost of deployments and content changes. |
| Eviction and outage behavior | Whether a cold cache fails safely when the network is unavailable. |
A 2026 report, Internal APIs Are All You Need, measured 950 ms for fully warmed cached execution versus 3,404 ms for Playwright browser automation in a single-host benchmark covering 94 domains. It reported a 3.6× mean speedup and 5.4× median speedup. Those are workload-specific figures, not guarantees: your pages, network, browser version, and cache policy may produce very different results.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshooting cache problems
Every request appears to hit the network
Check whether the context has any route installed. Playwright disables HTTP cache when routing is enabled. Remove routing from the normal context or move interception to a separate diagnostic context. Also inspect response headers for Cache-Control: no-store or validators that force revalidation.
A service-worker response looks stale after deployment
Inspect the active worker and Cache Storage names. Increment the cache namespace, delete old versions during activation, and verify that the new worker controls the page. Do not assume clearing the HTTP cache removes Cache Storage entries.
One user sees another user’s result
Treat this as a security incident. Stop serving the affected namespace, invalidate entries, and audit keys for authentication and tenant scope. Verify that separate BrowserContexts are used and that persisted profiles are not being shared between tasks.
Cache hits return the wrong locale or feature variant
Add locale, timezone, geolocation, feature flags, and application revision to the key. If the server varies on a header, include the semantic value in the key rather than relying on a URL alone.
Cold starts are slow after eviction
Measure the browser cache, service-worker cache, and agent cache separately. Warm only deterministic, read-heavy resources, and use atomic replacement after a successful load. Do not “fix” cold starts by caching login challenges, CSRF tokens, or mutable account data.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Or skip the browser setup
If your task is to obtain a clean screenshot rather than operate a stateful browser session, ScreenshotNeo provides a single-request alternative. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
Use the documented API parameters and inspect the returned headers when deciding whether to reuse a result:
Best Value
curl -G 'https://api.screenshotneo.com/v1/shot'
-d access_key=YOUR_API_KEY
--data-urlencode url=https://stripe.com
-o shot.webp
See the ScreenshotNeo API documentation for output formats, caching controls, signed links, asynchronous jobs, and webhooks.
import requests
r = requests.get(
'https://api.screenshotneo.com/v1/shot',
params={'access_key': 'YOUR_API_KEY', 'url': 'https://stripe.com'},
timeout=90,
)
r.raise_for_status()
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 failed: ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', data));
ScreenshotNeo supports full-page and element captures, dark mode, device presets or custom viewports, retina scale, PDFs, custom CSS and JavaScript, click-before-capture actions, selector hiding, wait conditions, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.
Every feature is included on every plan: 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000 shots, with yearly billing giving two months free. Create a free ScreenshotNeo account to try the endpoint without a card.
Frequently Asked Questions
Should a cache key include the browser engine if the URL is identical?
Yes, when rendering or JavaScript behavior can differ. Keep engine and application version in the structured key so a Chromium observation cannot silently satisfy a task running with a different browser or revision.
How can I prove that two tenants cannot share cached observations?
Run the same read under two isolated BrowserContexts and distinct tenant scopes, then assert that each result contains only its own marker. Repeat after eviction and after a service-worker update; treat any cross-scope value as a failed isolation test.
What is the safest way to debug a suspected stale response?
Use a fresh diagnostic context, record service-worker and response-cache signals, and perform one network fetch with a bounded retry. Keep that context separate from the cache-preserving production context because adding Playwright routing disables HTTP cache.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

