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-workerSetup
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_KEYImport 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.
wrangler deployVisit 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:
| Variable | What it does | Default |
|---|---|---|
CENTINEL_SECRET_KEY | API key sent to the validator | (none, required) |
CENTINEL_VALIDATOR_URL | Validator API endpoint | https://validator.centinelanalytica.com/validate |
CENTINEL_TIMEOUT | Request timeout in ms | 10000 |
CENTINEL_ENABLE_DEBUGGING | Set to "true" for debug logs | false |
Env vars take precedence over options passed to activateCentinel(), so you can use different settings per environment without changing code.
How requests flow
- Request arrives at your Cloudflare Worker
activateCentinelchecks the path against inclusion/exclusion patterns- If protected, it POSTs request metadata (URL, method, IP, headers,
_centinelcookie) to the validator API - 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 → ClientYour 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 pageYour worker is not called. The client receives a base64-decoded challenge page from the validator.
Client → Centinel → Validator (redirect) → Challenge pageThe 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 → ClientFail-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
/validateare now applied to all outgoing responses (block, redirect, and allow). Headers likeContent-Typeare no longer hardcoded — they come from the validator. - Validator API requests now include a
User-Agentheader identifying the integration name and version.