N-Docs LogoN-Docs
Web Development

Browser Caching Issues

Understanding and fixing favicon and static asset caching problems

Why Does My Favicon Not Update? Understanding Browser Caching and How to Fix It

If you've deployed your React website and changed the favicon, but the old icon still shows up even after rebuilding and clearing your browser cache you're not alone. This is a very common issue caused by browser caching behavior and CDN/proxy caching layers (like Cloudflare). Here's what's going on and how to fix it.

What is a Favicon?

A favicon is the small icon displayed in browser tabs, bookmarks, and other UI elements. It is typically linked in your HTML with:

<link rel="icon" type="image/png" href="/favicon.png" />

Why Does the Old Favicon Persist?

1. Browser Cache

Browsers aggressively cache favicons to avoid fetching them repeatedly on every page load. Even private/incognito mode may use some caching, especially if the resource has strong caching headers.

2. CDN or Proxy Cache

If you use a CDN or reverse proxy (e.g., Cloudflare Tunnel, Cloudflare CDN), the icon might be cached on those servers, serving stale content to clients.

3. No Cache-Busting Strategy

If the favicon URL never changes (always /favicon.png), browsers and proxies see it as the same resource and serve the cached version.

How to Fix It

1. Use Cache Busting Query Parameters

Change the favicon link to include a version query parameter, which forces browsers and proxies to treat it as a new resource:

<link rel="icon" type="image/png" href="/favicon.png?v=2" />

When you update the favicon, increment the v number.

2. Set Proper Cache-Control Headers in Nginx

You want to cache static assets for performance, but sometimes it's better to set a reasonable max-age for favicons or disable caching temporarily during development.

Example in your nginx.conf:

location = /favicon.png {
    expires 1d; 
    add_header Cache-Control "public, max-age=86400";
}

Or to disable caching during development:

location = /favicon.png {
    expires -1;
    add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
}

3. Make Sure the Correct Favicon Is Served

  • Confirm your build process copies the favicon to the right folder (dist/ or /usr/share/nginx/html).
  • Check the file contents in your container or server to verify.
  • If you serve multiple favicon sizes/types, verify all are up to date.

4. Clear CDN Cache or Purge Proxy Cache

If you use Cloudflare or other CDNs:

  • Purge the cache for /favicon.png and /favicon.ico.
  • Temporarily disable caching for these files during debugging.

Summary

ProblemSolution
Browser caching old faviconAdd version query parameter (?v=2)
CDN/proxy cachingPurge CDN cache, or disable caching for favicon
Nginx serving stale faviconConfigure proper cache headers
Build process missing faviconEnsure favicon copied during build

Example Working Setup for React + Docker + Nginx

# Build stage
FROM node:18-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM nginx:stable-alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

nginx.conf snippet:

server {
    listen 80;
    root /usr/share/nginx/html;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    # Cache static assets aggressively
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, max-age=31536000";
    }

    # Cache favicon for 1 day only
    location = /favicon.png {
        expires 1d;
        add_header Cache-Control "public, max-age=86400";
    }

    location = /favicon.ico {
        expires 1d;
        add_header Cache-Control "public, max-age=86400";
    }

    # Disable caching for HTML to enable quick updates
    location ~* \.html$ {
        expires -1;
        add_header Cache-Control "no-store, no-cache, must-revalidate";
    }
}

And in your index.html:

<link rel="icon" type="image/png" href="/favicon.png?v=2" />

Final Notes

  • Always bump the query parameter version (?v=2, ?v=3…) when updating the favicon.
  • Use browser dev tools (Network tab) to verify favicon requests and headers.
  • Purge CDN caches after deployment to avoid stale content.
  • For multiple favicons (e.g., .ico, .png), update all and reference accordingly.