DEV Community

Cover image for Add an Emoji Favicon with One Line of HTML (Next.js, Astro, Vue, WordPress) Plus Dynamic Tab Notifications
FindUtils
FindUtils

Posted on

Add an Emoji Favicon with One Line of HTML (Next.js, Astro, Vue, WordPress) Plus Dynamic Tab Notifications

Favicons used to mean a ZIP of PNGs, an ICO, an apple-touch icon, and a half-remembered manifest.json. For a lot of sites, that is still the right approach. For many others — a side project, a docs site, a staging deploy, a dashboard that needs a notification badge — you only need one emoji in the tab, and you need it today.

EmojiFavicons is a URL-based emoji favicon service from FindUtils. You point a normal <link rel="icon"> at an emoji slug, and the API returns an SVG (under 200 bytes for a plain emoji, per the docs). No signup, no API key, no build step. This article sticks to what the site documents and what the endpoints actually return when you request them.

The one-line install

Drop this in your HTML <head>:

<link rel="icon" href="https://emojifavicons.com/fire">
Enter fullscreen mode Exit fullscreen mode

Replace fire with any emoji name. The homepage and docs state that EmojiFavicons covers 3,773 Unicode emojis, searchable by 11,550 keywords. Names and keywords are case-insensitive. You can also use a keyword (/hot resolves to fire), a URL-encoded emoji character, or a country code for flags (/US, /TR).

A live request to https://emojifavicons.com/fire returns image/svg+xml — a tiny SVG wrapping the 🔥 glyph. Safari is a special case: the how-it-works page explains that Safari has limited SVG favicon support, so the service auto-serves a PNG (Twemoji) for Safari User-Agents. You can force a format with ?svg or ?png.

If you later want a classic downloadable package instead of a live URL, the docs also expose GET /download/:emoji — for example https://emojifavicons.com/download/rocket returns a ZIP of standard sizes. That is the honest self-host path when you do not want a third-party dependency at runtime.

Customize with URL parameters

Every favicon endpoint accepts query parameters. A documented example that works today:

https://emojifavicons.com/fire?size=64&bg=1a1a1a&animate=pulse
Enter fullscreen mode Exit fullscreen mode

That request returns image/svg+xml with a 64×64 viewBox, a dark background, and a CSS pulse animation. Useful parameters from the docs (not an exhaustive list):

Parameter What it does (per docs)
size SVG size in pixels (16–512; default 48)
bg Background hex without #
shape e.g. circle, rounded, hexagon, …
animate e.g. pulse, bounce, spin, and many others
badge Notification overlay: 1–99 or dot
theme Branded presets such as github-dark, vercel-dark, tailwind
png / svg Force output format

Combine freely. Combos put 2–10 emojis side by side with a +:

<link rel="icon" href="https://emojifavicons.com/fire+rocket">
Enter fullscreen mode Exit fullscreen mode

That endpoint returns a single SVG with 🔥 and 🚀 next to each other — useful for “shipping fast” vibes without designing an icon.

For a red unread count without JavaScript:

<link rel="icon" href="https://emojifavicons.com/bell?badge=3">
Enter fullscreen mode Exit fullscreen mode

Framework installs (verified against the official guides)

The frameworks index lists 19 tutorials. Below are the four most common, copied from the site’s own guides. In every case, remove or rename any default favicon.ico / favicon.svg in public/ so the external URL wins.

Next.js (App Router)

From the Next.js guide:

// app/layout.tsx
import type { Metadata } from 'next';

export const metadata: Metadata = {
  icons: {
    icon: 'https://emojifavicons.com/rocket',
    apple: 'https://emojifavicons.com/apple-touch-icon/rocket',
  },
};
Enter fullscreen mode Exit fullscreen mode

Pages Router: put the <link> tags in pages/_document.tsx inside <Head>. The guide notes that Vercel may cache an old favicon for up to 24 hours; append ?v=2 if you need a cache bust.

Astro

From the Astro guide, in your shared layout:

<head>
  <link rel="icon" type="image/svg+xml" href="https://emojifavicons.com/rocket" />
  <link rel="apple-touch-icon" href="https://emojifavicons.com/apple-touch-icon/rocket" />
</head>
Enter fullscreen mode Exit fullscreen mode

Delete public/favicon.svg if the starter left one. Keep the tags in the persistent layout so View Transitions do not thrash the tab icon.

