How to Add a Favicon to Your HTML Page
The favicon is the small icon in the browser tab, the bookmarks bar, and the home screen when someone saves your site to their phone. Without one you get a blank document glyph, which reads as unfinished. Adding one is a few lines — but the modern advice is different from the advice you'll find in older tutorials, and if your host serves only one file it's different again.
What browsers actually look for
Every browser requests /favicon.ico automatically, even if you never mention it. That's why an old site with no favicon markup can still show an icon, and why your server log has 404s for a file you never referenced.
Relying on that alone is a mistake, though — it gives you one small bitmap and no control over the high-resolution and mobile cases. Declaring the icons explicitly is better, and it's short.
The modern three-line setup
You no longer need the dozen tags older guides recommend. This covers effectively everything:
<link rel="icon" href="/favicon.ico" sizes="32x32">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
What each does:
- favicon.ico — the fallback for older browsers, and the file browsers request by default.
- icon.svg — a vector icon, so it's sharp at every size. Modern browsers prefer it. It can also adapt to dark mode (see below).
- apple-touch-icon.png — 180×180, used when someone adds your site to an iOS home screen. Without it iOS renders a screenshot of your page, which looks bad.
Doing it when your host serves one file
Here's the case tutorials never cover. On a single-file host like hdply, there is no /favicon.ico to upload — your site is index.html. Two ways around it, both entirely inside the HTML.
An emoji favicon (fastest thing that works)
An SVG can contain text, and text can be an emoji, and the whole SVG can live in the href:
<link rel="icon" href="data:image/svg+xml,
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>
<text y='.9em' font-size='90'>🚀</text>
</svg>">
Keep it on one line in your actual file. Note the single quotes inside the SVG — the attribute is already using double quotes.
A real icon as a data URI
For a designed mark rather than an emoji, base64-encode a small PNG and inline it. Keep it genuinely small — this is a 32×32 image, so a few kilobytes:
<link rel="icon" type="image/png"
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...">
To produce the string: base64 -i icon.png on macOS or Linux, or any online converter for a one-off. A vector version works the same way and stays sharp:
<link rel="icon" href="data:image/svg+xml,
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'>
<rect width='32' height='32' rx='7' fill='%230b5cff'/>
<text x='16' y='23' font-size='19' font-family='sans-serif'
font-weight='700' fill='white' text-anchor='middle'>M</text>
</svg>">
One encoding rule to remember: inside a data URI, # must be written %23, which is why the colour above reads %230b5cff. Forgetting it is the usual reason an inline SVG icon silently fails.
Making one from scratch
If you have no icon at all, in rough order of effort:
- An emoji — thirty seconds, using the snippet above. Perfectly respectable for a personal page.
- A letter mark — your initial on a coloured rounded square, as in the SVG above. Edit the letter and colour and you're done.
- A generator — favicon.io and RealFaviconGenerator turn text, an emoji or an image into a full icon set.
- A designed mark — draw at 32×32 or scale down something simple. Detail disappears at this size; two shapes and one colour is the realistic budget.
What sizes do you actually need?
Older guides list a dozen files for devices that no longer ship. The current, realistic set:
| File | Size | Used by | Skippable? |
|---|---|---|---|
| favicon.ico | 32×32 | Browser default request, older browsers | No |
| icon.svg | Vector | Modern browsers, any resolution | No |
| apple-touch-icon.png | 180×180 | iOS home screen | Only if nobody saves your site |
| icon-192.png / icon-512.png | 192, 512 | Android home screen, PWA install | Yes, unless you ship a manifest |
Two extras worth a line each. A theme-color tints the browser UI on mobile, which makes a page feel considered rather than default:
<meta name="theme-color" content="#0b5cff">
And if you want the site installable to a home screen with a proper name and icon, that needs a web app manifest — a second file, which a single-file host can't serve. It's the one favicon-adjacent feature you genuinely can't inline, so treat it as a reason to use a multi-file host rather than something to work around.
Dark mode
An SVG favicon can respond to the browser's theme, which a bitmap can't:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<style>
circle { fill: #111; }
@media (prefers-color-scheme: dark) { circle { fill: #fff; } }
</style>
<circle cx="16" cy="16" r="14"/>
</svg>
Worth doing if your icon is a dark shape that would vanish against a dark tab bar.
Why isn't my favicon showing?
Almost always one of these:
- Cached. Browsers cache favicons aggressively and ignore a normal refresh. Hard-reload, or open the icon URL directly to confirm it exists.
- Wrong path.
href="favicon.ico"resolves relative to the current page;href="/favicon.ico"is anchored to the site root. Prefer the leading slash. - The file isn't there. On a single-file host it can't be. Use the inline approach above.
- Broken data URI. Check for an unescaped
#, and for double quotes inside an attribute already delimited by double quotes. - Tag outside the head. The
<link>must be inside<head>.
Related: The meta tags every page should have · Make your link look good when shared