---
name: arcjet-seguridad-aplicaciones-web
description: Guia experta para integrar Arcjet en Next.js y Node.js: rate limiting, deteccion de bots, validacion de email y proteccion contra ataques mediante SDK code-first sin gestionar infraestructura.
license: Apache-2.0
metadata:
  id: 81e788d5
  slug: arcjet-seguridad-aplicaciones-web
  titulo: "Arcjet — Capa de Seguridad para Aplicaciones Web"
  servicio: Web
  categoria_recurso: Web-Desarrollo
  tipo: referencia
  nivel: intermedio
  idioma: es
  idioma_original: en
  acceso: gratis
  precio_eur: 0
  plataformas: [Next.js, Node.js, TypeScript, Express]
  dependencias: [@arcjet/next, @arcjet/node, ARCJET_KEY]
  licencia: { spdx: Apache-2.0, redistribuible: true, uso_comercial: true }
  fuente:
    repo: TerminalSkills/skills
    url: https://github.com/TerminalSkills/skills/tree/main/skills/arcjet
    commit: 77fa015
    autor: TerminalSkills
    nombre_original: arcjet
    duplicados_en: []
  seguridad: { veredicto: seguro, riesgo: bajo, escaneado: "2026-06-14", motor: "grep-estatico+auditor-llm" }
  ficha:
    que_hace: "Proporciona patrones de codigo listos para añadir rate limiting, deteccion de bots, validacion de email y escudo de ataques a aplicaciones JavaScript/TypeScript."
    como_lo_hace: "Mediante el SDK de Arcjet configurado como middleware en Next.js o Express, combinando reglas de seguridad encadenadas (shield, detectBot, tokenBucket) evaluadas en cada peticion."
  content_hash: "81e788d50d7ca54ca365e7f60d491e60bd553652a0c89c0a1df2cb5937d6ac7f"
  version: 1.0.0
---

# Arcjet — Application Security Layer


## Overview


Arcjet, the developer-first security platform that provides rate limiting, bot protection, email validation, and attack detection as a code-first SDK. Helps developers add security layers to Next.js, Node.js, and other JavaScript/TypeScript applications without managing infrastructure.


## Instructions

### Rate Limiting

Protect endpoints from abuse with flexible rate limiting:

```typescript
// src/lib/arcjet.ts — Configure Arcjet security rules
import arcjet, { tokenBucket, slidingWindow, fixedWindow } from "@arcjet/next";

// Token bucket — allows bursts, then limits sustained rate
// Good for APIs where occasional spikes are normal
export const aj = arcjet({
  key: process.env.ARCJET_KEY!,
  characteristics: ["ip.src"],      // Rate limit per IP address
  rules: [
    tokenBucket({
      mode: "LIVE",                  // "LIVE" enforces; "DRY_RUN" logs only
      refillRate: 10,                // Add 10 tokens per interval
      interval: 60,                  // Every 60 seconds
      capacity: 20,                  // Max burst of 20 requests
    }),
  ],
});

// Sliding window — smooth rate limiting without burst allowance
// Good for login endpoints where you want strict limits
export const loginLimiter = arcjet({
  key: process.env.ARCJET_KEY!,
  characteristics: ["ip.src"],
  rules: [
    slidingWindow({
      mode: "LIVE",
      max: 5,                        // 5 attempts
      interval: "15m",               // Per 15-minute window
    }),
  ],
});

// Fixed window with multiple tiers
export const apiLimiter = arcjet({
  key: process.env.ARCJET_KEY!,
  characteristics: ["http.request.headers[\"x-api-key\"]"],  // Per API key
  rules: [
    fixedWindow({
      mode: "LIVE",
      max: 100,                      // 100 requests
      interval: "1h",                // Per hour
    }),
    fixedWindow({
      mode: "LIVE",
      max: 1000,                     // 1000 requests
      interval: "1d",                // Per day
    }),
  ],
});
```

### Bot Protection

Detect and block automated traffic:

```typescript
// app/api/signup/route.ts — Protect signup from bots
import arcjet, { detectBot, shield } from "@arcjet/next";
import { NextRequest, NextResponse } from "next/server";

const aj = arcjet({
  key: process.env.ARCJET_KEY!,
  rules: [
    // Shield — detects common attack patterns (SQLi, XSS, path traversal)
    shield({ mode: "LIVE" }),

    // Bot detection — blocks automated clients
    detectBot({
      mode: "LIVE",
      allow: [
        "CATEGORY:SEARCH_ENGINE",     // Allow Google, Bing, etc.
        "CATEGORY:MONITOR",           // Allow uptime monitors
      ],
      // Everything else (scrapers, headless browsers, AI crawlers) is blocked
    }),
  ],
});

export async function POST(request: NextRequest) {
  const decision = await aj.protect(request);

  if (decision.isDenied()) {
    if (decision.reason.isBot()) {
      return NextResponse.json(
        { error: "Bot traffic is not allowed" },
        { status: 403 }
      );
    }
    if (decision.reason.isRateLimit()) {
      return NextResponse.json(
        { error: "Too many requests" },
        { status: 429, headers: { "Retry-After": "60" } }
      );
    }
    if (decision.reason.isShield()) {
      return NextResponse.json(
        { error: "Suspicious request blocked" },
        { status: 403 }
      );
    }
  }

  // Request passed all security checks — process normally
  const body = await request.json();
  const user = await createUser(body);
  return NextResponse.json({ user }, { status: 201 });
}
```

### Email Validation

Validate email addresses before accepting them:

