Skip to content

Brand logos are hiding in DNS

How an email standard gave us vector logos instead of 32×32 favicons

August 4, 2026

Getting a website's logo sounds like a solved problem until you look at the results.
HTML never standardized how websites should expose their primary logo. Most sites don't declare one at all, so you're left falling back to the favicon: a browser tab icon that's intentionally small, often simplified, and not necessarily the brand's official logo.
There is another source that's easy to overlook, and it's been sitting in DNS the whole time. It's always DNS.
TL;DR
  • Brands publish their logo in DNS as a BIMI record, the standard behind the logo your mailbox shows next to an email.
  • Roughly one in five of the top 500 sites publish one. High precision, low recall, so it ships as an optional package, not a favicon replacement.
  • Shipped as metascraper-logo-bimi, with the record logic split out as bimi-url.
Without one place to look, you end up probing a handful of optional markup conventions. metascraper does that for you; metascraper-logo walks the common hints in order:
// Resolve `logo` from HTML markup (metascraper-logo), first match wins.
logo: [
  toLogo($ => $('meta[property="og:logo"]').attr('content')),
  toLogo($ => $('meta[itemprop="logo"]').attr('content')),
  toLogo($ => $('img[itemprop="logo"]').attr('src')),
  toLogo($ => toLogoUrl($, 'brand.logo')),
  toLogo($ => toLogoUrl($, 'organization.logo')),
  toLogo($ => toLogoUrl($, 'place.logo')),
  toLogo($ => toLogoUrl($, 'product.logo')),
  toLogo($ => toLogoUrl($, 'service.logo')),
  toLogo($ => toLogoUrl($, 'publisher.logo')),
  toLogo($ => toLogoUrl($, 'logo.url')),
  toLogo($ => toLogoUrl($, 'logo'))
]
Even after checking every common convention, many sites still expose no logo metadata. To improve coverage we built metascraper-logo-favicon: almost every site exposes a /favicon.ico, so you can treat that as the logo when markup is empty:
FaviconFileSizeResolution
x.com/favicon.icoPNG549 B32×32
apple.com/favicon.icoICO22 KB64×64
cloudflare.com/favicon.icoPNG908 B99×96
adobe.com/favicon.icoICO15 KB48×48
This works surprisingly well for coverage, but it's a poor representation of a brand. Favicons are designed for browser tabs, not metadata. They're often tiny, simplified, or non-square because that's exactly what browsers need.

Mailbox providers already solved this

The web never standardized logo discovery, but email effectively did.
BIMI (Brand Indicators for Message Identification) lets domains publish an official brand logo in DNS. Mail providers like Gmail and Apple Mail use it to display the sender's logo next to authenticated emails:
$ dig +short TXT default._bimi.microlink.io
"v=BIMI1; l=https://cdn.microlink.io/logo/logo.svg;"
That makes BIMI an interesting source of logo metadata for several reasons:
  • DNS is fast. Resolving a TXT record is typically cheaper than downloading and parsing an HTML document, especially once the resolver is warm.
  • No HTML required. It still works when a page is JavaScript-rendered, rate-limited, or responds with a 403.
  • The logo is intentional. It's the same asset mailbox providers use to represent the brand.
  • The format is constrained. BIMI requires a square SVG Tiny P/S image, which is much better suited for avatars than a random favicon.

Why the record is a better source

BIMI requires SVG Tiny P/S (Portable/Secure), a restricted SVG profile designed specifically for safely displaying brand logos inside email clients.
  • No scripts: the SVG cannot run JavaScript, so mailbox clients can render it safely.
  • No external assets: no remote images, fonts, or stylesheets; the mark is self-contained.
  • Square by design: every logo fits a 1:1 aspect ratio, making it immediately usable as an avatar or application icon.
Here are the same four sites from the favicon table, with their BIMI logos next to those icons:
DomainFaviconBIMISizeTitle
x.comX faviconX Corp. BIMI logo520 BX Corp.
apple.comApple faviconApple BIMI logo1.1 KBApple
cloudflare.comCloudflare faviconCloudflare BIMI logo1.4 KBCloudflare Inc.
adobe.comAdobe faviconAdobe BIMI logo474 BAdobe: Creative, marketing…

