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

# Company autocomplete

> Find your company as you type, with a logo on every result, powered by the Brand Search API

export const BrandedSelectMenuDemo = () => {
  const options = [{
    name: "Stripe",
    domain: "stripe.com"
  }, {
    name: "GitHub",
    domain: "github.com"
  }, {
    name: "Linear",
    domain: "linear.app"
  }, {
    name: "Discord",
    domain: "discord.com"
  }, {
    name: "Slack",
    domain: "slack.com"
  }];
  const [open, setOpen] = useState(false);
  const [selected, setSelected] = useState(options[0]);
  return <div className="w-full max-w-[260px]">
      <label className="text-[13px] font-medium text-[#6b7280]">Company</label>
      <button onClick={() => setOpen(o => !o)} className="mt-1 w-full flex items-center gap-2.5 py-2 px-3 rounded-lg border border-[#63636333] hover:border-[#6363664d] transition-colors">
        <img noZoom src={`https://cdn.brandfetch.io/domain/${selected.domain}/w/48/h/48/fallback/lettermark?c=1bfwsmEH20zzEfSNTed`} alt={`${selected.name} logo`} className="w-6 h-6 rounded shrink-0" />
        <span className="flex-1 text-left text-sm font-medium">{selected.name}</span>
        <span className="text-[#9ca3af] text-xs">{open ? "▴" : "▾"}</span>
      </button>
      {open && <div className="mt-1 rounded-lg border border-[#63636333] bg-white dark:bg-[#1c1d1f] overflow-hidden">
          {options.map(o => <button key={o.domain} onClick={() => {
    setSelected(o);
    setOpen(false);
  }} className={`w-full flex items-center gap-2.5 py-2 px-3 text-left hover:bg-[#6363631f] transition-colors ${o.domain === selected.domain ? "bg-[#6363630d]" : ""}`}>
              <img noZoom src={`https://cdn.brandfetch.io/domain/${o.domain}/w/48/h/48/fallback/lettermark?c=1bfwsmEH20zzEfSNTed`} alt={`${o.name} logo`} className="w-6 h-6 rounded shrink-0" />
              <span className="text-sm">{o.name}</span>
            </button>)}
        </div>}
    </div>;
};

