React Favicon Not Showing? Here's the Fix
React renders into a DOM node and never touches the head, so the favicon lives in a static HTML file. A blank tab means that file's link tag is wrong, or the icon was imported from src and no longer sits at a fixed path.
The head is a static file, not a component
The browser requests the favicon while it parses the head, long before React has mounted. So the icon link has to be in the HTML shell: index.html at the project root under Vite, or public/index.html under Create React App.
Two things break it. In Create React App, a href that skips the %PUBLIC_URL% placeholder works locally and then 404s off the domain root. In any React project, importing the icon from src hands it to the bundler, which renames it with a content hash, so nothing answers at /favicon.ico anymore.
Track it down
- 1
Open /favicon.ico directly
A 404 means the file isn't being served at that path: a build or path problem. If it loads, the file is fine and the link tag or the cache is the issue.
- 2
Read the built index.html
Look in the build output, not your source. Confirm the icon href resolved to a real path and, for CRA, that %PUBLIC_URL% was substituted rather than left literal.
- 3
Stop importing the icon from src
Files in public/ keep their names and answer at fixed paths; imports from src/ are hashed. A favicon has to be in public/.
React favicon not showing: FAQ
Why is my React favicon not showing?
Almost always the link tag in index.html points somewhere the file isn't, or the icon was imported from src and got a hashed filename. Open /favicon.ico directly to see whether the file is even served at that path.
Why did my favicon 404 after I deployed to a sub-path?
The href resolved against the domain root instead of your subdirectory. In Vite set base in vite.config.js; in Create React App set the homepage field and use %PUBLIC_URL% in the template, then check the built index.html.
Do I need to import the favicon in my React code?
No. Files in public/ are copied to the build output as-is and aren't part of the module graph. Importing one produces a second, hashed copy and breaks the fixed /favicon.ico path.