Vue 3 + Vite / Nuxt 3

From the Vue guide:

Vite: edit root index.html:

<link rel="icon" type="image/svg+xml" href="https://emojifavicons.com/rocket" />
<link rel="apple-touch-icon" href="https://emojifavicons.com/apple-touch-icon/rocket" />
Enter fullscreen mode Exit fullscreen mode

Nuxt 3: in nuxt.config.ts:

export default defineNuxtConfig({
  app: {
    head: {
      link: [
        { rel: 'icon', type: 'image/svg+xml', href: 'https://emojifavicons.com/rocket' },
        { rel: 'apple-touch-icon', href: 'https://emojifavicons.com/apple-touch-icon/rocket' },
      ],
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

WordPress

From the WordPress guide, append to the child theme’s functions.php (or a site-wide snippets plugin):

add_action('wp_head', function () {
  echo '<link rel="icon" href="https://emojifavicons.com/rocket" type="image/svg+xml">';
  echo '<link rel="apple-touch-icon" href="https://emojifavicons.com/apple-touch-icon/rocket">';
});
Enter fullscreen mode Exit fullscreen mode

Clear the Customizer Site Icon if WordPress still serves its own. Hard-refresh after saving.

Dynamic tab notifications with the JS SDK

Static badges are fine for marketing sites. Apps need the tab to react. Include the SDK once:

<script src="https://emojifavicons.com/sdk.js"></script>
Enter fullscreen mode Exit fullscreen mode

https://emojifavicons.com/sdk.js returns application/javascript. The homepage and docs show the core surface; the script itself exposes:

EmojiFavicon.set('rocket');
EmojiFavicon.animate('fire', 'pulse');
EmojiFavicon.notify('bell', 3000); // flash, then restore
EmojiFavicon.restore();
EmojiFavicon.setBadge('bell', 5);
EmojiFavicon.clearBadge();
Enter fullscreen mode Exit fullscreen mode

A practical pattern for “you have new messages while the tab is in the background”:

function onUnread(count) {
  if (count > 0) {
    EmojiFavicon.set('bell', { badge: Math.min(count, 99) });
  } else {
    EmojiFavicon.restore();
  }
}
Enter fullscreen mode Exit fullscreen mode

notify(emoji, durationMs) temporarily swaps the icon, then restores the previous href — handy for a one-shot alert without managing state yourself.

Trade-offs (be honest)

Depends on a third-party URL. If emojifavicons.com is unreachable, the tab falls back to whatever the browser does without a favicon. The compare page itself lists this as a con of URL-based services, mitigated by CDN caching (docs: 7-day CDN cache, 24-hour browser cache) and by downloading the SVG/PNG/ICO (or the ZIP from /download/:emoji) and hosting it yourself.

Rate limits. The FAQ on the homepage says normal use has a 300 requests per minute limit, with no signup or credit card required. That is generous for a favicon, but it is still a shared free resource — do not hammer it from a CI loop that rebuilds thousands of pages per minute.

Not a full custom-image favicon studio. If you need a hand-drawn mark or a photo crop, generate and self-host assets instead. For that workflow, FindUtils’ favicon generator is a useful browser-side companion when you already have an image file. EmojiFavicons and the FindUtils generator solve different problems: emoji-as-URL vs. image-to-package.

Caching surprises. CDNs and browsers cache favicons aggressively. After a change, hard-refresh or bump a query string.

Quick health check

Before you ship, run your domain through the Favicon Health Checker. It scores icon / SVG / apple-touch / manifest coverage and offers copy-paste fixes. Pair that with the interactive generator if you want to preview size, shape, animation, and badge before pasting a URL into production.

Wrap-up

  1. Add <link rel="icon" href="https://emojifavicons.com/fire"> (or your emoji of choice).
  2. Optionally tune with ?size=, ?bg=, ?animate=, ?badge=, or a combo like /fire+rocket.
  3. Follow the framework guide for Next.js, Astro, Vue, or WordPress.
  4. For runtime swaps, load sdk.js and call set / animate / notify.
  5. If you outgrow a third-party URL, download the ZIP and self-host.

Start at emojifavicons.com, browse the docs, and if you need more free browser-only utilities beyond favicons, FindUtils has a large catalog of client-side tools that never upload your files.

Top comments (0)