AI crawlers

AI CRAWLERS

AI crawler tracking

See which AI and search crawlers read your site, verified against the operators own IP ranges.

Normal analytics cannot see crawlers, because they do not run JavaScript. To see them, a small Cloudflare Worker in front of your site forwards each crawler visit to your dashboard. Visitors are untouched: the Worker only reports requests whose user agent looks like a known crawler.

What you getDetail
Per crawler visits28 tracked crawlers from OpenAI, Anthropic, Google, Perplexity, Meta, Apple and more.
VerificationEach visit is checked against the IP ranges the operator publishes, so spoofed user agents are marked.
Pages and statusWhich paths are read and what status they returned, including 404s.

Set up

  1. Open Crawlers in your website and copy your API key from Settings.
  2. Create a Worker in Cloudflare and paste the snippet below.
  3. Add a secret named ANALYTICS_KEY with your API key.
  4. Route the Worker to your domain, for example example.com/*.
// Cloudflare Worker: forwards AI and search crawler visits to Analytics by 5H3LL.
// 1. Add a Worker secret named ANALYTICS_KEY containing your website's API key.
// 2. Route this Worker to your domain, for example example.com/*.
const CRAWLER_TOKENS = [
  'ChatGPT-User', 'Claude-User', 'Perplexity-User', 'Google-Agent',
  'Google-GeminiNotebook', 'Amzn-User', 'meta-externalfetcher', 'DuckAssistBot',
  'MistralAI-User', 'OAI-SearchBot', 'Claude-SearchBot', 'PerplexityBot',
  'Googlebot', 'Google-InspectionTool', 'Storebot-Google', 'bingbot',
  'Amzn-SearchBot', 'Applebot', 'DuckDuckBot', 'meta-webindexer',
  'GPTBot', 'ClaudeBot', 'Amazonbot', 'meta-externalagent',
  'CCBot', 'OAI-AdsBot', 'facebookexternalhit', 'GoogleOther',
];
const CRAWLERS = new RegExp(CRAWLER_TOKENS.join('|'), 'i');

export default {
  async fetch(request, env, ctx) {
    const response = await fetch(request);
    const userAgent = request.headers.get('user-agent') || '';
    if (CRAWLERS.test(userAgent)) {
      ctx.waitUntil(
        fetch('https://analytics.5h3ll.site/api/v1/crawls', {
          method: 'POST',
          headers: { authorization: 'Bearer ' + env.ANALYTICS_KEY, 'content-type': 'application/json' },
          body: JSON.stringify({ hits: [{ user_agent: userAgent, ip: request.headers.get('cf-connecting-ip'), url: request.url, status: response.status }] }),
        }).catch(() => {}),
      );
    }
    return response;
  },
};
npx wrangler secret put ANALYTICS_KEY

The snippet is generated from the same list as the crawler directory, so it always matches what we can classify.

Verification states

StateMeaning
verifiedThe user agent matched and the request came from an IP range the operator publishes.
claimedThe user agent matched, but the IP is outside the published ranges. Treat as possibly spoofed.
unverifiableThe operator publishes no IP ranges, so only the user agent can be checked.

Allowance

Crawler visits have their own monthly allowance on every plan, separate from page views. They never use your page view quota.

PlanCrawler visits per month
Free2,000
Starter10,000
Indie50,000
Growth250,000
Founder Lifetime250,000

Privacy

Crawler IP addresses are used to verify a visit and are not stored. Only daily counts per crawler, path and status are kept, for 400 days.

Something missing or wrong? Open a support ticket.