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

# Prefetch for Faster Response

> Warm the Context.dev brand cache with POST /utility/prefetch so the next /brand/retrieve lookup returns in under a second instead of ~7s cold.

A Brand lookup for a domain Context.dev hasn't seen before triggers a full crawl of the website and socials, which typically takes around 7s, up to a minute at p99, with a hard platform cap of 5 minutes. Once cached, the same lookup returns in under a second, and about 60% of all Brand API calls already hit that warm cache (full breakdown in the [latency table](#latency) below).

Prefetching warms the cache ahead of time. Call `POST /utility/prefetch` as soon as you know the domain or email, and the user-facing `/brand/retrieve` lands on a warm cache. The request body carries a `type` (currently only `"brand"`) and an `identifier` object with exactly one of `domain` or `email`:

```json theme={null}
{ "type": "brand", "identifier": { "domain": "stripe.com" } }
{ "type": "brand", "identifier": { "email": "founder@stripe.com" } }
```

The canonical case is a signup or onboarding form: fire a prefetch the moment the email field validates, and by the time the user submits, `/brand/retrieve` returns instantly.

<Badge color="green">0 Credits</Badge>. No rate limit. Subscriber-only.

<Note>
  The legacy `POST /brand/prefetch` and `POST /brand/prefetch-by-email` endpoints (and their SDK methods `utility.prefetch` / `utility.prefetchByEmail`) still work unchanged. New integrations should use `POST /utility/prefetch` so future identifier types are picked up automatically.
</Note>

<CodeGroup>
  ```bash cURL theme={null}
  # 1. As soon as the email field validates, fire a prefetch.
  curl -X POST https://api.context.dev/v1/utility/prefetch \
    -H "Authorization: Bearer $CONTEXT_DEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "type": "brand",
      "identifier": { "email": "founder@acme.com" }
    }'

  # 2. On submit, the real call hits a warm cache.
  curl -X POST https://api.context.dev/v1/brand/retrieve \
    -H "Authorization: Bearer $CONTEXT_DEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"type":"by_domain","domain":"acme.com"}'
  ```

  ```typescript TypeScript theme={null}
  import ContextDev from "context.dev";

  const client = new ContextDev({ apiKey: process.env.CONTEXT_DEV_API_KEY });

  // 1. As soon as the email field validates, fire a prefetch.
  async function onEmailEntered(email: string) {
    // Fire-and-forget. Ignore errors (disposable email, etc.).
    client.utility
      .prefetch({ type: "brand", identifier: { email } })
      .catch(() => {});
  }

  // 2. On submit, the real call hits a warm cache.
  async function onSignupComplete(email: string) {
    const domain = email.split("@")[1];
    const { brand } = await client.brand.retrieve({ type: "by_domain", domain });
    return brand;
  }
  ```

  ```python Python theme={null}
  import os
  from context.dev import ContextDev

  client = ContextDev(api_key=os.environ["CONTEXT_DEV_API_KEY"])

  # 1. As soon as the email field validates, fire a prefetch.
  def on_email_entered(email: str) -> None:
      try:
          client.utility.prefetch(type="brand", identifier={"email": email})
      except Exception:
          pass  # disposable / personal email; safe to ignore

  # 2. On submit, the real call hits a warm cache.
  def on_signup_complete(email: str):
      domain = email.split("@", 1)[1]
      return client.brand.retrieve(type="by_domain", domain=domain).brand
  ```

  ```ruby Ruby theme={null}
  require "context_dev"

  client = ContextDev::Client.new(api_key: ENV.fetch("CONTEXT_DEV_API_KEY"))

  # 1. Fire a prefetch the moment the email validates.
  def on_email_entered(client, email)
    client.utility.prefetch(type: "brand", identifier: { email: email })
  rescue StandardError
    # disposable / personal email; safe to ignore
  end

  # 2. On submit, the real call hits a warm cache.
  def on_signup_complete(client, email)
    domain = email.split("@", 2).last
    client.brand.retrieve(body: { type: :by_domain, domain: domain }).brand
  end
  ```

  ```go Go theme={null}
  package main

  import (
      "context"
      "os"
      "strings"

      contextdev "github.com/context-dot-dev/context-go-sdk"
      "github.com/context-dot-dev/context-go-sdk/option"
  )

  func main() {
      client := contextdev.NewClient(
          option.WithAPIKey(os.Getenv("CONTEXT_DEV_API_KEY")),
      )
      ctx := context.TODO()

      // 1. Fire a prefetch on email entry. Ignore errors.
      _, _ = client.Utility.Prefetch(ctx, contextdev.UtilityPrefetchParams{
          Type: "brand",
          Identifier: contextdev.UtilityPrefetchParamsIdentifier{
              Email: "founder@acme.com",
          },
      })

      // 2. On submit, the user-facing call lands warm.
      domain := strings.Split("founder@acme.com", "@")[1]
      _, _ = client.Brand.Get(ctx, contextdev.BrandGetParams{
          OfByDomain: &contextdev.BrandGetParamsBodyByDomain{Domain: domain},
      })
  }
  ```

  ```php PHP theme={null}
  <?php

  use ContextDev\Client;

  $client = new Client(apiKey: getenv('CONTEXT_DEV_API_KEY'));

  // 1. As soon as the email field validates, fire a prefetch.
  function onEmailEntered(string $email): void
  {
      global $client;
      try {
          $client->utility->prefetch(type: 'brand', identifier: ['email' => $email]);
      } catch (Throwable) {
          // disposable / personal email; safe to ignore
      }
  }

  // 2. On submit, the real call hits a warm cache.
  function onSignupComplete(string $email)
  {
      global $client;
      $domain = explode('@', $email, 2)[1];
      return $client->brand->retrieve(type: 'by_domain', domain: $domain)->brand;
  }
  ```
