> ## Documentation Index
> Fetch the complete documentation index at: https://docs.brandfetch.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Use Brandfetch with Airtable

Airtable's Attachment fields store real files, not URLs, so there's no `IMAGE`-style formula like Sheets or Microsoft Excel. Instead, build the logo URL with a formula field, then turn it into a real attachment with a no-code automation, or a script if you want more control.

## Prerequisites

* A [Brandfetch account](https://developers.brandfetch.com/) with an active client ID
* A table with a text field holding each record's domain (this guide uses `Domain`)

## Build the logo URL

Add a formula field, e.g. named `Logo URL`, that concatenates the domain into a Brandfetch CDN URL the same way you would in Microsoft Excel or Sheets:

```
"https://cdn.brandfetch.io/" & {Domain} & "/icon.png?c=BRANDFETCH_CLIENT_ID"
```

Requesting `icon.png` (the default type, as a real file extension) matters here: Brandfetch serves logos in WebP by default with no extension in the URL, and both of those can trip up Airtable's URL-to-attachment conversion in the next step.

This field only holds text. Airtable won't render an image from it directly, it just feeds the next step.

## Turn the URL into an attachment

<Steps>
  <Step title="Add an Attachment field">
    Create a field named `Logo` with type **Attachment**.
  </Step>

  <Step title="Create an automation">
    Go to **Automations > Create automation**. Trigger on **When a record matches conditions** (e.g. `Domain` is not empty and `Logo` is empty), so it fires once per record instead of re-downloading on every edit.
  </Step>

  <Step title="Update the record">
    Add an **Update record** action on the same table. Set the `Logo` field's value to the `Logo URL` field from the trigger. Airtable downloads the file at that URL and stores it as a real attachment.
  </Step>
</Steps>

<Note>
  If a record's `Logo` field still doesn't populate, use the script method below, it lets you set the filename explicitly.
</Note>

## Scripting

The **Scripting** extension, or a **Run a script** step in Automations, gives you a loop over every record in one run and lets you set the attachment's filename directly:

```js Attach Logos theme={null}
let table = base.getTable("Companies");
let records = await table.selectRecordsAsync({ fields: ["Domain", "Logo"] });

const clientId = "BRANDFETCH_CLIENT_ID";

for (let record of records.records) {
    let domain = record.getCellValue("Domain");
    if (!domain || record.getCellValue("Logo")) continue;

    let url = `https://cdn.brandfetch.io/${domain}/w/512/h/512/icon.png?c=${clientId}`;

    await table.updateRecordAsync(record.id, {
        Logo: [{ url: url, filename: `${domain}.png` }],
    });
}
```

Swap `"Companies"` for your table's name. Since this loops over every record with an empty `Logo` field, it's safe to rerun after adding new rows. For large tables, run it in the Scripting extension rather than an automation, automation scripts stop after 30 seconds.

## Theme and fallback

Any [Logo API parameter](/logo-api/parameters) works the same way inside the URL, for example a dark-theme icon with a lettermark fallback, combined with the `.png` extension from above:

```
https://cdn.brandfetch.io/nike.com/theme/dark/fallback/lettermark/icon.png?c=BRANDFETCH_CLIENT_ID
```

## Access all brand data (logos, colors, company data...)

Attachments cover the logo, but a CRM-style base usually wants more: the brand's name, colors, and fonts. Those come from the [Brand API](/brand-api/overview), which the same script pattern can call with `fetch`. You'll need a Brand API key from the [API keys page](https://developers.brandfetch.com/dashboard/keys), this is a secret key, separate from the client ID used above.

Add text fields named `Brand Name`, `Accent Color`, and `Title Font`, then run:

```js Enrich With Brand Data theme={null}
let table = base.getTable("Companies");
let records = await table.selectRecordsAsync({
    fields: ["Domain", "Brand Name", "Accent Color", "Title Font"],
});

const apiKey = "YOUR_BRAND_API_KEY";

for (let record of records.records) {
    let domain = record.getCellValue("Domain");
    if (!domain || record.getCellValue("Brand Name")) continue;

    let res = await fetch(`https://api.brandfetch.io/v2/brands/domain/${domain}`, {
        headers: { Authorization: `Bearer ${apiKey}` },
    });
    if (!res.ok) continue;

    let brand = await res.json();
    let accent = brand.colors.find((c) => c.type === "accent");
    let titleFont = brand.fonts.find((f) => f.type === "title");

    await table.updateRecordAsync(record.id, {
        "Brand Name": brand.name,
        "Accent Color": accent ? accent.hex : "",
        "Title Font": titleFont ? titleFont.name : "",
    });
}
```

Each enriched record costs one Brand API request against your plan's quota; the `Brand Name` check keeps reruns from re-billing records that are already filled.

<Warning>
  Brand API keys are secret. Anyone who can open the base's automations or extensions can read the key, so keep the base's collaborator list in mind before pasting it in.
</Warning>
