# Website Logo & Brand Kit Extractor: Colors, Fonts (`maliksaid/website-logo-brand-kit`) Actor

Extract the logo, favicon and app icons, brand colors, fonts and social profiles of any company website. Logos come from JSON-LD, the header, apple-touch-icon and the manifest. Colors come from theme-color, CSS and logo pixels. HTTP only. robots.txt respected.

- **URL**: https://apify.com/maliksaid/website-logo-brand-kit.md
- **Developed by:** [Malik Said](https://apify.com/maliksaid) (community)
- **Categories:** Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 brand kits

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Website Logo & Brand Kit Extractor: Colors, Fonts

Website Logo & Brand Kit Extractor gets the logo, favicon, brand colors, fonts and social profiles of any company website. Give it a list of domains. For each domain it returns one brand kit row.

The Actor reads each site's own files: the homepage, the web app manifest and the stylesheets. It ranks every logo candidate it finds and loads the best ones to check that they are real images. It does not use any third-party logo API. It uses plain HTTP, with no browser.

Use it to add logos to a CRM or lead list, to fill company cards in an app, to build a brand reference for a design project, or to watch a list of companies for rebrands.

### Website logo and brand kit data you get

One row per domain. The main fields:

| Field | What it holds |
|---|---|
| `domain`, `finalUrl`, `siteName`, `title` | The domain, its homepage after redirects, and the site name |
| `logoUrl`, `logoSource`, `logoFormat`, `logoWidth`, `logoHeight` | The chosen logo, where it came from, and its real format and size |
| `logoFileUrl` | Download link of the stored logo file (with Save logo files on) |
| `iconUrl`, `faviconUrl`, `favicons` | Square app icon (apple-touch-icon or manifest icon), favicon, and every icon declared in the page head |
| `logoCandidates` | Every logo and icon candidate, ranked, with format, size and whether it loaded |
| `brandColors` | Brand colors as hex, strongest signals first, each with its sources |
| `logoColors` | Main colors of the logo pixels, with their share in percent |
| `themeColor`, `manifestThemeColor`, `manifestBackgroundColor`, `tileColor` | Colors the site declares for browsers and apps |
| `cssColorVariables`, `cssTopColors` | CSS variables with brand-like names, and the most used colors in the CSS |
| `primaryFont`, `fonts` | Font families named in the CSS, with use counts and whether the site loads the font file |
| `socialProfiles` | Company profile links: LinkedIn company page, X, Facebook, Instagram, YouTube, TikTok, GitHub, Pinterest, Threads, Vimeo |

### How the website logo is chosen

The Actor collects candidates from these places, in this order of trust:

1. The organisation logo in the page's JSON-LD data.
2. An inline SVG or an image inside the header logo or the home link.
3. Other images whose file name or alt text names the site.
4. apple-touch-icon and web app manifest icons.
5. The Open Graph image, when its file name says logo.
6. mask-icon and favicon files, and `/favicon.ico` when the page declares no icon.

It loads up to 3 logo candidates and the first icon of each type. A file that does not load, is not an image, or is far too big for a logo (such as a banner photo) is not chosen. The `logoCandidates` list shows every candidate, so you can pick another one.

### How brand colors are found

`brandColors` merges these signals. Close shades merge into one entry.

- `theme-color`: the theme-color meta tag.
- `manifest`: theme_color in the web app manifest.
- `logo`: the main colors of the logo pixels, read with sharp. White, black and grey are left out.
- `css-variable`: CSS custom properties named primary, brand, accent and similar. In color scales only the base steps (400 to 600) count.
- `css-frequent`: the most used strong colors in the CSS.
- `tile-color`: the msapplication-TileColor meta tag.

An inline SVG logo often takes its color from the page CSS. Its pixel colors then show as black or grey, and the `notes` field says so. The CSS signals still give the brand color in that case.

### Example output

A real row for cloudflare.com, shortened:

```json
{
    "domain": "cloudflare.com",
    "finalUrl": "https://www.cloudflare.com/",
    "siteName": "Cloudflare",
    "logoUrl": "https://www.cloudflare.com/logo.svg",
    "logoSource": "json-ld",
    "logoFormat": "svg",
    "logoWidth": 341,
    "logoHeight": 156,
    "faviconUrl": "https://www.cloudflare.com/favicon.ico",
    "themeColor": "#ff4801",
    "brandColors": [
        { "hex": "#ff4801", "sources": ["theme-color"] },
        { "hex": "#f38020", "sources": ["logo"] },
        { "hex": "#faae40", "sources": ["logo"] },
        { "hex": "#ff5e1f", "sources": ["css-variable", "css-frequent"] }
    ],
    "logoColors": [
        { "hex": "#f38020", "share": 82.6, "neutral": false },
        { "hex": "#faae40", "share": 17.4, "neutral": false }
    ],
    "primaryFont": "FT Kunst Grotesk",
    "fonts": [
        { "family": "FT Kunst Grotesk", "uses": 33, "webFont": true, "sources": ["font-face", "css"] },
        { "family": "Apercu Mono Pro", "uses": 11, "webFont": true, "sources": ["font-face", "css"] }
    ],
    "socialProfiles": {
        "github": "https://github.com/cloudflare",
        "linkedin": "https://www.linkedin.com/company/cloudflare",
        "x": "https://x.com/cloudflare"
    },
    "stylesheetsRead": 4,
    "robotsTxtFound": true
}
```

### How to extract website logos and brand kits

1. Open the Actor and paste your domains into **Domains**, one per line. Plain domains and full URLs both work.
2. Turn on **Save logo files** if you want the logo files themselves. Each run then stores one logo file per domain in its key-value store.
3. Click **Start**. Brand kits appear in the Output tab as each domain finishes.
4. Download the results as JSON, CSV or Excel, or read them through the Apify API.

Domains that could not be read are listed with the reason in the `FAILED_DOMAINS` record of the run's key-value store. They are not charged.

### Input

| Field | Default | What it does |
|---|---|---|
| `domains` | 3 example domains | Domains or homepage URLs to read |
| `analyzeLogoColors` | true | Read the main colors of the chosen logo |
| `saveLogoFiles` | false | Store the chosen logo file per domain and return its link |
| `maxStylesheets` | 4 | CSS files to read per homepage, for fonts and colors |
| `monitorMode` | false | Return a domain only when its logo, colors or fonts changed since the last monitor run |
| `stateKey` | default | Name of the monitor memory. Use one key per domain list |
| `maxItems` | 100 | Stop after this many brand kits. 0 means no limit |

Example input:

```json
{
    "domains": ["apify.com", "www.mozilla.org", "wordpress.org"],
    "saveLogoFiles": true,
    "maxItems": 100
}
```

### Pricing

The Actor uses pay per event pricing:

- $0.02 per run start.
- $0.002 per brand kit saved. That is $2 per 1,000 domains.

A run of 500 domains costs at most $1.02. Domains that fail (blocked, offline, no logo found) cost nothing. Monitor mode charges only for domains that changed.

### Limits and good practice

- The Actor reads robots.txt for every host it touches, including CDN hosts for CSS and images, and skips any file robots.txt disallows.
- It waits at least 500 ms between two requests to the same host. Each request stops after 30 seconds.
- It never tries to pass a bot check, CAPTCHA or login. Sites behind Cloudflare, AWS WAF or similar checks, and sites that answer 403, are listed as failed. In a test of 168 well-known domains, 125 gave a brand kit.
- It refuses private and local network addresses.
- Sites that build their page with JavaScript only may show no logo to a plain HTTP reader. Those domains are listed as failed and not charged.
- Fonts come from the CSS text. A font loaded only by a script is not seen.

### Trademarks and fair use

Logos, names and brand assets are trademarks of their owners. This Actor only finds the files each company publishes on its own website. Check that your use of a logo is allowed, for example to identify the company in a list or a CRM. Do not use a logo in a way that suggests the owner endorses you.

The Actor returns company data only. It skips personal LinkedIn profiles, share links and posts, and it reads no email addresses or phone numbers.

### FAQ

**Can it get logos from sites behind a bot check?** No. The Actor does not bypass protections. It lists those domains as failed and does not charge for them.

**Why is `logoUrl` empty but `logoFormat` is svg?** The logo is an inline SVG inside the page, so it has no URL of its own. Turn on Save logo files to get it as an SVG file through `logoFileUrl`.

**Can I watch companies for a rebrand?** Yes. Turn on monitor mode and schedule the Actor. It returns a domain again only when its chosen logo, brand colors or fonts change.

**Does it use Clearbit, Brandfetch or another logo API?** No. Every value comes from the company's own website.

### Related Actors

- [Website Technology Detector & Company Profile](https://apify.com/maliksaid/website-tech-stack): finds the tech stack of the same domains (CMS, analytics, ecommerce, hosting), plus company profile fields. Run both on one domain list to build a full company card.

### Support

Open an issue on the Actor's Issues tab. Include the run ID and the domain that gave a wrong result.

# Actor input Schema

## `domains` (type: `array`):

Enter company domains or homepage URLs, one per line, for example stripe.com or https://www.ikea.com. The Actor reads the homepage of each domain.

## `analyzeLogoColors` (type: `boolean`):

Read the pixels of the chosen logo and return its main colours with their share. Turn off to save a little time.

## `saveLogoFiles` (type: `boolean`):

Store the chosen logo file of each domain in the run's key-value store and return its download link in logoFileUrl.

## `maxStylesheets` (type: `integer`):

Read up to this many CSS files per homepage to find fonts and colours. Files on the site's own host come first. Set 0 to read only the CSS inside the page.

## `monitorMode` (type: `boolean`):

Return a domain only when its logo, brand colours or fonts changed since earlier monitor-mode runs with the same state key. Schedule the Actor with this on to watch for rebrands.

## `stateKey` (type: `string`):

Name the memory that monitor mode uses. Use a different key for each separate domain list.

## `maxItems` (type: `integer`):

Stop after saving this many brand kits. The default keeps test runs short and cheap. Set 0 for no limit.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "www.mozilla.org",
    "wordpress.org"
  ],
  "analyzeLogoColors": true,
  "saveLogoFiles": false,
  "maxStylesheets": 4,
  "monitorMode": false,
  "stateKey": "default",
  "maxItems": 100
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `failed` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "domains": [
        "apify.com",
        "www.mozilla.org",
        "wordpress.org"
    ],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("maliksaid/website-logo-brand-kit").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "domains": [
        "apify.com",
        "www.mozilla.org",
        "wordpress.org",
    ],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("maliksaid/website-logo-brand-kit").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "domains": [
    "apify.com",
    "www.mozilla.org",
    "wordpress.org"
  ],
  "maxItems": 100
}' |
apify call maliksaid/website-logo-brand-kit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maliksaid/website-logo-brand-kit"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/JgXc4sAIGckKHhrN5/builds/CmgNxGE9CaWM62dR7/openapi.json
