Install with an AI assistant
This page is the canonical install reference for people and for AI coding assistants. Every package name, import and option below exists in the published packages. If a snippet you were given elsewhere uses a name that is not on this page, it is wrong.
A machine-readable index of these docs is at docs.webdecoy.com/llms.txt, and the full text is at llms-full.txt.
The best path: connect the assistant to WebDecoy
Section titled “The best path: connect the assistant to WebDecoy”If your assistant supports MCP (Claude Code, Claude.ai, ChatGPT, Codex, Cursor and others), connect it to WebDecoy’s hosted MCP server at https://mcp.webdecoy.com/mcp. Its get_install_guide tool returns the install steps for your stack with your site’s public IDs already filled in, and get_install_status proves the install is reporting. Nothing has to be copied by hand.
In Claude Code:
/plugin marketplace add WebDecoy/claude-plugins/plugin install webdecoy@webdecoyThen run /webdecoy:install. For every other assistant, follow Connect an AI assistant.
A prompt to paste into your assistant
Section titled “A prompt to paste into your assistant”Without MCP, paste this into ChatGPT, Claude, Cursor, Copilot or any other assistant working in your codebase:
Install WebDecoy bot detection in this project.
1. Read https://docs.webdecoy.com/installation/install-with-ai/ and use only the package names, imports, options and environment variables shown there. Do not invent any other WebDecoy package, option or variable.2. Detect this project's stack and pick the matching section. If none matches, use the browser detection script.3. Leave WebDecoy in its default monitor mode. Do not set mode: 'enforce'.4. Never write a secret into the code or a committed file. Read secrets from environment variables, tell me each variable's name and where to create its value, and let me set it myself.5. Tell me how to verify the install, using the test request on that page.Before you start
Section titled “Before you start”Most installs need a free account at app.webdecoy.com and a site in it. Where a step needs a value from the dashboard:
| Value | Where it comes from | Secret? |
|---|---|---|
WEBDECOY_API_KEY (sk_live_...) |
API Keys in the dashboard | Yes |
data-aid, data-sid on the script tag |
Detection Scripts, Copy snippet | No |
WEBDECOY_SITE_KEY, WEBDECOY_SCANNER_ID |
The platform’s step in Setup | No |
WEBDECOY_SENSOR_KEY |
The platform’s step in Setup | Yes |
The Node packages do not read WEBDECOY_API_KEY by themselves. Pass it as apiKey, as every snippet below does. Without an apiKey the Node middleware still runs its local rules (the tripwire by default, and any rate limits you configure), but nothing reports to your dashboard.
Every Node framework adapter starts in monitor mode: it records verdicts and serves every request. Switch to mode: 'enforce' only after you have reviewed what it would have blocked.
Pick your stack
Section titled “Pick your stack”| Your stack | Install | Code change? |
|---|---|---|
| Next.js | @webdecoy/nextjs |
Yes |
| Express | @webdecoy/express |
Yes |
| Fastify | @webdecoy/fastify |
Yes |
| Hono (Workers, Bun, Deno, Node) | @webdecoy/hono |
Yes |
| Any other Node.js server | @webdecoy/node |
Yes |
| WordPress | The webdecoy plugin |
No |
| Shopify | The WebDecoy Shopify app | No |
| Cloudflare | One-click edge sensor | No |
| Vercel | Integration (log drain), optional middleware | No, or one file |
| Netlify | Extension plus environment variables | No |
| PHP (Laravel, Symfony, plain PHP) | composer require webdecoy/sensor |
Yes |
| Anything else | A script tag | One line of HTML |
Next.js
Section titled “Next.js”npm install @webdecoy/nextjs @webdecoy/node// middleware.ts (project root, or src/ if you use it)import { withWebDecoy } from '@webdecoy/nextjs';
export default withWebDecoy({ apiKey: process.env.WEBDECOY_API_KEY!,});
// Protect the routes that matter and leave static assets alone.export const config = { matcher: ['/api/:path*', '/checkout/:path*'],};Details: Next.js middleware. To refuse scrapers on chosen paths with a clearance token instead, see Vercel middleware (clearance).
Express
Section titled “Express”npm install @webdecoy/express @webdecoy/nodeimport express from 'express';import { webdecoy } from '@webdecoy/express';
const app = express();
app.use(webdecoy({ apiKey: process.env.WEBDECOY_API_KEY, skipPaths: ['/health'],}));
app.get('/', (req, res) => { // req.webdecoy carries the detection (decision, confidence, threat_level, bot_detected) res.send('ok');});Mount it before your routes. Behind a proxy, pass trustProxy (a hop count, 'cloudflare', 'railway', or your proxies’ CIDRs). Details: Express middleware.
Fastify
Section titled “Fastify”npm install @webdecoy/fastify @webdecoy/nodeimport Fastify from 'fastify';import webdecoy from '@webdecoy/fastify';
const app = Fastify();
await app.register(webdecoy, { apiKey: process.env.WEBDECOY_API_KEY, skipPaths: ['/health'],});
// request.webdecoy carries the detection on every routeBehind a proxy, pass trustProxy to the WebDecoy plugin, not to Fastify. Details: Fastify plugin.
npm install @webdecoy/hono @webdecoy/nodeimport { Hono } from 'hono';import { webdecoy } from '@webdecoy/hono';
const app = new Hono();
app.use('*', webdecoy({ apiKey: process.env.WEBDECOY_API_KEY, skipPaths: ['/health'],}));
app.get('/', (c) => { // c.get('webdecoy') carries the decision; in monitor mode this is where it surfaces return c.text('ok');});
export default app;On Cloudflare Workers, process.env needs the nodejs_compat compatibility flag and a recent compatibility date. Behind Cloudflare, trustProxy: 'cloudflare' is stronger than the default of one trusted hop.
For any other fetch-style runtime (Bun, Deno, Astro, SvelteKit, Remix), createFetchGuard() from @webdecoy/node is the same implementation the Hono adapter wraps:
import { createFetchGuard } from '@webdecoy/node';
const guard = createFetchGuard({ apiKey: process.env.WEBDECOY_API_KEY });
export default { async fetch(request: Request): Promise<Response> { const { response } = await guard.check(request); if (response) return response; // only ever set in enforce mode return guard.decorate(await handle(request)); // handle() is your app },};Any other Node.js server
Section titled “Any other Node.js server”npm install @webdecoy/nodeimport http from 'node:http';import { WebDecoy } from '@webdecoy/node';
const wd = new WebDecoy({ apiKey: process.env.WEBDECOY_API_KEY });
http.createServer(async (req, res) => { const decision = await wd.protect({ method: req.method, path: new URL(req.url, 'http://localhost').pathname, ip: req.socket.remoteAddress ?? '', user_agent: req.headers['user-agent'], headers: Object.fromEntries( Object.entries(req.headers).map(([name, value]) => [name, String(value)]) ), timestamp: Date.now(), });
// protect() returns a decision and blocks nothing itself. // Log decision.conclusion ('ALLOW', 'DENY', 'CHALLENGE' or 'ERROR') first; // refuse with a 403 when decision.allowed is false only once you are ready. res.end('ok');}).listen(3000);protect() fails open: if WebDecoy cannot be reached, allowed is true. Behind a proxy, use resolveClientIp() from the same package to get the real client address. Details: Node.js SDK.
WordPress
Section titled “WordPress”wp plugin install webdecoy --activateOr in WordPress Admin: Plugins, Add New, search WebDecoy, Install Now, Activate. It runs locally with no account or API key and starts in monitor mode. Details: WordPress plugin.
Shopify
Section titled “Shopify”Install the WebDecoy app from the Shopify App Store, then enable the WebDecoy Bot Detection app embed in your published theme. There is no code to add and no separate WebDecoy login. Details: Shopify app.
Cloudflare (one click)
Section titled “Cloudflare (one click)”If your traffic is proxied through Cloudflare (orange cloud), install the edge sensor from the dashboard. There is no code and no package:
- Open Integrations, Cloudflare and choose Connect with Cloudflare.
- Open Edge Sensor, pick the zone and route, and choose Deploy edge sensor.
It sees crawlers that never run JavaScript. Details: Cloudflare edge sensor.
Vercel
Section titled “Vercel”For reporting with no code change, install the WebDecoy Vercel integration. It sets up a log drain and needs a Vercel Pro or Enterprise team. Details: Vercel integration.
To refuse scrapers on chosen paths, add the clearance middleware. Set WEBDECOY_SITE_KEY, WEBDECOY_SCANNER_ID and WEBDECOY_SENSOR_KEY from Enforcement, Setup in the Vercel project, then:
// middleware.ts, Next.jsimport { withClearance } from '@webdecoy/nextjs';
export default withClearance();
export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],};// middleware.ts, Astro, SvelteKit, Nuxt, Remix or a static siteexport { default } from '@webdecoy/node/vercel';It follows the site’s WebDecoy mode, monitor until you switch it. Details: Vercel middleware (clearance).
Netlify
Section titled “Netlify”- Install the WebDecoy Crawler Sensor extension on your Netlify team.
- Add
WEBDECOY_SITE_KEY,WEBDECOY_SCANNER_IDandWEBDECOY_SENSOR_KEY(from the site’s Setup page, Netlify step) as site environment variables with the Functions scope. - Trigger a deploy.
Details: Netlify extension.
composer require webdecoy/sensor<?php// Early in your front controller (for example public/index.php), after Composer's autoloader.use WebDecoy\Sensor\{Sensor, Config, Request};
$sensor = new Sensor(Config::fromEnvironment()); // reads WEBDECOY_API_KEY$request = Request::fromGlobals();
// Report after the response is on its way. observe() never throws.register_shutdown_function(static fn () => $sensor->observe($request));Behind a CDN or load balancer, set WEBDECOY_TRUSTED_PROXIES to your proxies’ CIDRs (comma separated), or every visitor looks like your proxy. Requires PHP 8.1 or later with ext-curl and ext-json. It is a sensor: it reports and never blocks. Framework middleware and auto_prepend_file setups are in the package README. For WordPress use the plugin instead.
Plain script tag
Section titled “Plain script tag”For any site where you can edit the HTML. Copy the generated line from Detection Scripts in the dashboard and paste it before </head> in your shared layout:
<script async src="https://cdn.webdecoy.com/bot-detection/v1/bot-detection.min.js" data-aid="your-property-uuid" data-sid="your-scanner-uuid"></script>Do not assemble the IDs by hand: data-aid is the site’s property ID and data-sid is the detection script ID. A script tag cannot see clients that never run JavaScript, such as GPTBot or curl. Details: Browser detection script.
Verify the install
Section titled “Verify the install”For server installs (Node packages, PHP, Netlify, the Cloudflare edge sensor), send one request with the reserved test User-Agent:
curl -A "WebDecoy-Test/1.0" http://localhost:3000/Send it to a path your middleware actually runs on. With the Next.js snippet above, the matcher covers only /api/* and /checkout/*, so use a route such as http://localhost:3000/api/health instead of /. The test request reports only when an apiKey is passed.
A detection labeled Test appears on the Detections page within a few seconds. Test detections are excluded from stats and billing. For the script tag, load a page that carries it and watch Sensors. For every method, see Verify your install.
What not to do
Section titled “What not to do”- Do not install packages that are not on this page. WebDecoy has no Go, Python or NestJS bot-detection SDK; the Node packages are
@webdecoy/node,@webdecoy/express,@webdecoy/fastify,@webdecoy/nextjs,@webdecoy/honoand@webdecoy/client. (The separate AI Protection SDKs are a different product.) - Do not commit
WEBDECOY_API_KEYorWEBDECOY_SENSOR_KEY. - Do not turn on
mode: 'enforce'as part of the install.