Security
Updated
2 min read

Introducing Arcjet filters to quickly implement access rules

Arcjet filters let you block requests using expressions over HTTP headers, IP addresses, and other request fields.

Introducing Arcjet filters to quickly implement access rules

Arcjet allows developers to quickly implement sophisticated protections against bots, scrapers, and spammers with our security SDK. In just a few lines of code you can protect signup forms, login routes, and other sensitive areas of your application with easy local-testing of security rules that work the same way in production.

However, sometimes it's necessary to implement more basic protections by blocking requests based on simple characteristics. What if you want to only allow user logins from a specific company VPN network? Or block specific high-risk countries? Or validate that requests have specific headers?

As part of the latest beta-12 release of our JS SDK, Arcjet Filters let you block requests using Wireshark-like display filter expressions over HTTP headers, IP addresses, and other request fields. This allows you to quickly enforce rules like allow/deny by country, network, or user-agent.

Expressions for allowing or denying requests

The expression language is based on Wireshark-like display filter expressions. Like other programming languages, there are fields (ip.src.vpn), functions (lower()), operators (ormatches), and values ("curl").

For example, to deny VPN or Tor traffic and any user agent header (converted to lower case) that matches curl or is not present, we can use this expression:

ip.src.vpn or
ip.src.tor or
lower(http.request.headers["user-agent"]) matches "curl" or
len(http.request.headers["user-agent"]) eq 0

Implementing this in middleware will block requests before your route handlers execute, for example in Next.js:

import arcjet, { createMiddleware, filter } from "@arcjet/next";

// Get your Arcjet key at <https://app.arcjet.com>.
// Set it as an environment variable instead of hard coding it.
const arcjetKey = process.env.ARCJET_KEY;

if (!arcjetKey) {
  throw new Error("Cannot find `ARCJET_KEY` environment variable");
}

const aj = arcjet({
  characteristics: ['http.request.headers["user-agent"]', "ip.src"],
  key: arcjetKey,
  rules: [
    filter({
      // This will deny any traffic using a VPN, Tor, that matches the curl
      // user agent, or that has no user agent
      deny: [
        'ip.src.vpn or ip.src.tor or lower(http.request.headers["user-agent"]) matches "curl" or len(http.request.headers["user-agent"]) eq 0',
      ],
      // Block requests with `LIVE`, use `DRY_RUN` to log only.
      mode: "LIVE",
    }),
  ],
});

export default createMiddleware(aj);

export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};

Or as a full Next.js function handler where you have more flexibility to adjust the user flow with custom logic:

import arcjet, { filter } from "@arcjet/next";
import { NextResponse } from "next/server";

const aj = arcjet({
  key: process.env.ARCJET_KEY!,
  rules: [
    filter({
      deny: [
        // Requests matching this expression will be denied. All other
        // requests will be allowed.
        'ip.src.vpn or ip.src.tor or lower(http.request.headers["user-agent"]) matches "curl" or len(http.request.headers["user-agent"]) eq 0',
      ],
      mode: "LIVE",
    }),
  ],
});

export async function GET(req: Request) {
  const decision = await aj.protect(req);

  if (decision.isDenied()) {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  return NextResponse.json({
    message: "Hello world",
  });
}

Arcjet provides detailed IP address metadata within the decision response, but the filters expression language makes it easy to manipulate the underlying data and return immediate allow or deny decisions without having to write the logic in your own code.

Try it now

This is available to all Arcjet users across all supported runtimes (Node, Bun, Deno) and frameworks (Express, Remix, Astro, SvelteKit, NestJS, Fastify, Next.js, React Router) now by upgrading to the latest SDK release.

Check out the quick start guide and filters reference documentation.

Related articles

Subscribe by email

Get the full posts by email every week.