Vercel BotID vs Arcjet
Arcjet is an alternative to Vercel BotID for protecting your applications from bots. Both products offer bot detection and mitigation features, but there are some key differences to consider when choosing between them.
Key differences: Vercel BotID vs Arcjet
Section titled “Key differences: Vercel BotID vs Arcjet”- Security platform: Arcjet is a comprehensive security platform that offers a wide range of protections including bot detection, rate limiting, email validation, sensitive info detection, shield WAF (web application firewall), filter rules for expression-based traffic control, and AI Runtime Protection (bot detection and prompt injection for AI endpoints, per-user token budget enforcement, and PII detection in AI flows). Vercel BotID is primarily focused on bot detection and mitigation. Vercel’s broader platform services include WAF and rate limiting, but they are separate from BotID and must be configured independently.
- Integration: Arcjet is designed to integrate directly into your codebase, allowing you to customize protections for different parts of your application. Vercel BotID is primarily designed as a wrapper around your Next.js application in the instrumentation client or within specific event handlers for other frameworks. Protected paths must be configured separately from the code for BotID whereas Arcjet configuration happens in code. Vercel’s BotID doesn’t work with traditional HTML forms whereas Arcjet can protect any type of request handler.
- Platform independence: Arcjet is platform-agnostic and can be used with any hosting provider or framework for JavaScript, TypeScript, and Python. Vercel BotID only works for JS/TS applications hosted on Vercel.
- Developer experience: Arcjet is called like any other library from your codebase and provides a response with detailed analysis of each request. Rules are just code so can be varied dynamically based on request context e.g. changing rate limits based on user subscription level or allowing / denying certain bots based on the type of traffic you expect. Results can be inspected to understand the decision and customize the response. Vercel BotID provides few configuration options and returns only minimal information about the request.
- Advanced client signals and filter rules: Arcjet provides advanced bot signals, a browser-based detection layer that runs a WebAssembly module in the client to collect environment signals identifying headless browsers and sophisticated scrapers — without CAPTCHAs or user challenges. Vercel BotID provides its own client-side script for bot verification, but unlike Arcjet does not expose filter rules for composing cookie, header, IP, or geo conditions in code alongside your other bot and rate limiting rules. Vercel’s BotID deep check feature provides similuar functionality to Arcjet’s advanced client signals, but is very expensive.
Comparison
Section titled “Comparison”| Area | Arcjet | Vercel BotID |
|---|---|---|
| Features | App-level security SDK: bot management, rate limiting, WAF, email verification, PII detection/redaction, filter rules, and AI Runtime Protection (prompt injection, token budgets, PII in AI flows). | Bot detection/verification. WAF & rate limiting are separate Vercel features. No AI runtime protection. |
| Hosting | Platform-agnostic. Use on any provider/framework. | Only works on Vercel. |
| Local development | Same behavior as production. | Returns isBot: false locally; supports developmentOptions to bypass/override. |
| Integration model | Call from code in any handler. | Client script + server checkBotId(); you must list protected paths |
| HTML forms | Works with native forms and any HTTP request. | Native HTML form POST is not supported. You must refactor your forms. |
| Configuration | Rules-as-code; configure bots to allow by name and category. Returns detailed context you can log/inspect. Filter rules let you compose cookie, header, IP reputation, and geo conditions alongside bot and rate limiting rules using an expression DSL. | Minimal config, no ability to choose which bots to allow or deny, server API essentially returns isBot (boolean) with minimal detail. No filter rule language. |
| Advanced bot signals | Browser-based WebAssembly signal collection detects headless browsers and sophisticated scrapers without CAPTCHAs. | Client-side script provides bot verification signals; no equivalent filter rule language to compose with other rules in code. |
| AI protection | AI Runtime Protection: bot + prompt injection detection for AI endpoints, per-user token budget enforcement, PII detection in AI flows — all in the same SDK. | No AI runtime protection features. |
| Pricing (bot feature) | See the pricing page for details. | Basic analysis free within compute/request limits per plan. $1 per 1,000 Deep Analysis requests. |
When to choose which
Section titled “When to choose which”- Choose Arcjet if you want security independence regardless of where you deploy, need native form support, want rules-as-code with inspectable decisions, have applications built in multiple languages (JavaScript, TypeScript, and/or Python), want to be able to test locally with the same behavior as production, need advanced client signals for headless browser detection without CAPTCHAs, want filter rules to compose cookie/IP/geo conditions with bot and rate limiting rules in code, or are building AI applications that need prompt injection detection, per-user token budgets, or PII protection — all in one SDK.
- Choose BotID if you’re fully on Vercel, want a quick boolean bot check, don’t need to make any customizations, and are fine configuring rate limits/WAF separately in the Vercel Firewall.
Does BotID work without Vercel?
Section titled “Does BotID work without Vercel?”No. Vercel BotID requires hosting on Vercel to function. Arcjet is platform-agnostic and can be used with any hosting provider or framework, including running locally.
Can I configure which bots to allow or block?
Section titled “Can I configure which bots to allow or block?”With Arcjet, you can customize which bots to allow or block based on your application’s needs. You can allow well-known good bots by name (e.g., Googlebot) and category (e.g. search engines) while blocking malicious ones.
Vercel BotID does not provide configuration options to choose which bots to allow or deny - you only get the details of which bots were detected afterwards.
For example, this Arcjet configuration allows search engine bots but blocks all others:
const aj = arcjet({ key: process.env.ARCJET_KEY!, // Get your site key from https://app.arcjet.com rules: [ // Create a bot detection rule detectBot({ mode: "LIVE", // Blocks requests. Use "DRY_RUN" to log only // Block all bots except the following allow: [ "CATEGORY:SEARCH_ENGINE", // Google, Bing, etc // Uncomment to allow these other common bot categories // See the full list at https://arcjet.com/bot-list //"CATEGORY:MONITOR", // Uptime monitoring services //"CATEGORY:PREVIEW", // Link previews e.g. Slack, Discord ], }), ],});Arcjet can then be called from within any request handler and the results inspected:
export async function GET(req: Request) { const decision = await aj.protect(req);
if (decision.isDenied()) { if (decision.reason.isBot()) { return NextResponse.json( { error: "No bots allowed", reason: decision.reason }, { status: 403 }, ); } else { return NextResponse.json( { error: "Forbidden", reason: decision.reason }, { status: 403 }, ); } }
if (decision.ip.isVpn()) { return NextResponse.json( { error: "VPNs are not allowed" }, { status: 403 }, ); }
if (decision.ip.hasCountry() && decision.ip.country === "US") { // Return a custom response for the United States return NextResponse.json({ message: "Hello from the US!" }); }
return NextResponse.json({ message: "Hello world" });}Compare this to Vercel BotID where you can only inspect minimal details about the results:
import { checkBotId } from "botid/server";import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest) { const botResult = await checkBotId(); const { isBot, verifiedBotName, isVerifiedBot, verifiedBotCategory } = botResult;
if (isBot) { return NextResponse.json({ error: "Access denied" }, { status: 403 }); }
return NextResponse.json({ message: "Hello world" });}