> For an index of all Botscent documentation, see https://botscent.nibnalin.me/llms.txt.

# Cloudflare Workers

Add the server half of Botscent to a Cloudflare Worker and check the install.

Add the server half of Botscent to a Cloudflare Worker. The server half wraps the Worker's `fetch` handler. The handler gets the request's own verdict as a fourth argument. For the page half, see [A script tag](/docs/script-tag), [React](/docs/react), [Vue](/docs/vue) or the page for the framework your site uses.

If your Worker uses Hono, follow [Hono](/docs/hono) instead.

## Before you start

You need:

* A Cloudflare Worker with a `fetch` handler
* Node.js 22.12 or later, to install the package

## 1. Install the package

Install `botscent` from npm.

```sh title="Terminal"
npm install botscent
```

With pnpm, yarn or bun, use their `add` command.

## 2. Add the server half

In `src/index.ts`, wrap the `fetch` handler with `withBotscent`.

```ts title="src/index.ts"
import { withBotscent } from 'botscent/workers'

export default {
  fetch: withBotscent(async (request) => fetch(request)),
}
```

The adapter now inspects each request before your handler runs.

The adapter also reads Cloudflare's `request.cf`, so the platform's verified-bot field counts as evidence.

A Worker runs per request in front of the cache, so the transport is on by default. For an agent's document navigation, the adapter adds a `Server-Timing` entry with `Cache-Control: no-store`. The page half reads the entry.

Behind Workers Cache, a cached page carries no entry. For the details, see [From the server to the page](/docs/server-to-page).

If the Worker stores HTML with the Cache API, set `transport: 'never'`:

```ts title="src/index.ts"
import { withBotscent } from 'botscent/workers'

export default {
  fetch: withBotscent(async (request) => fetch(request), { transport: 'never' }),
}
```

The adapter then sends no entry to the page.

## 3. Add the page half

The server half reads only what each request declares. The page half finds agents that operate a browser, from inside the page.

If the Worker sends your HTML, add `<script defer src="/botscent.js"></script>` to each page. Serve `node_modules/botscent/dist/botscent.js` at `/botscent.js` from your own origin. If a frontend framework renders your pages, add the page half there instead. The [Quickstart](/docs/quickstart) lists every framework.

## 4. Read the verdict

In the handler, read the fourth argument.

```ts title="src/index.ts"
import { withBotscent } from 'botscent/workers'

export default {
  fetch: withBotscent(async (request, _env, _ctx, verdict) => {
    if (new URL(request.url).pathname === '/verdict') return Response.json(verdict)
    return fetch(request)
  }),
}
```

A request from `curl` to `/verdict` gets `{"type":"agent","agent_name":"curl","reasons":["ua.declared-agent-token"]}`.

To give an agent access, use `isVerified` from `botscent/server` on this verdict. Use no other field for access. See [The trust model](/docs/trust-model).

## 5. Check the install

Deploy the Worker. Then run the check against one of its pages.

```sh title="Terminal"
npx botscent check https://your-site.example/
```

The `server-half` and `page-script` checks print `pass`, and the check exits with code 0. If Workers Cache answered the check's request, `server-half` prints `unknown`. Run the check again after the cached copy expires. If a check fails, see [Verify your install](/docs/verify).

## Next steps

* [The verdict](/docs/verdict): what `type`, `agent_name` and `reasons` mean.
* [Netlify](/docs/netlify): use the same adapter in a Netlify Edge Function.
* [Server API (TypeScript)](/docs/server-api): every option of the Workers adapter and of `inspect`.
* [Workers example](https://github.com/nalinbhardwaj/botscent/tree/main/examples/workers): the tested Worker.
