Icon Horse

API docs

Icon Horse returns the logo or favicon for any website or product. Give it a domain (stripe.com) or a product name (Microsoft Entra ID) and get back a PNG, WebP, ICO or SVG. Free, no API key, no signup. Every URL below works in an <img> tag, a spreadsheet, a slide or a script.

Machine-readable: openapi.json · llms.txt · llms-full.txt (this page as markdown)

1. Quick start

<img src="https://icon.horse/icon/stripe.com" alt="Stripe" width="32" height="32">

That is the whole integration. The URL returns Stripe's icon as a PNG, up to 256×256. If the site has no icon, you get a letter tile instead of a broken image (or a 404, if you ask for one).

curl -o stripe.png https://icon.horse/icon/stripe.com/128
curl -o entra.png  https://icon.horse/name/microsoft-entra-id/128
curl 'https://icon.horse/api/icons?q=stripe.com&q=Microsoft%20Entra%20ID'

2. Icon by domain: /icon/<domain>

URLReturns
/icon/github.comPNG, the best icon the site has, up to 256px
/icon/github.com/64PNG at 16, 32, 48, 64, 128 or 256px
/icon/github.com/256/webpWebP at any allowed size
/icon/github.com/icoICO with 16, 32 and 48px frames
/icon/github.com/svgThe site's own SVG, or 404 if it has none

Sizes: 16, 32, 48, 64, 128, 256. Formats: png (default), webp, ico, svg. ICO and SVG take no size. ?size=64 and ?format=webp also work and redirect (301) to the path form.

Paste anything. Scheme, www., path, port and case are dropped, and the request redirects (301) to one canonical URL:

/icon/https://www.Stripe.com/pricing   →  301  /icon/stripe.com
/icon/stripe.com?size=64&format=webp   →  301  /icon/stripe.com/64/webp

Icon Horse ranks the site's <link rel="icon"> tags, apple-touch-icon, web app manifest icons and /favicon.ico. SVG wins, then the largest size. Parked "domain for sale" pages count as not found.

3. Icon by product name: /name/<product>

Many products do not have their own domain. Microsoft Entra ID lives on microsoft.com; CoCounsel lives on thomsonreuters.com. Ask for them by name:

https://icon.horse/name/microsoft-entra-id
https://icon.horse/name/microsoft-entra-id/128/webp
https://icon.horse/icon?q=Microsoft%20Entra%20ID     →  301  /name/microsoft-entra-id

The name becomes a lowercase slug. Sizes, formats and variants work the same as /icon. Names resolve in this order:

  1. Curated catalog. Hand-checked name → domain or image entries for products that public data gets wrong.
  2. Wikidata. The query must match whole words in an entity's label or alias, and the entity must have an icon, a logo or an official website. Icon Horse tries the icon, then a square logo, then the website's favicon, then a wide wordmark.

No match means not found. Icon Horse never guesses a logo for a name it does not know.

4. Variants: trim, weight, pad, bg, tone, fallback

Query options that make a row of logos look even. They work on /icon and /name, at every size and raster format.

OptionEffect
trim=1Cut empty border so the mark fills the frame
weight=1Scale by visual mass, not bounding box, so a solid square and a thin mark look equally heavy. Implies trim
pad=0..40Padding, percent of each side
bg=white, bg=black, bg=<hex>Background color. Default is transparent. Hex without #, 3 or 6 digits. With bg set, a logo that will not read on it gets an X-Icon-Warning header
tone=mono, color=<hex>Recolor the mark to one color to match a deck. Default color is black or white, whichever reads on bg
fallback=404Return 404 instead of a letter tile when no icon is found
https://icon.horse/icon/bill.com/128?trim=1&weight=1&pad=8&bg=white
https://icon.horse/icon/stripe.com/64?bg=0a2540
https://icon.horse/icon/example.com?fallback=404

Use fallback=404 with the onerror handler of an <img> when you would rather hide a missing logo than show a letter.

5. Honest response headers

Every image response says what it is. Browsers can read these cross-origin (Access-Control-Expose-Headers is set).

HeaderMeaning
X-Icon-Fallbacktrue when the image is a placeholder letter tile
X-Icon-Source-SizeOriginal size, such as 48x48, or vector. Under 128px looks soft when scaled up
X-Icon-SourceThe URL the icon came from
X-Icon-Confidence0 to 1. 0 means placeholder
X-Icon-Stand-Intrue when a styled request (weight, pad, bg or tone) got a neutral stand-in tile because no logo exists
X-Icon-WarningProblems with a styled icon: low contrast on bg, or tone=mono skipped
$ curl -sI https://icon.horse/icon/stripe.com/64
HTTP/2 200
content-type: image/png
x-icon-fallback: false
x-icon-source-size: vector
x-icon-confidence: 0.9
x-icon-source: https://images.stripeassets.com/.../favicon.svg
const res = await fetch('https://icon.horse/icon/acme.example')
if (res.headers.get('X-Icon-Fallback') === 'true') {
  // No real logo. Show a placeholder of your own, or nothing.
}

6. Icon pages: /site/<domain>

