Skip to main content
Brand API provides programmatic access to any company’s brand assets through a single API call. This includes their latest logos, color schemes, fonts, images, and other firmographic information. Brand API works in real-time, if a brand is not part of our dataset, it will index the information live ensuring global coverage for businesses of all sizes, geography and industries.

Implementation guide

1

Get your API key

You’ll need to create an account on our Developer Portal. Creating an account is quick and easy, and will give you access to your dashboard where you’ll find your API key.
Building an agent that runs without a human in the loop? Skip the account: pay per request with x402 or MPP, or buy standing access with prepaid credits.
2

Make your first API call

The Brand API supports multiple identifier types (domain, website URL, email address, Stock or ETF ticker, ISIN, Crypto symbol). Authentication is done by passing your API key as a Bearer Authentication.
The shorthand route /v2/brands/{identifier} (without a type prefix) is still supported and auto-detects the identifier type (in the order: domain → ticker → ISIN → crypto), but explicit type routes are recommended to avoid naming collisions.The API reads an identifier that contains @ as an email address and resolves it to its registrable domain. john@example.brandfetch.com returns the same response as brandfetch.com. The API does not store the address. Your request logs show only the resolved domain. Email addresses work on the shorthand route only.The API reads an identifier that starts with http:// or https:// (or the percent-encoded https%3A%2F%2F) as a website URL. The API also reads a domain with a path (brandfetch.com/developers/pricing) as a website URL. The API resolves the URL to the registrable domain of its host, so https://www.brandfetch.com/developers/pricing returns the same response as brandfetch.com. The API does not store the URL. Your request logs show only the resolved domain. Website URLs work on the shorthand route only.
If you only have company names, use the Brand Search API to match brand names to the most likely URLs.
3

Test and deploy

All requests for the domain brandfetch.com are free and will not count towards your usage/quotas. You can make as many requests to the Brandfetch’s brand as you need while you iterate on and test your integration.Once you are ready to go live, replace brandfetch.com with the identifier you want to look up: a domain name, website URL, email address, Stock/ETF ticker, ISIN, or Crypto symbol.
If you have custom requirements, or any questions contact us.

Prefetching brands

Brand API works in real time: the first request for a brand nobody has asked for before crawls it live, which may take a moment. When you know ahead of time which brand you will need — a user has just signed up, and their brand screen is a few steps away — ask for it in advance with a HEAD request on the same route:
Prefetch at signup
The response carries no body. The status code is the answer: HEAD accepts every identifier the GET does — a domain, an email address, a brand ID, a ticker, an ISIN or a crypto symbol. Prefetch requests never count towards your quota. Prefetch requests may be throttled to prevent abuse and ensure quality of service. See the reference for the full contract.

Batch lookups

Send up to 100 identifiers in one request. Get one result per identifier, in the order you sent them.
Batch lookup
Each result carries the identifier you sent, a status and, on a 200, the brand (shortened here):
A batch never crawls while you wait. A brand that is not indexed yet is queued for indexing and answered 202. Request it again later, on its own or in your next batch. A string is read as the identifier of GET /v2/brands/{identifier}: a domain, website URL, email address, brand ID, ticker or ISIN. To name the type, send an object: { "type": "ticker", "value": "BHP.AX" }. type is domain, ticker, isin, crypto or brandId. An exchange-suffixed ticker sent as a string, such as bhp.ax, is read as a domain. cachedOnly, allowNsfw and palette go in the body, as booleans, and mean what they mean on GET. Each identifier answered 200 uses one API credit. Every other result is free, 404 included, and an identifier repeated in one request is charged once. When your organization has fewer credits left than a batch could use, the batch is refused with 429 and nothing is charged. Batch lookups are available on paid plans and with prepaid credits. A free plan receives 403 with the header x-bf-error: paid_plan_required. See the reference for the full contract.

Skip crawling (cached only)

By default, a brand that is not yet part of the dataset is indexed live. This guarantees global coverage, but a live crawl can take several seconds. A crawl still running when the request has to be answered carries on in the background, and the request is answered 404 with the header x-bf-error: crawl_queued: retry in a minute or two; if the brand could be collected, it is served. When latency matters more than coverage, such as enriching records in bulk or rendering a screen that cannot wait, set the cachedOnly query parameter to true. The API then answers from its store alone, instantly and without crawling:
  • A brand that is already indexed is returned immediately (200), exactly as a normal request would return it.
  • A brand that is not yet indexed is answered with 204 No Content instead of being crawled live.
cachedOnly works on every GET /v2/brands route and with every identifier type. On a ticker, ISIN, or crypto symbol that is not yet indexed, the API skips the identifier resolution too and answers 204. A 204 has no body, so check the status code before parsing the response. A 204 does not count towards your quota. To index a brand ahead of time, make a standard request without cachedOnly, or prefetch it with a HEAD request. Once the brand is indexed, cachedOnly=true requests return it instantly.

Color palette

Every brand response carries colors: the brand’s accent, dark, and light colors. Add palette=true to a Brand API request to get the brand’s full color system. palette=1 does the same:
Palette
The response gains one key, palette. The rest of the response does not change. A request without the parameter, or with another value, does not change. The palette object holds:
  • colors: the ranked colors. Each color has a role such as primary or background, and a context of identity, interface, or both. Each color also has the text color that reads best on it.
  • onPairs: the background and text pairs that the brand’s website uses, with their WCAG contrast.
  • themes: the light and dark themes that the website showed.
  • gradients: the gradients in the brand’s stylesheets.
  • logos: the colors of each logo and icon.