export const BrandAutocompleteDemo = () => {
  const [query, setQuery] = useState("");
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);
  const [selected, setSelected] = useState(null);
  const [open, setOpen] = useState(false);
  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, 5) : []);
          setLoading(false);
        }
      } catch {
        if (reqId.current === id) {
          setResults([]);
          setLoading(false);
        }
      }
    }, 250);
    return () => clearTimeout(t);
  }, [query]);
  return <div className="w-full max-w-[340px]">
      <style>{`
        @keyframes bf-fade-in { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }
      `}</style>
      <div className="relative">
        <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="absolute left-3 top-1/2 -mt-[7.5px] opacity-40">
          <circle cx="11" cy="11" r="7" />
          <path d="m21 21-4.3-4.3" />
        </svg>
        <input className="w-full box-border py-[9px] pl-9 pr-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 any brand..." value={query} onFocus={() => setOpen(true)} onChange={e => {
    setQuery(e.target.value);
    setSelected(null);
    setOpen(true);
  }} />
      </div>

      {open && query.trim() && !selected && <div className="mt-2 rounded-xl border border-[#63636326] bg-white dark:bg-[#1c1d1f] shadow-sm overflow-hidden animate-[bf-fade-in_150ms_ease_both]">
          {results.length === 0 ? <div className="py-3 px-3.5 text-[13px] text-[#9ca3af]">
              {loading ? "Searching…" : `No brands found for “${query.trim()}”`}
            </div> : results.map(r => <button key={r.brandId} onClick={() => {
    setSelected(r);
    setQuery(r.name || r.domain);
    setOpen(false);
  }} className="w-full flex items-center gap-2.5 py-2 px-3 text-left cursor-pointer bg-transparent border-0 transition-colors duration-100 hover:bg-[#6363631f]">
                <img noZoom src={r.icon} alt={`${r.name || r.domain} logo`} className="w-7 h-7 rounded-md shrink-0" />
                <span className="min-w-0">
                  <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>
              </button>)}
        </div>}

      {selected && <div className="mt-2 flex items-center gap-3 rounded-xl border border-[#63636326] bg-white dark:bg-[#1c1d1f] p-3 animate-[bf-fade-in_150ms_ease_both]">
          <img noZoom src={selected.icon} alt={`${selected.name || selected.domain} logo`} className="w-9 h-9 rounded-lg shrink-0" />
          <div className="min-w-0">
            <div className="text-sm font-semibold truncate">{selected.name || selected.domain}</div>
            <div className="text-xs text-[#6b7280] truncate">
              {selected.domain} · <span className="font-mono">{selected.brandId}</span>
            </div>
          </div>
        </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>;

"Type your company name" fields fail quietly: typos, subsidiaries, brands whose trading name doesn't match the legal one. The [Brand Search API](/brand-search-api/overview) turns that field into a type-ahead: a partial name goes in, matching brands come out, each with its name, domain, and logo.

## Match brand names to their domain and logo

The classic type-ahead: debounced live search with each result showing the brand's icon, name, and domain. Selecting a result hands you the `domain` and `brandId`, the keys you pass to Brandfetch's other APIs.

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

  <Tab title="Code">
    ```tsx BrandAutocomplete.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 BrandAutocomplete() {
      const [query, setQuery] = useState("");
      const [results, setResults] = useState<BrandResult[]>([]);
      const [loading, setLoading] = useState(false);
      const [selected, setSelected] = useState<BrandResult | null>(null);
      const [open, setOpen] = useState(false);
      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, 5) : []);
              setLoading(false);
            }
          } catch {
            if (reqId.current === id) {
              setResults([]);
              setLoading(false);
            }
          }
        }, 250);
        return () => clearTimeout(t);
      }, [query]);

      return (
        <div className="w-full max-w-[340px]">
          <style>{`@keyframes bf-fade-in { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }`}</style>
          <div className="relative">
            <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" className="absolute left-3 top-1/2 -mt-[7.5px] opacity-40">
              <circle cx="11" cy="11" r="7" />
              <path d="m21 21-4.3-4.3" />
            </svg>
            <input
              className="box-border w-full rounded-lg border border-[#63636333] bg-transparent py-[9px] pl-9 pr-3 text-sm text-inherit outline-none focus:border-[#0084FF] focus:shadow-[0_0_0_3px_#0084ff26]"
              placeholder="Search any brand..."
              value={query}
              onFocus={() => setOpen(true)}
              onChange={(e: ChangeEvent<HTMLInputElement>) => {
                setQuery(e.target.value);
                setSelected(null);
                setOpen(true);
              }}
            />
          </div>

          {open && query.trim() && !selected && (
            <div className="mt-2 animate-[bf-fade-in_150ms_ease_both] overflow-hidden rounded-xl border border-[#63636326] bg-white shadow-sm dark:bg-[#1c1d1f]">
              {results.length === 0 ? (
                <div className="px-3.5 py-3 text-[13px] text-[#9ca3af]">
                  {loading ? "Searching…" : `No brands found for “${query.trim()}”`}
                </div>
              ) : (
                results.map((r) => (
                  <button
                    key={r.brandId}
                    onClick={() => {
                      setSelected(r);
                      setQuery(r.name || r.domain);
                      setOpen(false);
                    }}
                    className="flex w-full cursor-pointer items-center gap-2.5 border-0 bg-transparent px-3 py-2 text-left transition-colors duration-100 hover:bg-[#6363631f]"
                  >
                    <img src={r.icon} alt={`${r.name || r.domain} logo`} className="h-7 w-7 shrink-0 rounded-md" />
                    <span className="min-w-0">
                      <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>
                  </button>
                ))
              )}
            </div>
          )}

          {selected && (
            <div className="mt-2 flex animate-[bf-fade-in_150ms_ease_both] items-center gap-3 rounded-xl border border-[#63636326] bg-white p-3 dark:bg-[#1c1d1f]">
              <img src={selected.icon} alt={`${selected.name || selected.domain} logo`} className="h-9 w-9 shrink-0 rounded-lg" />
              <div className="min-w-0">
                <div className="truncate text-sm font-semibold">{selected.name || selected.domain}</div>
                <div className="truncate text-xs text-[#6b7280]">
                  {selected.domain} · <span className="font-mono">{selected.brandId}</span>
                </div>
              </div>
            </div>
          )}
        </div>
      );
    }
    ```
  </Tab>
</Tabs>

<Prompt description="Want a live brand search autocomplete in your app? This prompt gives your AI coding tool everything it needs to build it in your framework." actions={["copy", "cursor"]}>
  Build a brand search autocomplete input. As the user types, query Brandfetch's Brand Search API directly from the browser, it's free and needs only a client ID (get one at `https://developers.brandfetch.com/register`):

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

  The response is a JSON array of matches, each with `name`, `domain`, `brandId`, and `icon` (a ready-to-use logo URL). Render a dropdown under the input where each row shows the brand's icon, name, and domain. Hotlink the returned `icon` URL as-is (the URLs expire after 24 hours, so don't persist them). Don't render the response's `claimed` or `verified` fields as a badge, they're not meant to be surfaced as a trust signal in your UI.

  Debounce keystrokes by \~250-300ms, search from the first character, discard out-of-order responses, and show nothing until the user types (no default result list). When the user selects a result, keep its `domain` and `brandId`, those are the identifiers you pass to Brandfetch's Logo API and Brand API for logos and full brand data.

  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 input">
    Fire a search after a short pause in typing (\~200 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`, exactly the three things an autocomplete row needs. Show a skeleton row while the request is in flight.
  </Step>

  <Step title="Keep the domain">
    The selected `domain` is the stable key for everything that follows, store it, and chain into the [Brand API](/brand-api/overview) for colors, fonts, and company data when you need more than the logo.
  </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. Create a client ID on the [Developer Portal](https://developers.brandfetch.com/register), no attribution required.

## Measuring impact

Track the search-to-select rate on the field and completion of the flow it lives in. [Pitch reported a 3× increase in activation](https://brandfetch.com/developers/customers/pitch) after building company search into their product.

## 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" icon="palette" href="/brand-api/overview">
    Fetch full brand data once a user selects a result.
  </Card>

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