10개의 사이트에 대해 나만의 파비콘 체커를 실행했습니다. 10개 모두 실패했습니다.

작성자

카테고리:

← 피드로
DEV Community · lixy · 2026-09-06 개발(SW)

lixy

I maintain a small collection of single-purpose web tools. Last month I built a favicon checker: you type a URL, it reads the icon declarations in the HTML head, probes every referenced file, and also hits /favicon.ico directly, because plenty of software still requests that path without ever reading your HTML.

The first thing you should do with any auditing tool is point it at your own stuff. So I did. Ten sites, all built by me, all shipped and verified in browsers I actually use.

All ten failed. Not seven out of ten. Ten.

Failure one: SVG-only icon sets

Every site had a nice crisp favicon.svg and nothing else. Modern browsers request it, render it at any size, everything looks great in Chrome and Firefox. Then something older comes along: a bookmark sidebar, an RSS reader, a corporate proxy portal that lists your link, that one intern running Opera 12. These clients do not parse your <link> tags. They request /favicon.ico and hope.

All ten sites returned a 404 for that path. The fix is not glamorous. You need an actual .ico file, ideally with 16, 32, and 48 pixel frames packed inside, plus a PNG for iOS. More on that below.

Failure two: no apple-touch-icon

Nine of the ten sites had no apple-touch-icon.png. When someone saves such a site to an iOS home screen, Safari does not use your favicon. It takes a screenshot of the page, letterboxes it, and calls that your app icon. If you have ever seen a bookmark that looked like a cropped text paragraph, that is why.

The fix is one file and one tag: a 180 by 180 PNG, referenced with <link rel="apple-touch-icon" href="/apple-touch-icon.png">. Done. No JavaScript, no media queries, no dark mode variants needed. iOS rounds the corners itself.

Failure three: the 404 that would not leave

This is the one that cost me an evening, so pay attention if any of your sites sit behind Cloudflare.

I generated the missing icons, deployed them, and re-ran the checker. Still 404. I deployed again. Still 404. I started doubting my build, my deploy script, my cache headers, my sanity.

The files were fine. The problem was that Cloudflare had cached the original 404 responses. The .ico extension is on Cloudflare’s default cached file list, and that rule does not distinguish between a 200 with an image and a 404 with an error page. The edge had helpfully stored my failure and now served it at speed.

You can confirm this with a response header check: if cf-cache-status: HIT shows up on a request you know should be fresh, you are looking at a cached answer, not the origin’s. Two ways out: request the file with a query string like ?v=2, which bypasses the cache and shows you what the origin actually returns, or wait for the cached entry to expire on its own. Purging works too if you have dashboard access.

So the deploy sequence that actually worked was: upload the files, verify with a query string, then trust that the plain path would heal itself as the cache aged out.

How I generated everything locally

No online favicon service, because the source icons belong to the sites and uploading them somewhere for conversion defeats the point. The pipeline:

  1. Render the source SVG in a headless browser with a transparent background, at each target size. This respects whatever the SVG actually draws, which matters for icons with effects that naive rasterizers mangle.
  2. Use Pillow to pack 16, 32, and 48 pixel frames into a single multi-resolution .ico.
  3. Save a 180 by 180 PNG as apple-touch-icon.png.
  4. Add the tag block to the HTML head of every page template.

Then the checklist before calling it done: /favicon.ico returns 200 with an image content type, apple-touch-icon.png exists, and the sizes declared in the HTML match the actual pixel dimensions of the files. That last one is sneaky. I found two sites declaring sizes="32x32" on a file that was actually 48 pixels square. Browsers mostly cope, but a checker that compares declared versus actual will flag it, and the fix is a one-line attribute edit.

The five minute version for your own sites

If you want to audit your own setup without building anything, run through this:

  • curl -I https://yoursite.example/favicon.ico and look for 200 plus an image content type, not text/html
  • Check that /apple-touch-icon.png exists and is 180 by 180
  • Compare the sizes attributes in your head against the real dimensions of the files they point to
  • If you use a CDN, remember it may cache your 404s the same way it caches your assets

Or point a checker at it. I eventually wired the probe logic into a free favicon checker that runs the whole battery in one go: the direct /favicon.ico request, every declared icon, the apple-touch-icon, format sniffing, and declared versus actual dimensions. It runs server-side probes only, no account, and it is how the ten-versus-zero result above got measured. For a deeper reference on sizes, formats, and which tags to use, the favicon best practices guide on the same site covers the long version.

The humbling part of shipping an auditing tool is that it audits you first. All ten of my sites failed a check I had just written the logic for. The icons took an afternoon to fix. The Cloudflare cache lesson would have taken much longer to debug in production, and that one I only hit because the checker kept retesting instead of trusting my deploy script’s success message.

Tools that re-verify from the outside are worth more than tools that report what you intended.

원문에서 계속 ↗