Each color also says where the website uses it:
  • usage: the elements that the website paints with the color, such as button backgrounds or link text, with counts and example labels. This is the field to read when you want to know what a color is for.
  • tokens: the website’s own CSS variable names for the color, such as hds-color-core-brand-500.
  • variants: the near-identical HEX codes that Brandfetch merged into the color.
When Brandfetch finds no color that it can defend as the brand’s color, no color has the role primary. An integration that shows one brand color has nothing to show for that brand. A color that only a theme, gradient, on-pair, or logo references is also in colors, with rank: null and member: true. To get the brand colors alone, keep the colors with a rank. If a brand has no palette yet, the first request builds one from the brand’s last crawl and stores it. This first request can take some seconds longer. Later requests get the stored palette. A palette built this way has no new render, so themes and onPairs can be empty. The next crawl of the brand replaces it.

Shortcut fields

logos and images list every logo and image Brandfetch holds for a brand, in each theme and format. Most integrations show one image of each kind. Every Brand API response carries four shortcut fields for that: logo, symbol, icon and banner. Each shortcut field picks the best match of its kind from logos or images. It holds that image’s address, or null when the brand has no image of that kind.
Use a shortcut field when you need one image of a kind. Use logos and images when you need every theme, format or variant. Fetch each address as it is given. Its c parameter is a client ID signed for your API key. The client ID is required, and a request without it is refused. Its t parameter changes when the image does, so you can cache the image for as long as you like. The image does not count towards your quota. It works in an <img> tag, from a browser, or from your server.
  • The address of a logo or symbol names its theme. theme/dark is a dark image, for light backgrounds. theme/light is a light image, for dark backgrounds.
  • If an image is gone when you fetch it, logo, symbol and banner return 404. icon returns a lettermark instead: the brand’s initial on a plain square.
  • All four shortcut fields are null for brands with isNsfw: true.

Homepage screenshot

A brand kit tells you the brand’s logos, colors and fonts. It does not show how the brand puts them together. A screenshot of the homepage does: the layout, the illustration style, the spacing, the tone of the imagery. When you generate designs or content for a brand, give the screenshot to your model next to the brand data. Every Brand API response carries a screenshot object with the address of the image and when Brandfetch took it:
Fetch url as it is given: the c parameter is a client ID signed for your API key, and the image does not count towards your quota. It works in an <img> tag, from a browser, or from your server. A request that drops the client ID is refused. The address returns a PNG of the top of the homepage at a desktop viewport, as Brandfetch saw it on its last visit. It is not a full-page capture. t is the time of capture: the address changes when Brandfetch takes a new screenshot, so you can cache the image for as long as you like.
  • screenshot is null when Brandfetch holds no screenshot of the homepage yet. A held brand gets one on its next visit. It is also null for brands with isNsfw: true.
  • The screenshot is what the crawler saw. For some sites that is a cookie banner, a blank page that had not finished loading, or a bot-protection page. Check the image before you rely on it.

Quotas and usage

When you sign up for a free developer account, you get 100 free requests. HEAD requests (see Prefetching brands) and 204 responses to cachedOnly requests (see Skip crawling) are not counted. A batch counts one request per identifier answered 200 (see Batch lookups). If you need to make more requests, please upgrade to a paid plan. When upgrading, you can confirm your quota by looking at the x-api-key-quota response header. To see your current month’s usage, look for the x-api-key-approximate-usage response header. We will also send you an email warning you upon reaching 80% of your quota. The API will return an HTTP status code 429 when the quota has been reached. In addition to a usage quota we also apply a request throughput limit to protect our service from abuse. By default, throughput is limited to a sustained 100 requests/second with some flexibility to accommodate bursts (30,000 requests / rolling 5 minute hard limit). You’ll receive an HTTP status code 429 when you exceed this limit. If your use-case requires higher throughput limits, contact us.

Overage billing

When you purchase a subscription plan, you are allotted a quota depending on the payment plan. When you make more API requests than your quota allows, rather than blocking requests which are over your quota, we apply overage billing. This means that you’ll never have any unexpected downtime. Requests over your quota are charged at an overage-fee rate. To set a spending limit, head to the Developer Dashboard and set a hard spending limit. Set this to $0 if you want to disable overage. Overage billing is not available on the free plan. To start using overage, please upgrade first to one of the paid plans.

Errors

When the Brand API refuses a request, the response says why in two places. The x-bf-error header carries one code. The JSON body repeats that code as error, beside the message you have always received and a docs link to this table. Branch on the code, not on the message text.
The status codes are the same as before, and so are the message texts, except that a bare Bad Request now says what was wrong with the request. The header and the two body fields are additions, so an existing integration keeps working. A 402 is the exception, whether no credential was sent or a payment was not accepted: its body is the payment protocols’ own, so only the header names the refusal (payment_required). API Gateway answers a few requests itself, for example a throughput limit. Those responses carry no x-bf-error header.

The request

The credential

The brand

Every 404 below uses one API credit: you asked us to look, and we looked. A pay-per-request 404 is settled too, except crawl_queued: that payment is not charged, the body says so in a payment object, and the same payment can be presented again for the retry. The code tells you whether asking again can help.

Our side

API Reference

For more details, refer to our API Reference.