> ## 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.

# Logo picker

> Let users search a brand and drop the right logo asset into the document, powered by the Brand Search API and Brand API

export const LogoPickerDemo = () => {
  const [query, setQuery] = useState("");
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);
  const [picked, setPicked] = useState(null);
  const reqId = useRef(0);
  useEffect(() => {
    const q = query.trim();
    if (!q) {
      setResults([]);
      setLoading(false);
      return;
    }
    setLoading(true);
    const id = ++reqId.current;
    const t = setTimeout(async () => {
      try {
        const res = await fetch(`https://api.brandfetch.io/v2/search/${encodeURIComponent(q)}?c=1bfwsmEH20zzEfSNTed`);
        const data = await res.json();
        if (reqId.current === id) {
          setResults(Array.isArray(data) ? data.slice(0, 4) : []);
          setLoading(false);
        }
      } catch {
        if (reqId.current === id) {
          setResults([]);
          setLoading(false);
        }
      }
    }, 250);
    return () => clearTimeout(t);
  }, [query]);
  return <div className="w-full max-w-[360px] rounded-xl border border-[#63636333] bg-white dark:bg-[#1c1d1f] overflow-hidden">
      <div className="py-3 px-4 border-b border-[#63636326] text-sm font-semibold">Insert brand logo</div>
      <div className="p-4">
        <input className="w-full box-border py-2 px-3 rounded-lg border border-[#63636333] text-sm outline-none bg-transparent text-inherit focus:border-[#0084FF] focus:shadow-[0_0_0_3px_#0084ff26]" placeholder="Search brands..." value={query} onChange={e => {
    setQuery(e.target.value);
    setPicked(null);
  }} />
        <div className="mt-3 flex flex-col gap-1.5 min-h-[196px]">
          {results.map(r => {
    const isPicked = picked && picked.brandId === r.brandId;
    return <button key={r.brandId} onClick={() => setPicked(r)} className={`flex w-full items-center gap-2.5 py-2 px-3 rounded-lg border text-left cursor-pointer bg-transparent transition-colors duration-100 hover:bg-[#63636314] ${isPicked ? "border-[#0084FF]" : "border-[#63636326]"}`}>
                <img noZoom src={r.icon} alt={`${r.name || r.domain} logo`} className="w-8 h-8 rounded-md shrink-0" />
                <span className="min-w-0 flex-1">
                  <span className="block truncate text-sm font-medium text-inherit">{r.name || r.domain}</span>
                  <span className="block text-xs text-[#6b7280] truncate">{r.domain}</span>
                </span>
                {isPicked && <svg viewBox="0 0 24 24" width="16" height="16" className="shrink-0">
                    <circle cx="12" cy="12" r="11" fill="#0084FF" />
                    <path d="m7.5 12 3 3 6-6" fill="none" stroke="white" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>}
              </button>;
  })}
          {results.length === 0 && <div className="flex flex-1 items-center justify-center text-[13px] text-[#9ca3af]">
              {loading ? "Searching…" : query.trim() ? `No brands found for “${query.trim()}”` : "Search for a brand to see its logo"}
            </div>}
        </div>
        <button className="mt-3 w-full py-2 rounded-lg text-white text-sm font-medium border-0 transition-colors" style={{
    background: picked ? "#0084FF" : "#9ca3af",
    cursor: picked ? "pointer" : "default"
  }}>
          {picked ? `Insert ${picked.name || picked.domain} logo` : "Select a logo"}
        </button>
      </div>
    </div>;
};

export const Preview = ({children}) => <div className="relative rounded-xl border border-[#63636333] bg-[#6363630d] pt-12 px-8 pb-8 mt-4 mb-4 overflow-hidden">
    <style>{`
      .bf-preview-body img { margin: 0 !important; max-width: none; }
      .bf-preview-body ul, .bf-preview-body ol { margin: 0; padding: 0; }
      .bf-preview-body li { margin: 0 !important; padding-left: 0 !important; }
      .bf-preview-body li::before, .bf-preview-body li::marker { content: none !important; display: none !important; }
      .bf-preview-body p { margin: 0; }
    `}</style>
    <span className="absolute top-3.5 left-[18px] text-[11px] font-semibold tracking-[0.06em] uppercase text-[#636363b3]">
      Preview
    </span>
    <div className="bf-preview-body flex justify-center">{children}</div>
  </div>;

