Hex.pm Hexdocs.pm GitHub Actions

FindSiteIcon

Find a usable, high-quality icon for a website URL.

FindSiteIcon fetches a page, extracts known icon links, adds common fallback locations, probes the candidates, and returns the best icon URL it can validate. It is built on Req and keeps the public API small enough to use directly in application code.

Installation

Add find_site_icon to your dependencies:

def deps do
  [
    {:find_site_icon, "~> 1.0"}
  ]
end

Quick Start

case FindSiteIcon.find_icon("https://nytimes.com") do
  {:ok, icon_url} ->
    icon_url

  {:error, reason} ->
    reason
end

If you already have the page HTML, pass it in to avoid an extra fetch:

FindSiteIcon.find_icon("https://example.com/article", html: html)

For hot paths, cap the whole lookup:

FindSiteIcon.find_icon("https://example.com", timeout: 3_000)

Options

OptionWhat it does
:htmlUses caller-provided HTML instead of fetching the page first.
:default_icon_urlReturns {:ok, default_icon_url} when no valid icon is found.
:timeoutCaps the whole lookup and applies the same timeout to internal HTTP requests.
:http_optionsPasses Req options to the internal HTTP client.
:max_concurrencyLimits concurrent icon probes. Defaults to 8.
:max_iconsLimits how many candidate icon URLs are probed. Defaults to no limit.
:pool_max_idle_timeMilliseconds before idle Finch socket pools are terminated so file descriptors are reclaimed when probing many distinct hosts. Defaults to 30_000. Pass :infinity to restore Req's pre-1.0.2 behaviour of keeping pools alive forever.

What It Checks

  • HTML icon links: apple-touch-icon, apple-touch-icon-precomposed, shortcut icon, and icon.
  • Common fallback locations such as /apple-touch-icon.png, /favicon.png, and /favicon.ico.
  • PNG, JPEG, WebP, SVG, and ICO icon URLs.
  • Response metadata with a HEAD-first request, falling back to GET when needed.
  • cache-control: max-age for cache expiration when the server provides it.

Development

mix deps.get
mix test
mix credo --strict
mix dialyzer

The live website smoke test is tagged :external so regular test runs do not depend on the public internet:

mix test --include external

Documentation is available at hexdocs.pm/find_site_icon.