picked

Track AI crawlers on your server: GPTBot, ClaudeBot and the rest

To track GPTBot, ChatGPT-User, ClaudeBot and other AI crawlers on your own server, add our open-source package to your Next.js, Express or Fetch API app, or POST the hits from any language. It sends only AI bot visits, after the response, and never slows down or breaks a request.

npm install @picked-so/crawler-detect

Picked is an AI visibility tool for SEO and marketing agencies, and B2B SaaS teams. Every day it asks ChatGPT, Claude, Gemini, Perplexity and Google's AI answers the prompts your buyers ask, records which brands and pages they name, and writes the article built to become the source they quote.

How it works

What does the package do?

@picked-so/crawler-detect matches each request's user agent against the AI bots Picked knows. When one matches, it sends the hit (host, path, user agent, IP, status and time) to your project's private ingest address. Every other request is ignored.

  1. After the response

    The send happens once your page is out, so a visitor never waits for it, and a failed send never touches the request.

  2. Verified by IP

    Anyone can claim to be ChatGPT-User. Picked checks each hit's IP against the ranges OpenAI, Anthropic, Perplexity, Google and Apple publish, and by reverse DNS for Amazonbot, so a fake doesn't count when Verified only is on.

  3. Visits from AI answers (0.2 and later)

    A page view whose referrer is an AI assistant, or whose utm_source names one (utm_source=chatgpt.com), is sent too: the page, the user agent and the referrer's origin (https://chatgpt.com, never the chat's address). No IP address, no cookie. referrals: false turns it off.

  4. A secret address

    The address carries your project's ingest key, so it belongs in server code and an environment variable, never in the browser. Disconnecting issues a new key and the old one stops working.

Set up

How do you add it?

Four steps. The AI crawlers guide in the docs has them next to the Cloudflare and Vercel connections.

  1. 1

    Open Analytics

    In your project, choose Your server. The dialog shows your address and the code for your stack.

  2. 2

    Install the package

    Add it from npm with the command at the top of this page, and set PICKED_INGEST_URL to the address from the dialog.

  3. 3

    Add one line

    The table below says where it goes for your framework.

  4. 4

    Deploy

    The first AI crawler visit shows up once a bot next opens a page.

  • Next.js

    In proxy.ts (Next.js 16), or middleware.ts on 13 to 15: call trackAiCrawler(request, event)
  • Express

    Before your routes: app.use(aiCrawlers()). Behind a proxy, set app.set("trust proxy", true) so the IP is the bot's
  • Workers, Hono, Bun, Deno, Remix, SvelteKit, Astro

    Anything that handles a Fetch API request: call trackAiCrawler with the request, the response and the context
  • Any other server

    POST up to 200 hits at once as JSON, from any language

Any language

What does the plain HTTP call look like?

Send a hit when the User-Agent matches one of the bots Picked knows (the dialog lists the pattern), as JSON to your address:

  • host

    Your domain
  • path

    The path requested
  • userAgent

    The full user agent string
  • ip

    The bot's address, not your proxy's
  • status

    The response status you sent
  • at

    When it happened, in milliseconds
  • country

    Optional: a two-letter code, such as the one your CDN gives

Limits

What should you know before adding it?

  1. From the day you deploy

    The package sends what happens after it runs. There is no history. Visits from AI answers need version 0.2 or later.

  2. Your server sees the bot's IP only if the proxy passes it on

    Behind a load balancer or a CDN, make sure the real client address reaches your code, or Picked can't verify it.

  3. One source per project

    A project reads its crawlers from your server, Cloudflare or Vercel, not two at once, or a visit counts twice.

  4. A few bots stay unverified

    Meta and some others publish no IP ranges, so their hits show, but not as verified.

  5. The catalogue is ours

    The package carries its own list of bots. When a new AI crawler appears, we add it and publish a new version, so update the package now and then.

When not to

When this won't work for you

Honest answer: sometimes this isn't worth your time.

  • A static site with no server code

    A static host that runs nothing on the request can't send a hit. Use Cloudflare if it sits behind it, or Vercel if it runs there.

  • You don't want to touch the code

    Cloudflare needs no code at all, only a sign-in.

  • You need history

    Only Cloudflare reads the last 30 days back.

Sources

How we checked

Questions

Frequently asked questions

Short answers, each one checked against the product as built or the docs we link to.

The AI crawlers Picked knows: `GPTBot`, `OAI-SearchBot` and `ChatGPT-User` from OpenAI, `ClaudeBot`, `Claude-SearchBot` and `Claude-User` from Anthropic, `PerplexityBot` and `Perplexity-User`, Google's AI crawlers, Applebot and others. The list is in the package.

No. The send happens after the response is out, and a failure never touches the request.

Yes, if you'd rather add the package to your `proxy.ts` than use a log drain. It only sends AI bot visits, so it doesn't carry the drain's volume.

Yes. The package and its code are public on GitHub under the Picked organisation.

Yes. It contains your project's ingest key. Keep it in an environment variable on the server, never in code the browser loads.

Behind a proxy or CDN, your app sees the proxy's address unless it is told to trust the forwarded header. Set the real client address, as in Express's `trust proxy` setting, or the hit can't be verified.

Find out what ChatGPT and Google AI say about you

Add your domain and the prompts your buyers ask. Unlimited seats for your whole team, and no promises we can't keep.