```typescript
// app/api/subscribe/route.ts — Validate emails at signup
import arcjet, { validateEmail } from "@arcjet/next";
import { NextRequest, NextResponse } from "next/server";

const aj = arcjet({
  key: process.env.ARCJET_KEY!,
  rules: [
    validateEmail({
      mode: "LIVE",
      block: [
        "DISPOSABLE",                // Block temporary email services
        "INVALID",                    // Block malformed addresses
        "NO_MX_RECORDS",             // Block domains without mail servers
      ],
      // Allow free email providers (Gmail, Yahoo) — block only throwaway
    }),
  ],
});

export async function POST(request: NextRequest) {
  const { email } = await request.json();

  const decision = await aj.protect(request, { email });

  if (decision.isDenied()) {
    const reason = decision.reason;
    if (reason.isEmail()) {
      // Specific error messages based on email issue
      if (reason.emailTypes.includes("DISPOSABLE")) {
        return NextResponse.json(
          { error: "Please use a permanent email address" },
          { status: 422 }
        );
      }
      if (reason.emailTypes.includes("INVALID")) {
        return NextResponse.json(
          { error: "Please check your email address" },
          { status: 422 }
        );
      }
    }
  }

  // Email is valid — proceed with subscription
  await addToMailingList(email);
  return NextResponse.json({ success: true });
}
```

### Next.js Middleware Integration

Apply security rules globally via middleware:

```typescript
// middleware.ts — Global security middleware for Next.js
import arcjet, { detectBot, shield, tokenBucket } from "@arcjet/next";
import { NextRequest, NextResponse } from "next/server";

const aj = arcjet({
  key: process.env.ARCJET_KEY!,
  characteristics: ["ip.src"],
  rules: [
    shield({ mode: "LIVE" }),
    detectBot({
      mode: "LIVE",
      allow: ["CATEGORY:SEARCH_ENGINE", "CATEGORY:MONITOR", "CATEGORY:PREVIEW"],
    }),
    tokenBucket({
      mode: "LIVE",
      refillRate: 60,
      interval: 60,
      capacity: 120,
    }),
  ],
});

export async function middleware(request: NextRequest) {
  const decision = await aj.protect(request);

  // Log all decisions for monitoring
  console.log(`[Arcjet] ${request.url} | ${decision.conclusion} | IP: ${decision.ip.ip}`);

  if (decision.isDenied()) {
    // Return appropriate error based on reason
    if (decision.reason.isRateLimit()) {
      return NextResponse.json({ error: "Rate limited" }, { status: 429 });
    }
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  // Add security headers
  const response = NextResponse.next();
  response.headers.set("X-Arcjet-Decision", decision.conclusion);
  return response;
}

export const config = {
  matcher: [
    "/api/:path*",              // Protect all API routes
    "/((?!_next|favicon).*)",   // Protect pages (exclude static assets)
  ],
};
```

### Node.js / Express Integration

Use Arcjet with Express or any Node.js framework:

```typescript
// src/middleware/security.ts — Arcjet with Express
import arcjet, { tokenBucket, detectBot, shield } from "@arcjet/node";
import { Request, Response, NextFunction } from "express";

const aj = arcjet({
  key: process.env.ARCJET_KEY!,
  characteristics: ["ip.src"],
  rules: [
    shield({ mode: "LIVE" }),
    detectBot({ mode: "LIVE", allow: ["CATEGORY:SEARCH_ENGINE"] }),
    tokenBucket({ mode: "LIVE", refillRate: 30, interval: 60, capacity: 60 }),
  ],
});

export async function arcjetMiddleware(req: Request, res: Response, next: NextFunction) {
  const decision = await aj.protect(req);

  if (decision.isDenied()) {
    const status = decision.reason.isRateLimit() ? 429 : 403;
    return res.status(status).json({
      error: decision.reason.isRateLimit() ? "Rate limited" : "Forbidden",
    });
  }

  next();
}

// Usage in Express app
app.use("/api", arcjetMiddleware);
```

## Installation

```bash
# Next.js
npm install @arcjet/next

# Node.js / Express
npm install @arcjet/node

# Get API key at https://app.arcjet.com
```


## Examples


### Example 1: Setting up Arcjet with a custom configuration

**User request:**

```
I just installed Arcjet. Help me configure it for my TypeScript + React workflow with my preferred keybindings.
```

The agent creates the configuration file with TypeScript-aware settings, configures relevant plugins/extensions for React development, sets up keyboard shortcuts matching the user's preferences, and verifies the setup works correctly.

### Example 2: Extending Arcjet with custom functionality

**User request:**

```
I want to add a custom bot protection to Arcjet. How do I build one?
```

The agent scaffolds the extension/plugin project, implements the core functionality following Arcjet's API patterns, adds configuration options, and provides testing instructions to verify it works end-to-end.


## Guidelines

1. **Start with DRY_RUN** — Use `mode: "DRY_RUN"` first to monitor traffic patterns before enforcing rules
2. **Layer multiple rules** — Combine shield + bot detection + rate limiting; each catches different attack types
3. **Rate limit by the right characteristic** — Use IP for public endpoints, API key for authenticated ones, user ID for per-user limits
4. **Allow legitimate bots** — Search engines, uptime monitors, and link previews are not attacks; whitelist them
5. **Validate emails early** — Check email validity at signup, not after sending a verification email (saves deliverability)
6. **Middleware for global protection** — Apply shield and bot detection in middleware; add specific rate limits per route
7. **Monitor before enforcing** — Review Arcjet dashboard logs to understand traffic patterns and tune thresholds
8. **Graceful degradation** — If Arcjet is unavailable, your app should still work; wrap in try/catch with a permissive fallback
