Skip to main content
Documentation

Capture AI crawlers on Cloudflare.

Last reviewed 2026-10-19

A Worker reports AI crawlers from a proxied zone without blocking responses, on any plan. On Enterprise, Logpush sends complete edge logs, including cached responses, with no code.

Choose a method#

MethodPlansCoverage
Workers (most sites)Any planReports supported AI crawlers from a proxied zone without blocking responses
Logpush (recommended on Enterprise)EnterprisePassive, complete edge-log coverage, including cached responses

Both need the site's DNS record proxied (orange cloud). You need your site ID and server secret from Settings → Connection (see Hosting integrations). In the dashboard, Connect analytics → Hosting integrations → Cloudflare shows these steps with your values filled in.

Workers#

Set up with your coding agent

Hand the setup to Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own; the agent asks you for the server secret. In the dashboard, Install with AI fills them in.

Prompt
Install Virent AI crawler analytics on example.com with a Cloudflare Worker.

Site ID: <your-site-id>
Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value.

Steps:
1. Create a Worker in the Cloudflare dashboard.
2. Replace the starter code with:

```javascript
const SITE_ID = "<your-site-id>"
const INGEST = "https://stage.virent.app/v1/ingest/bot"

// Send eligible requests for classification by Virent.
const ASSET = /\.(?!(?:html?|txt|md|xml|json|pdf)$)[a-z0-9]+$/i

export default {
  async fetch(request, env, ctx) {
    const response = await fetch(request)
    ctx.waitUntil(report(request, response, env.VIRENT_INGEST_SECRET).catch(() => {}))
    return response
  },
}

async function report(request, response, secret) {
  if (request.method !== "GET") return

  const url = new URL(request.url)
  const userAgent = request.headers.get("user-agent") || ""
  if (ASSET.test(url.pathname)) return

  const cf = request.cf || {}

  await fetch(INGEST, {
    method: "POST",
    headers: {
      "content-type": "application/json",
      "x-api-key": secret,
    },
    body: JSON.stringify({
      siteId: SITE_ID,
      url: url.origin + url.pathname,
      host: url.host,
      path: url.pathname,
      query: {},
      method: request.method,
      statusCode: response.status,
      userAgent,
      accept: request.headers.get("accept"),
      acceptLanguage: request.headers.get("accept-language"),
      referer: null,
      country: cf.country || null,
      requestId: request.headers.get("cf-ray") || crypto.randomUUID(),
      timestamp: new Date().toISOString(),
    }),
  })
}
```

3. Add a route of *example.com/* on the zone serving the site.
4. Under DNS → Records, keep the site A, AAAA, or CNAME record proxied (orange cloud).

Reporting must run in ctx.waitUntil. Do not hard-code the secret in a committed repo if you can use Worker secrets instead.

Create a Worker#

In the Cloudflare dashboard, open Workers, click Create application, start with Hello World, choose any Worker name, then deploy it.

Store the connection secret#

Run this for the Worker and paste your Virent server secret when prompted. The secret stays out of the Worker source.

SH
npx wrangler secret put VIRENT_INGEST_SECRET

Paste the tracking code#

Open Edit code, replace the starter code with this snippet and your site ID, and deploy again. Reporting runs in ctx.waitUntil and never blocks the site response.

worker.js
const SITE_ID = "<your-site-id>"const INGEST = "https://stage.virent.app/v1/ingest/bot"// Send eligible requests for classification by Virent.const ASSET = /\.(?!(?:html?|txt|md|xml|json|pdf)$)[a-z0-9]+$/iexport default {  async fetch(request, env, ctx) {    const response = await fetch(request)    ctx.waitUntil(report(request, response, env.VIRENT_INGEST_SECRET).catch(() => {}))    return response  },}async function report(request, response, secret) {  if (request.method !== "GET") return  const url = new URL(request.url)  const userAgent = request.headers.get("user-agent") || ""  if (ASSET.test(url.pathname)) return  const cf = request.cf || {}  await fetch(INGEST, {    method: "POST",    headers: {      "content-type": "application/json",      "x-api-key": secret,    },    body: JSON.stringify({      siteId: SITE_ID,      url: url.origin + url.pathname,      host: url.host,      path: url.pathname,      query: {},      method: request.method,      statusCode: response.status,      userAgent,      accept: request.headers.get("accept"),      acceptLanguage: request.headers.get("accept-language"),      referer: null,      country: cf.country || null,      requestId: request.headers.get("cf-ray") || crypto.randomUUID(),      timestamp: new Date().toISOString(),    }),  })}

Route your domain through it#

On the Worker, open Domains, add a Route such as *example.com/*, and point it at the zone serving your site.

Verify your proxy status#

Under DNS → Records, make sure the site's A, AAAA or CNAME record has the orange cloud and is set to Proxied. Gray-cloud traffic bypasses the Worker. Then send a test crawler request.

Logpush#

Set up with your coding agent

Hand the setup to Claude Code, Codex or another coding agent. Replace the site ID and example.com with your own; the agent asks you for the server secret. In the dashboard, Install with AI fills them in.

Prompt
Configure Cloudflare Logpush so example.com sends HTTP request logs to Virent AI crawler analytics.

Site ID: <your-site-id>
Use the full Virent server secret from the Connect dialog. Do not use the masked preview "vha_sk_••••" as the real value.

Steps:
1. In the example.com zone, create a Logpush job with HTTP destination https://stage.virent.app/api/ingest/cloudflare-logpush?header_x-api-key=%3Cpaste-your-server-secret%3E.
2. Dataset: HTTP requests.
3. Job name: Virent Crawler Logs.
4. Fields: ClientRequestHost, ClientRequestMethod, ClientRequestURI, EdgeResponseStatus, EdgeStartTimestamp, RayID, ClientRequestUserAgent, ClientRequestReferer, ClientIP, ClientCountry, WorkerSubrequest.
5. Keep DNS proxied (orange cloud).

WorkerSubrequest lets Virent ignore the site's own Worker subrequests. Do not commit the server secret.

Select a destination#

In your site's zone, create a Logpush job, select HTTP destination, paste this endpoint and continue. Replace the header_x-api-key value with your server secret (URL-encoded); the dashboard fills it in after Rotate + reveal.

HTTP destination
https://stage.virent.app/api/ingest/cloudflare-logpush?header_x-api-key=%3Cpaste-your-server-secret%3E

Select the dataset#

Choose HTTP requests.

Configure the Logpush job#

SettingValue
Job nameVirent Crawler Logs
FieldsClientRequestHost, ClientRequestMethod, ClientRequestURI, EdgeResponseStatus, EdgeStartTimestamp, RayID, ClientRequestUserAgent, ClientRequestReferer, ClientIP, ClientCountry, WorkerSubrequest

Keep the sampling rate at 1.0 (100%). WorkerSubrequest lets Virent ignore requests made by your own Workers so they are not counted twice. Raw client IPs are hashed immediately and never stored.

Verify your proxy status#

Under DNS → Records, make sure the site's A, AAAA or CNAME record has the orange cloud and is set to Proxied. Then send a test crawler request.