A strong signal when it's there

We ran dig TXT default._bimi.<domain> across the top 500 sites:
SetPublishes a logo
Top 10019 / 100 (19%)
Top 50097 / 500 (19%)
Coverage is still limited. BIMI significantly improves quality when present, but it isn't common enough to replace existing discovery strategies. So it ships as its own package rather than folded into the favicon rule, and ordering is the caller's choice:
const metascraper = require('metascraper')([
  require('metascraper-logo-bimi')(),
  require('metascraper-logo')(),
  require('metascraper-logo-favicon')()
])
Putting the BIMI rule first means it wins whenever the domain publishes a record, while existing HTML and favicon strategies remain unchanged for everyone else. On a warm resolver the lookup measured between 23 ms and 78 ms (median 52 ms). Since results are memoized per domain, that cost is typically paid only once.

Try it

The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://www.cloudflare.com' URL with 'meta' API parameter:

CLI Microlink API example

microlink https://www.cloudflare.com&meta

cURL Microlink API example

curl -G "https://api.microlink.io" \
  -d "url=https://www.cloudflare.com" \
  -d "meta=true"

JavaScript Microlink API example

import mql from '@microlink/mql'

const { data } = await mql('https://www.cloudflare.com', {
  meta: true
})

Python Microlink API example

import requests

url = "https://api.microlink.io/"

querystring = {
    "url": "https://www.cloudflare.com",
    "meta": "true"
}

response = requests.get(url, params=querystring)

print(response.json())

Ruby Microlink API example

require 'uri'
require 'net/http'

base_url = "https://api.microlink.io/"

params = {
  url: "https://www.cloudflare.com",
  meta: "true"
}

uri = URI(base_url)
uri.query = URI.encode_www_form(params)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)

puts response.body

PHP Microlink API example

<?php

$baseUrl = "https://api.microlink.io/";

$params = [
    "url" => "https://www.cloudflare.com",
    "meta" => "true"
];

$query = http_build_query($params);
$url = $baseUrl . '?' . $query;

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "GET"
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #: " . $err;
} else {
    echo $response;
}

Golang Microlink API example

package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io"
)

func main() {
    baseURL := "https://api.microlink.io"

    u, err := url.Parse(baseURL)
    if err != nil {
        panic(err)
    }
    q := u.Query()
    q.Set("url", "https://www.cloudflare.com")
    q.Set("meta", "true")
    u.RawQuery = q.Encode()

    req, err := http.NewRequest("GET", u.String(), nil)
    if err != nil {
        panic(err)
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        panic(err)
    }

    fmt.Println(string(body))
}
logo here comes from default._bimi.cloudflare.com, not from the page. The favicon path returns a 99×96 PNG for the same site.

Add BIMI to your company

If you want metadata tools (and mailboxes) to pick up your real logo, publish it. Three pieces, in order:
1. Export the logo as SVG Tiny P/S. Start from your official brand mark, not a favicon. The export has to match the Portable/Secure profile covered above: square, no scripts, no linked assets, baseProfile="tiny-ps" on the root <svg>. A default Illustrator or Figma SVG usually fails that check, so convert and validate before you upload anything.
2. Host it over HTTPS. Serve the file as image/svg+xml. Stay on https through any redirects. Put the mark on a stable URL you control (or your CA's BIMI host if you buy a VMC).
3. Publish one TXT record at default._bimi.yourdomain.com:
$ dig +short TXT default._bimi.microlink.io
"v=BIMI1; l=https://cdn.microlink.io/logo/logo.svg;"
  • v=BIMI1 is the version.
  • l= is the HTTPS URL of the SVG.
  • a= is optional: a Verified Mark Certificate, if you want mailbox providers that require one (Gmail is the usual reason).
For inbox display you also need DMARC at enforcement (p=quarantine or p=reject). For metadata extraction, the DNS logo alone is enough: that is the part metascraper-logo-bimi reads.

Join the community

All of these improvements or features are community driven: We listen to your feedback and act accordingly.
Whether you are building a product, an indie developer, or just interested in web technologies, come chat with us.