Cloudflare Workers (npm)
Add Centinel bot detection to an existing Cloudflare Worker using the npm package.
Overview
This guide covers adding Centinel to an existing Cloudflare Worker project via the npm package. Requests flow through the Centinel validator before reaching your worker, blocking bots while letting legitimate traffic through.
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.
Prerequisites
- Secret key from your dashboard
- An existing Cloudflare Worker project using Wrangler
Install
npm install @centinel/cloudflare-workerConfigure
Use a Wrangler secret. Do not add CENTINEL_SECRET_KEY to [vars]. A committed
wrangler.toml can expose the key.
npx 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.
Options
Pass a second argument to activateCentinel:
export default activateCentinel(myWorker, {
// Only validate paths matching this pattern (tested against pathname)
protectedPathsInclusion: /\/api(\/|$)/,
// Also validate requests whose query string matches this pattern
protectedQueryInclusion: /[?&]cat=/,
// 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: 500)
timeout: 5000,
// Structured JSON debug logging (default: false)
enableDebugging: true,
});Path matching
protectedPathsInclusion and protectedPathsExclusion are tested against the URL pathname (e.g. /api/users), not the full URL. Query strings and hostname are ignored.
Query matching
The worker tests protectedQueryInclusion against the query string with its leading ?, for example ?cat=nb&sort=p. The worker decodes percent-encoded parameter names first. The worker validates a request when the path pattern or the query pattern matches. The worker applies protectedPathsExclusion first.
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 | Validator timeout in milliseconds | 500 |
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 interstitial page from the validator.
Client → Centinel → Validator (redirect) → Interstitial pageFail-open behavior
If the validator is down, slow, or returns an error, the worker forwards the request without validation. This keeps the site available.
Centinel sends each request to your worker one time. CORS preflight (OPTIONS) requests do not go to the validator.
A bad secret key, an authentication failure, or a validator response error can also forward a protected request to your origin without validation.
After repeated failures, the worker uses exponential backoff (1s, 2s, 4s, ... up to 5 minutes). This prevents repeated calls to a broken endpoint.
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);Verify
Visit your site and confirm normal traffic works. A response includes
Server-Timing: validator;dur=<ms> when the worker gets a validator duration; a network error has
no timing header.
For log output, open Workers dashboard → Your worker → Logs → Begin log stream and look for
"service": "CentinelAnalytics" entries. Set CENTINEL_ENABLE_DEBUGGING = "true" for a JSON line
at each step.
Changelog
- v1.4.0 — Query string inclusion option
- v1.3.0 — 500 ms default validator timeout
- v1.2.1 — Edge case fixes