X Xerobit

How to Add a Favicon to Your Website — Complete Guide

Adding a favicon requires placing the icon file and linking it in HTML. Here's how to add favicons for all browsers, frameworks, and contexts including Apple touch icons and...

Mian Ali Khalid · · 5 min read
Use the tool
Favicon Generator
Generate favicon package from any image or emoji. Multiple sizes (16, 32, 48, 180, 192, 512), manifest.json, and HTML snippet.
Open Favicon Generator →

Adding a favicon to your website takes two steps: create the icon file and add the <link> tag to your HTML <head>. Getting it right for all browsers and contexts requires a few more files and tags, but the process is straightforward.

Use the Favicon Generator to create all the icon sizes you need from a single source image.

Minimum viable favicon

For most modern browsers, this is enough:

<head>
  <link rel="icon" href="/favicon.ico">
</head>

Place favicon.ico at the root of your site (/favicon.ico). Browsers request this URL automatically even without the <link> tag, but including the tag ensures it loads in all cases.

Complete multi-format setup

For full cross-browser and cross-context support:

<head>
  <!-- Primary favicon: SVG for modern browsers (scales to any size) -->
  <link rel="icon" href="/favicon.svg" type="image/svg+xml">
  
  <!-- Fallback: ICO for older browsers and edge cases -->
  <link rel="icon" href="/favicon.ico" sizes="any">
  
  <!-- Apple devices: home screen icon (no transparency on older iOS) -->
  <link rel="apple-touch-icon" href="/apple-touch-icon.png">
  
  <!-- Android/Chrome: web app manifest for home screen icons -->
  <link rel="manifest" href="/site.webmanifest">
</head>

Files you need:

  • favicon.svg — vector icon (scalable, ~1KB)
  • favicon.ico — multi-size container (16×16, 32×32, 48×48)
  • apple-touch-icon.png — 180×180 PNG for iOS
  • site.webmanifest — JSON config for Android icons

File placement

For static sites:

public/
  favicon.ico
  favicon.svg
  apple-touch-icon.png
  site.webmanifest
  favicon-192.png   (referenced by manifest)
  favicon-512.png   (referenced by manifest)

The ICO file must live at /favicon.ico — the domain root, not a subfolder. Browsers hard-code this lookup.

The web manifest file

{
  "name": "Your Site Name",
  "short_name": "Site",
  "icons": [
    {
      "src": "/favicon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/favicon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "theme_color": "#ffffff",
  "background_color": "#ffffff",
  "display": "standalone"
}

The manifest powers Android “Add to Home Screen” and Progressive Web App (PWA) installation.

Framework-specific setup

React / Vite

<!-- index.html (in project root) -->
<!DOCTYPE html>
<html>
  <head>
    <link rel="icon" href="/favicon.ico" sizes="any">
    <link rel="icon" href="/favicon.svg" type="image/svg+xml">
    <link rel="apple-touch-icon" href="/apple-touch-icon.png">
    <link rel="manifest" href="/site.webmanifest">
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

Place all icon files in the public/ directory.

Next.js (Pages Router)

<!-- pages/_document.tsx or _document.js -->
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head>
        <link rel="icon" href="/favicon.ico" sizes="any" />
        <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
        <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
        <link rel="manifest" href="/site.webmanifest" />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

Next.js (App Router)

// app/layout.tsx
export const metadata = {
  title: 'Your Site',
  icons: {
    icon: [
      { url: '/favicon.ico', sizes: 'any' },
      { url: '/favicon.svg', type: 'image/svg+xml' },
    ],
    apple: '/apple-touch-icon.png',
  },
  manifest: '/site.webmanifest',
};

export default function RootLayout({ children }) {
  return (
    <html>
      <body>{children}</body>
    </html>
  );
}

Next.js App Router generates the correct <link> tags from the metadata object.

Astro

<!-- src/layouts/Layout.astro -->
---
const { title } = Astro.props;
---
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" sizes="any" />
    <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
    <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
    <link rel="manifest" href="/site.webmanifest" />
    <title>{title}</title>
  </head>
  <body>
    <slot />
  </body>
</html>

WordPress

<!-- functions.php add to your theme -->
function add_favicon() {
  echo '<link rel="icon" href="' . get_template_directory_uri() . '/images/favicon.ico" sizes="any">';
  echo '<link rel="icon" href="' . get_template_directory_uri() . '/images/favicon.svg" type="image/svg+xml">';
  echo '<link rel="apple-touch-icon" href="' . get_template_directory_uri() . '/images/apple-touch-icon.png">';
}
add_action('wp_head', 'add_favicon');

Or use the WordPress Customizer: Appearance → Customize → Site Identity → Site Icon (handles all sizes automatically).

Verifying your favicon works

Browser tab: Hard-refresh the page (Ctrl+Shift+R / Cmd+Shift+R). The favicon should appear in the tab.

DevTools check:

  1. Open DevTools → Network tab
  2. Filter by “favicon” or “ico”
  3. Reload the page
  4. Verify favicon requests return 200, not 404

Test all contexts:

  • Browser tab (16×16 display)
  • Bookmark bar
  • History dropdown
  • Windows taskbar pin (32×32 or 48×48)
  • iOS Safari → Add to Home Screen (180×180)
  • Android Chrome → Add to Home Screen (requires manifest)

Common issue — browser cache: Browsers cache favicons aggressively. If your new favicon isn’t showing:

  1. Open DevTools → Network tab → check “Disable cache”
  2. Or visit yourdomain.com/favicon.ico directly and hard refresh
  3. Or test in an incognito/private window

Multiple favicons for different pages

You can specify different favicons per page (useful for subdomains or distinct app sections):

<!-- Main site -->
<link rel="icon" href="/favicon-main.ico">

<!-- Admin section -->
<link rel="icon" href="/favicon-admin.ico">

<!-- Different color per environment -->
<!-- production: -->
<link rel="icon" href="/favicon.ico">
<!-- staging: -->
<link rel="icon" href="/favicon-staging.ico">  <!-- Orange border variation -->

Related posts

Related tool

Favicon Generator

Generate favicon package from any image or emoji. Multiple sizes (16, 32, 48, 180, 192, 512), manifest.json, and HTML snippet.

Written by Mian Ali Khalid. Part of the Frontend & Design pillar.