</CodeGroup>

## How the cache works

* **Cache TTL is up to 3 months.** After that, the next call triggers a refresh in the background.
* **The cache is shared across the account.** A prefetch from a backend job warms the cache for a user-facing call seconds later.
* **Prefetch is fire-and-forget.** The endpoint returns immediately after queuing the work. You do not wait for the prefetch before calling `/brand/retrieve`.
* **Prefetch by email skips known free/disposable providers.** Calls against `gmail.com`, `yahoo.com`, `outlook.com`, and the 10,000+ disposable services return a `422` (`FREE_EMAIL_DETECTED` or `DISPOSABLE_EMAIL_DETECTED`) that you can safely ignore.
* **Provide exactly one identifier.** Sending both `domain` and `email` (or neither) returns a `400`.

## Latency

| Pattern                                                | p50  | p90  | p99     |
| ------------------------------------------------------ | ---- | ---- | ------- |
| Cold `/brand/retrieve` (no prefetch)                   | 7s   | 18s  | \~1 min |
| Cached `/brand/retrieve` (after prefetch or prior hit) | \<1s | \<1s | \<1s    |

Every second of prefetch lead time turns a multi-second (sometimes minute-long) cold wait into a sub-second user-facing call.

## What prefetch does not do

* **It does not speed up scraping endpoints.** `/web/scrape/*`, `/web/crawl`, `/web/screenshot`, and `/brand/ai/*` are not affected by the brand cache. Each call fetches the target URL.
* **It does not preempt rate limits.** Prefetch itself is rate-limit-free, but the eventual `/brand/retrieve` call still counts against your plan's per-minute rate limit.
* **It does not return brand data.** The endpoint queues the work and returns `{ status, message, type, domain, key_metadata }`. To read the brand, call `/brand/retrieve` separately.

## Related resources

<CardGroup cols={2}>
  <Card title="Rate limits" icon="gauge" href="/optimization/rate-limits">
    How the per-plan per-minute limits interact with cached and prefetched
    calls.
  </Card>

  <Card title="Best practices" icon="list-check" href="/optimization/best-practices">
    Where prefetching fits in the broader integration pattern.
  </Card>

  <Card title="Troubleshooting" icon="triangle-exclamation" href="/optimization/troubleshooting">
    Cold-hit timeouts and how to handle them.
  </Card>

  <Card title="Get brand data" icon="address-card" href="/guides/get-brand-data">
    The endpoint prefetching warms.
  </Card>
</CardGroup>
