Centinel AnalyticaCentinel Analytica
Platforms

Cloudflare Workers (npm)

Add Centinel bot detection to an existing Cloudflare Worker using the npm package.

Prerequisites

  • Secret key from your dashboard
  • An existing Cloudflare Worker project using Wrangler

Looking for the standalone version?

If you don't have an existing worker and want to paste a single file into the Cloudflare dashboard, see the Cloudflare Workers (standalone) guide instead.

Install

npm install @centinel/cloudflare-worker

Setup

Set your secret key

Add CENTINEL_SECRET_KEY to your wrangler.toml:

[vars]
CENTINEL_SECRET_KEY = "sk_live_..."

Or use a Wrangler secret (recommended for production):

wrangler secret put CENTINEL_SECRET_KEY
Wrap your worker

Import activateCentinel and wrap your existing worker:

import { activateCentinel } from '@centinel/cloudflare-worker';

const myWorker = {
    async fetch(request, env, ctx) {
        // Your existing worker code
        return new Response('Hello from my app');
    },
};

export default activateCentinel(myWorker);

Requests now go through the Centinel validator before reaching your worker. Bots are blocked; legitimate traffic passes through.

Deploy
wrangler deploy
Verify

Visit your site and confirm normal traffic works. Check worker logs for "service": "CentinelAnalytics" entries. Protected paths include a Server-Timing: validator;dur=<ms> response header showing how long the validator call took.

Options

Pass a second argument to activateCentinel:

export default activateCentinel(myWorker, {
    // Only validate paths matching this pattern (tested against full URL)
    protectedPathsInclusion: /\/api(\/|$)/,

    // Skip paths matching this pattern (default: static assets like .css, .js, .png)
    protectedPathsExclusion: /\.(css|js|png|jpg|woff2)$/i,

    // Validator API timeout in milliseconds (default: 10000)
    timeout: 5000,

    // Structured JSON debug logging (default: false)
    enableDebugging: true,
});

Path matching

protectedPathsInclusion and protectedPathsExclusion are tested against the full URL (e.g. https://example.com/api/users), not just the pathname. Write your regex accordingly.

Environment variables

Options can be overridden per-request via environment variables. Set in wrangler.toml, the dashboard, or .dev.vars:

VariableWhat it doesDefault
CENTINEL_SECRET_KEYAPI key sent to the validator(none, required)
CENTINEL_VALIDATOR_URLValidator API endpointhttps://validator.centinelanalytica.com/validate
CENTINEL_TIMEOUTRequest timeout in ms10000
CENTINEL_ENABLE_DEBUGGINGSet to "true" for debug logsfalse

Env vars take precedence over options passed to activateCentinel(), so you can use different settings per environment without changing code.

How requests flow

  1. Request arrives at your Cloudflare Worker
  2. activateCentinel checks the path against inclusion/exclusion patterns
  3. If protected, it POSTs request metadata (URL, method, IP, headers, _centinel cookie) to the validator API
  4. The validator returns a decision:

Request is forwarded to your worker. If the validator set cookies, they're added to the response.

Client → Centinel → Validator (allow) → Your Worker → Client

Your worker is not called. The client receives an HTML error page with the status code from the validator (default 403).

Client → Centinel → Validator (block) → 403 HTML page

Your worker is not called. The client receives a base64-decoded challenge page from the validator.

Client → Centinel → Validator (redirect) → Challenge page

The URL didn't match any protected endpoint on the validator side. Request is forwarded to your worker normally.

Client → Centinel → Validator (not_matched) → Your Worker → Client

Fail-open behavior

If the validator is down, slow, or returns an error, the request is forwarded to your worker. Your site stays up even if the validator has problems.

After repeated failures, the worker backs off exponentially (1s, 2s, 4s, ... up to 5 minutes) to stop hammering a broken endpoint. It retries once the backoff expires.

Standalone mode

If you don't have an existing worker, the default export works on its own:

import centinelWorker from '@centinel/cloudflare-worker';
export default centinelWorker;

TypeScript

Type definitions are included:

import { activateCentinel, CentinelOptions, CentinelHandler } from '@centinel/cloudflare-worker';

const options: CentinelOptions = {
    protectedPathsInclusion: /\/api\//,
    timeout: 5000,
};

export default activateCentinel(myWorker, options);

Monitoring

  • Real-time logs: Workers dashboard → Your worker → Logs → Begin log stream
  • Debug mode: Set CENTINEL_ENABLE_DEBUGGING = "true" in your env vars for detailed JSON logs at each step
  • Server-Timing header: Every response from a protected path includes Server-Timing: validator;dur=<ms> showing how long the validator call took

Changelog

v1.1.2

  • Response headers from /validate are now applied to all outgoing responses (block, redirect, and allow). Headers like Content-Type are no longer hardcoded — they come from the validator.
  • Validator API requests now include a User-Agent header identifying the integration name and version.

On this page