Why the Favicon Cache Is So Sticky
Browsers treat favicons differently from every other asset on your page. CSS files honor your Cache-Control headers. Images respect ETag validation. JavaScript bundles get fingerprinted by your build tool and naturally cache-bust on every deploy.
Favicons get none of that respect. Once a browser has a favicon for your origin, it stores it in a separate database — Chrome calls it the Favicons SQLite store, Firefox keeps it in favicons.sqlite, Safari files it inside WebpageIcons.db — and consults that store before it consults the network. The browser only refreshes the entry when one of three things happens:
- The user explicitly clears site data for your origin (basically nobody does this).
- The cached entry expires from the favicon database itself, which can take weeks or months depending on the browser.
- The HTML
<link rel="icon">tag points at a different URL than the one already cached.
That third condition is the entire fix. The reason your hard refresh did nothing is that hard refresh only invalidates the page cache, not the favicon cache. The browser still sees /favicon.ico in the head, and /favicon.ico is exactly what it has on file, so it never goes back to fetch it.
The only reliable way to force a favicon update for users who have already visited your site is to change the URL of the favicon itself.
The Four-Step Fix That Actually Works in 2026
Step 1 — Version the filename, not just the query string
The lazy fix is to append a query string: <link rel="icon" href="/favicon.ico?v=2">. This works in Chrome and Firefox. It does not work reliably in Safari on macOS or iOS, which strips the query string before keying its favicon cache. It also does not work for crawlers (Googlebot, GPTBot, Slack's link unfurler) which often request /favicon.ico directly with no query string at all.
The robust fix is to ship a new file path. Move from /favicon.ico to /favicon-v2.ico, or better, use a content hash: /favicon-a3f2.ico. Update your <link> tag to match. Every cache on earth will treat the new path as a fresh resource.
<!-- Before -->
<link rel="icon" href="/favicon.ico">
<!-- After -->
<link rel="icon" href="/favicon-a3f2.ico">
<link rel="icon" type="image/svg+xml" href="/icon-a3f2.svg">
<link rel="apple-touch-icon" href="/apple-touch-icon-a3f2.png">
Step 2 — Keep the old file in place for 30 days
Do not delete /favicon.ico the moment you ship the new path. Browsers, RSS readers, link previewers, and search engine indexes will keep requesting the old URL for weeks. If you 404 on those requests, some surfaces show a broken-image placeholder until they re-crawl your HTML.
Leave the old file at the old path for at least 30 days, ideally 90. The cost is a few KB on disk; the upside is no broken icons in Slack, Notion previews, or Google search results during the transition window.
Step 3 — Update every meta tag, not just the favicon
The <link rel="icon"> tag is one of about eight image references that surface as "your icon" in different contexts. If you only update one, the others go out of sync. Here is the full set to version in lockstep:
<link rel="icon" href="/favicon-a3f2.ico" sizes="32x32">
<link rel="icon" type="image/svg+xml" href="/icon-a3f2.svg">
<link rel="apple-touch-icon" href="/apple-touch-icon-a3f2.png">
<link rel="manifest" href="/manifest-a3f2.json">
<meta name="msapplication-TileImage" content="/mstile-a3f2.png">
<meta property="og:image" content="https://example.com/og-image-a3f2.png">
And inside manifest.json, make sure every icons[].src path also carries the same version suffix. This is the single most-missed step — the browser tab updates instantly, but the iOS home-screen icon stays stuck on the old design for a year because the manifest still points at the old PNGs.
Step 4 — Send a long Cache-Control header on the new file
Once you have versioned the path, you want aggressive caching. Set this on every favicon-related response from your CDN or origin server:
Cache-Control: public, max-age=31536000, immutable
One year, immutable. Because the URL changes whenever the contents change, the browser can hold the bytes forever and you will never have a staleness problem again. This is the same pattern Vercel, Netlify, and Cloudflare Pages use for hashed static assets — favicons should follow the same rule.
How to Test the Update Without Visiting Every Browser
Once your new favicon is deployed, you have three options for verifying that browsers are actually picking it up. Pick whichever fits the problem you are debugging.
Option A — A clean private window
Open an incognito or private window and visit the page. Private windows have no shared favicon cache with the regular browser profile, so they always render whichever favicon the HTML currently points at. If the new icon shows here but not in your normal tabs, the deploy is fine — your local profile is just holding the old entry.
Option B — Direct file fetch
Visit the favicon URL directly in the address bar: https://yoursite.com/favicon-a3f2.ico. If the file loads and shows the right design, the asset is on the CDN correctly and any "old icon" you see in tabs is purely a client-side cache problem.
Option C — RealFaviconChecker
Tools like RealFaviconGenerator's checker, or our own favicon generator validator, will fetch every favicon-related URL on your page (icon, apple-touch-icon, manifest entries, msapplication-TileImage) and report which ones resolve, what dimensions they actually serve, and whether the manifest paths line up. This is the cheapest way to spot a missed version bump in the manifest before it embarrasses you on iOS.
Generate a versioned favicon set in 30 seconds
Upload your logo or pick an emoji. Get a complete favicon bundle — ICO, SVG, all PNG sizes, apple-touch-icon, and a ready-to-paste manifest.json — with content-hashed filenames included. Free, no signup.
Try it free →Common Variants of "My Favicon Won't Update"
"It updated in Chrome but Safari is still wrong"
Safari ignores query strings on favicon URLs. If your fix was ?v=2, that is the cause. Move to a real path change (/favicon-v2.ico) and Safari will pick it up on the next page load — though existing pinned tabs on macOS may need to be unpinned and re-pinned once.
"The browser tab updated but Google still shows the old one in search results"
Google's favicon for search snippets is cached separately on Google's CDN and refreshes on its own crawl schedule, typically 1–4 weeks. There is no manual flush. Make sure your new file is reachable at every URL Google has indexed (don't 404 the old path), and the snippet will roll over on the next crawl. For deeper troubleshooting on the search-result side, see our companion piece on favicons not showing in Google search results.
"It works on desktop but the iOS home screen still has the old icon"
The home-screen icon is sourced from apple-touch-icon and the manifest, not from favicon.ico. If you only versioned the latter, iOS will keep serving the cached apple-touch-icon.png until the user removes and re-adds the home-screen shortcut. Version the apple-touch-icon path too, then ask testers to long-press → remove → re-add.
"The new favicon flashes for a second, then the browser switches back to the old one"
This is a build pipeline problem, not a cache problem. Something on your site (often a service worker, a stale CDN edge, or an A/B testing snippet) is racing the network response and serving an older HTML payload that still references the old favicon path. Open DevTools → Network and filter by "favicon" — if you see two different paths fetched on a single page load, you have a cache-versus-fresh-HTML race condition to chase down.
The TL;DR Checklist
- Change the favicon's URL path (not just a query string) every time the file contents change.
- Update every related tag in lockstep: icon, apple-touch-icon, manifest entries, msapplication-TileImage.
- Keep the old file at the old path for 30–90 days so crawlers and link previewers don't 404.
- Set
Cache-Control: public, max-age=31536000, immutableon the new versioned files. - Verify in an incognito window before assuming the deploy is broken.
Do these five things and you will never wonder again why your favicon update isn't sticking. The favicon cache is uniquely sticky on purpose — once you stop fighting it and start versioning around it, it becomes one of the most reliable parts of your site instead of one of the most frustrating.
Skip the manual export grind
Our free favicon generator outputs a complete set with version-friendly hashed filenames so cache-busting works on day one. ICO, SVG, all PNG sizes, apple-touch-icon, and manifest.json — bundled in a single ZIP.
Generate yours free →