You purged everything and it’s still the old page.
A service worker is a script the site installed on your visitor’s machine that answers requests before the network does. It is the one layer no server-side purge can reach, and no response header reveals it.
Not sure this is the layer? Paste your URL and the checker reads the headers for you.
Check my siteHow to tell it’s a service worker
Nothing in the response headers identifies one, so this is diagnosed in the browser, not with a checker. In Chrome open devtools on the affected machine and go to Application → Service Workers. If one is registered and you have purged every server-side cache without effect, this is your layer. source
In the console, navigator.serviceWorker.getRegistrations() lists every registration for the page. source
How to clear it
On your own machine
- Application → Service Workers → Unregister, then reload. Update performs a one-time update, Bypass for network forces the browser to the network, and Update on reload forces an update on every load while you debug. source
- Application → Clear storage unregisters service workers and clears all caches and storage in one click. source
- In code: unregistering is not enough on its own — the Cache API keeps its entries. Do both:
source source
const regs = await navigator.serviceWorker.getRegistrations(); for (const r of regs) await r.unregister(); for (const k of await caches.keys()) await caches.delete(k); location.reload();
For everyone else
You cannot reach your visitors’ machines, so ship a fix instead: publish a new service worker that cleans up on activate, or send the Clear-Site-Data header. Clear-Site-Data: "cache", "storage" tells the browser to drop the cache and all DOM storage, and the storage directive explicitly unregisters service worker registrations. The quotes are required, and the header only works over HTTPS. source
Why your new worker never installs: the 24-hour rule
This is the most common cause. The browser fetches the worker script to see whether it changed, but it only bypasses the HTTP cache if the previous fetch was more than 24 hours ago. source So a long max-age on sw.js means the browser keeps re-reading a cached copy of your old worker, and your new one never installs.
- Fix it two ways. Serve
sw.jswithCache-Control: no-cache, and register with{ updateViaCache: "none" }, which means the HTTP cache is never consulted for the worker script. The default,imports, skips the cache for the worker itself but still uses it for anything loaded withimportScripts(). source - A hard refresh doesn’t fix it because it reloads the page, not the registration: the old worker keeps controlling the page until it is replaced or unregistered.
Other fix guides
Sources
Every step above was written from these pages, read on 14 Sep 2026. Vendors move buttons; if one has moved, the source page will say where.