Presentation, design, and document editors all need the same thing: a way for users to find a brand and insert its logo without leaving the canvas. The [Brand Search API](/brand-search-api/overview) powers the autocomplete, a partial name goes in, matching brands come out with a ready-to-use logo. And once a brand is selected, the [Brand API](/brand-api/overview) returns all of its available logos, logo, symbol, and icon, in light and dark themes, so users can view every variant and insert the one that fits.

## Instantly insert logos to your tool

The same API powering an "insert logo" dialog, like a presentation or design editor where users search a brand and drop its logo into the document. This is the pattern behind the [Pitch integration](https://brandfetch.com/developers/customers/pitch).

<Tabs>
  <Tab title="Preview">
    <Preview>
      <LogoPickerDemo />
    </Preview>
  </Tab>

  <Tab title="Code">
    ```tsx LogoPicker.tsx theme={null}
    import { useState, useEffect, useRef, type ChangeEvent } from "react";

    const CLIENT_ID = "YOUR_CLIENT_ID"; // free client ID from developers.brandfetch.com/register

    type BrandResult = { brandId: string; name: string; domain: string; icon: string };

    export function LogoPicker() {
      const [query, setQuery] = useState("");
      const [results, setResults] = useState<BrandResult[]>([]);
      const [loading, setLoading] = useState(false);
      const [picked, setPicked] = useState<BrandResult | null>(null);
      const reqId = useRef(0);

      useEffect(() => {
        const q = query.trim();
        if (!q) {
          setResults([]);
          setLoading(false);
          return;
        }
        setLoading(true);
        const id = ++reqId.current;
        const t = setTimeout(async () => {
          try {
            const res = await fetch(`https://api.brandfetch.io/v2/search/${encodeURIComponent(q)}?c=${CLIENT_ID}`);
            const data = await res.json();
            if (reqId.current === id) {
              setResults(Array.isArray(data) ? data.slice(0, 4) : []);
              setLoading(false);
            }
          } catch {
            if (reqId.current === id) {
              setResults([]);
              setLoading(false);
            }
          }
        }, 250);
        return () => clearTimeout(t);
      }, [query]);

      return (
        <div className="w-full max-w-[360px] overflow-hidden rounded-xl border border-[#63636333] bg-white dark:bg-[#1c1d1f]">
          <div className="border-b border-[#63636326] px-4 py-3 text-sm font-semibold">Insert brand logo</div>
          <div className="p-4">
            <input
              className="box-border w-full rounded-lg border border-[#63636333] bg-transparent px-3 py-2 text-sm text-inherit outline-none focus:border-[#0084FF] focus:shadow-[0_0_0_3px_#0084ff26]"
              placeholder="Search brands..."
              value={query}
              onChange={(e: ChangeEvent<HTMLInputElement>) => {
                setQuery(e.target.value);
                setPicked(null);
              }}
            />
            <div className="mt-3 flex min-h-[196px] flex-col gap-1.5">
              {results.map((r) => {
                const isPicked = picked?.brandId === r.brandId;
                return (
                  <button
                    key={r.brandId}
                    onClick={() => setPicked(r)}
                    className={`flex w-full cursor-pointer items-center gap-2.5 rounded-lg border bg-transparent px-3 py-2 text-left transition-colors duration-100 hover:bg-[#63636314] ${
                      isPicked ? "border-[#0084FF]" : "border-[#63636326]"
                    }`}
                  >
                    <img src={r.icon} alt={`${r.name || r.domain} logo`} className="h-8 w-8 shrink-0 rounded-md" />
                    <span className="min-w-0 flex-1">
                      <span className="block truncate text-sm font-medium text-inherit">{r.name || r.domain}</span>
                      <span className="block truncate text-xs text-[#6b7280]">{r.domain}</span>
                    </span>
                    {isPicked && (
                      <svg viewBox="0 0 24 24" width="16" height="16" className="shrink-0">
                        <circle cx="12" cy="12" r="11" fill="#0084FF" />
                        <path d="m7.5 12 3 3 6-6" fill="none" stroke="white" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" />
                      </svg>
                    )}
                  </button>
                );
              })}
              {results.length === 0 && (
                <div className="flex flex-1 items-center justify-center text-[13px] text-[#9ca3af]">
                  {loading ? "Searching…" : query.trim() ? `No brands found for “${query.trim()}”` : "Search for a brand to see its logo"}
                </div>
              )}
            </div>
            <button
              className="mt-3 w-full rounded-lg border-0 py-2 text-sm font-medium text-white transition-colors"
              style={{ background: picked ? "#0084FF" : "#9ca3af", cursor: picked ? "pointer" : "default" }}
            >
              {picked ? `Insert ${picked.name || picked.domain} logo` : "Select a logo"}
            </button>
          </div>
        </div>
      );
    }
    ```
  </Tab>
</Tabs>

<Prompt description="Want a Pitch-style 'insert brand logo' picker? This prompt gives your AI coding tool everything it needs to build it in your framework." actions={["copy", "cursor"]}>
  Build an "insert brand logo" picker dialog for an editor. It has a search input at the top; as the user types, query Brandfetch's Brand Search API from the browser (free, client ID only; get one at `https://developers.brandfetch.com/register`):

  ```
  GET https://api.brandfetch.io/v2/search/{query}?c=YOUR_CLIENT_ID
  ```

  Render the results as a vertical list of selectable rows (limit to \~4), each showing the brand's `icon` image, `name`, and `domain` from the response. Clicking a row selects it (accent border and a checkmark) and enables an "Insert" button that places the logo into the document. Debounce keystrokes by \~300ms and hotlink the returned `icon` URLs as-is.

  For the inserted asset, render a high-resolution or themed variant from the Logo API using the selected result's `domain`: `https://cdn.brandfetch.io/domain/{domain}?c=YOUR_CLIENT_ID` (add `/type/logo`, `/theme/light`, or size segments as needed).

  Use the Search API the intended way: call it straight from the browser with your client ID (not a secret key), debounce input between keystrokes, and hotlink the returned `icon` URLs as-is without caching them (they expire after 24h). It should enhance a larger app, not replicate Brandfetch.