A page for people: the icon, the site's name and description, downloads in every size and format, and copy-paste embed code.

https://icon.horse/site/stripe.com

Downloads: PNG at 16 to 256px, WebP 256px, ICO, and SVG when the site has one.

7. Batch JSON: /api/icons

Resolve up to 20 domains or product names in one call. Each result says whether a real icon was found, how confident the match is, where it came from, and the URLs to use.

curl 'https://icon.horse/api/icons?q=stripe.com&q=Microsoft%20Entra%20ID'

curl -X POST https://icon.horse/api/icons \
  -H 'Content-Type: application/json' \
  -d '{"q": ["stripe.com", "Microsoft Entra ID", "CoCounsel"]}'

A query with a space, or with no dot, is a product name. Anything else is a domain. Response (shortened):

{
  "results": [
    {
      "query": "Microsoft Entra ID",
      "kind": "name",
      "found": true,
      "fallback": false,
      "confidence": 0.85,
      "name": "Microsoft Entra ID",
      "hostname": "azure.microsoft.com",
      "via": "wikidata-logo",
      "source": { "url": "https://commons.wikimedia.org/wiki/Special:FilePath/Microsoft%20Entra%20ID%20color%20icon.svg", "format": "svg", "size": "vector" },
      "urls": {
        "png": "https://icon.horse/name/microsoft-entra-id",
        "png_64": "https://icon.horse/name/microsoft-entra-id/64",
        "webp": "https://icon.horse/name/microsoft-entra-id/256/webp",
        "ico": "https://icon.horse/name/microsoft-entra-id/ico",
        "svg": "https://icon.horse/name/microsoft-entra-id/svg",
        "page": null
      },
      "candidates": [ ... ]
    }
  ]
}
FieldMeaning
kinddomain or name
found / fallbackWhether a real icon exists. When found is false, urls is null
confidence0 to 1, same as X-Icon-Confidence
viaHow the icon was found: website, catalog, or a Wikidata source such as wikidata-logo
sourceOriginal URL, format and size (vector for SVG)
urlsReady-to-use links. svg is null when there is no vector; page is null for names
candidatesOther sources considered, for name lookups
errorSet instead of the fields above when a query is empty or the host is rejected

GET responses are cached for 5 minutes. POST is not cached. More than 20 queries returns 400.

8. Force a refresh: /refresh/<domain>

Changed your favicon? Refetch it now:

curl https://icon.horse/refresh/example.com
{"refreshed":true,"changed":true,"purged":true}

Without a refresh, a changed icon shows up within about 2 days on its own.

9. Use in Google Slides, Docs or PowerPoint

Slides and documents accept an image by URL. Use a PNG URL; they do not accept SVG or ICO.

  1. Google Slides or Google Docs: Insert → Image → By URL. Paste https://icon.horse/icon/stripe.com/256.
  2. PowerPoint or Word on Windows: Insert → Pictures → This Device, then paste the same URL into the file name box. On Mac or the web, open the URL in a browser, save the PNG, and insert the file.
  3. Product without a domain: use the name form, such as https://icon.horse/name/microsoft-entra-id/256.

Tip for an even row of logos: add ?trim=1&weight=1&pad=8&bg=white. Every logo then fills its square the same way on a white tile, so a row of customer or vendor logos lines up.

https://icon.horse/icon/stripe.com/256?trim=1&weight=1&pad=8&bg=white
https://icon.horse/icon/github.com/256?trim=1&weight=1&pad=8&bg=white
https://icon.horse/name/microsoft-entra-id/256?trim=1&weight=1&pad=8&bg=white

Google Sheets works too: =IMAGE("https://icon.horse/icon/stripe.com/64").

10. For AI agents: MCP, stack and logo sets

Agents can call the plain URLs and /api/icons above. Three more endpoints are built for agent workflows; openapi.json has every parameter.

MCP server: /mcp

A remote Model Context Protocol server at https://icon.horse/mcp (Streamable HTTP, no key) with four tools:

claude mcp add --transport http icon-horse https://icon.horse/mcp

Company stack: /api/stack

Which tools a company uses: client portals, practice software, email, CRM, analytics. It reads the homepage, a few likely pages (client portal, pay, contact) and DNS records. Every tool comes with the evidence that put it there (a link and its text, a script, an MX or TXT record) and a confidence. No observed signal, no tool. A missing tool means no evidence was found, not that the company does not use it.

curl 'https://icon.horse/api/stack?domain=stripe.com'

Logo set: /api/set

A row of logos with the same size, visual weight, padding, background and tone. Parameters: q (repeat, up to 20), size, bg, pad, tone (color or mono), color, gap. Each result adds set_url (the styled image), warnings (for example low contrast on a dark row) and standIn (true when no real logo exists and a neutral tile stands in). row_url renders the whole row as one PNG.

curl 'https://icon.horse/api/set?q=stripe.com&q=Microsoft%20Teams&size=128&bg=ffffff&pad=8'
curl -X POST https://icon.horse/api/set -d '{"q": ["stripe.com", "Microsoft Teams"], "bg": "1f2937", "tone": "mono"}'

11. Caching and limits

Need more volume or something custom? [email protected]