</Prompt>

## Implementation

<Steps>
  <Step title="Debounce the search">
    Fire a search after a short pause in typing (\~250 ms). Requests can go straight from the browser, the API is free and authenticates with your client ID as a query parameter.

    ```text theme={null}
    GET https://api.brandfetch.io/v2/search/{name}?c=YOUR_CLIENT_ID
    ```
  </Step>

  <Step title="Render the results">
    Each match carries the brand's `name`, `domain`, and `icon`. Lay the results out as selectable rows and hotlink the returned `icon` URLs as-is, don't cache them, they expire after 24 hours.
  </Step>

  <Step title="Show all available logos">
    On selection, fetch the full brand record with the [Brand API](/brand-api/overview) (server-side, so the API key stays secret) using the picked `domain`. Its `logos` array carries every variant the brand has, `type` (logo, symbol, icon), `theme` (light, dark), and `formats` (SVG, PNG, WebP), so you can display them all and let the user pick the exact asset to insert.

    ```bash theme={null}
    curl "https://api.brandfetch.io/v2/brands/domain/{domain}" \
      --header "Authorization: Bearer YOUR_API_KEY"
    ```
  </Step>

  <Step title="Insert the logo">
    Place the chosen variant's `src` into the document. For a lighter setup without the Brand API call, you can also render a single asset straight from the [Logo API](/logo-api/overview), choosing the size, type, and theme that fit the canvas.

    ```text theme={null}
    https://cdn.brandfetch.io/domain/{domain}/type/logo?c=YOUR_CLIENT_ID
    ```
  </Step>
</Steps>

Review the [usage guidelines and rate limits](/brand-search-api/overview#usage-guidelines) before going live, search requests should come from your users' browsers, debounced between keystrokes.

## Pricing

The Brand Search API is free, and the Logo API is free with a client ID. Create one on the [Developer Portal](https://developers.brandfetch.com/register), no attribution required. Listing every available logo variant costs one [Brand API](/brand-api/overview) brand fetch per selected brand, and domain-level caching means each brand is fetched once. See [plans](https://brandfetch.com/developers/pricing) for quotas.

## Going further

<CardGroup cols={3}>
  <Card title="Brand Search API" icon="code" href="/brand-search-api/overview">
    Match brand names to their domain and logo.
  </Card>

  <Card title="Brand API reference" icon="palette" href="/reference/brand-api-domain">
    The `logos` array: every variant, theme, and format.
  </Card>

  <Card title="Get started" icon="rocket" href="https://developers.brandfetch.com/register">
    Create a free account and start building.
  </Card>
</CardGroup>
