Arcjet Deno SDK reference
This guide shows how to use the package
@arcjet/deno.
Its source code is on GitHub.
The code is open source and licensed under Apache 2.0.
What is Arcjet?
Arcjet helps developers protect their apps in just a few lines of code. Bot detection. Rate limiting. Email validation. Attack protection. Data redaction. A developer-first approach to security.Quick start
Section titled “Quick start”See the Deno quick start.
Requirements
Section titled “Requirements”- Deno 2 or later
- ESM
Install
Section titled “Install”deno add npm:@arcjet/denoConfigure
Section titled “Configure”Build Arcjet clients as few times as possible. That means outside request handlers. If you need different strategies, such as one for logged-in users and one for guests, create two clients and choose which one to use inside the handler.
Options
Section titled “Options”The main way to configure Arcjet is to pass options to the arcjet function.
The fields are:
characteristics(Array<string>, default:["src.ip"]) — characteristics to track a user by; can also be passed to rulesclient(Client, optional) — client used to make requests to the Cloud APIkey(string, required) — API key to identify the site in Arcjet (typically throughprocess.env.ARCJET_KEY)log(ArcjetLogger, optional) — log interface to emit useful inforules(Array<ArcjetRule>, required) — rules to use (order insensitive)
Get your site key from the Arcjet dashboard.
Set it as an environment variable called ARCJET_KEY in your .env file:
ARCJET_KEY=your_site_key_hereEnvironment variables
Section titled “Environment variables”Next to the convention of using ARCJET_KEY for the Arcjet Cloud API key,
there are several environment variables that affect how Arcjet works.
ARCJET_BASE_URL— an allowed URL to the Cloud API (defaults tohttps://decide.arcjet.com)ARCJET_ENV,MODE,NODE_ENV— whether development mode is onARCJET_LOG_LEVEL— log level to useFLY_APP_NAME,VERCEL,RENDER— hosting platform
Protect
Section titled “Protect”Use the protect function to protect a request from Deno.
Some rules, such as validateEmail, may need extra properties.
The protect function returns a promise that resolves to a decision.
import "jsr:@std/dotenv/load";import arcjetDeno, { tokenBucket } from "npm:@arcjet/deno";
const arcjetKey = Deno.env.get("ARCJET_KEY");
if (!arcjetKey) { throw new Error("Cannot find `ARCJET_KEY` environment variable");}
const arcjet = arcjetDeno({ key: arcjetKey, rules: [ tokenBucket({ capacity: 10, characteristics: ["userId"], interval: 10, mode: "LIVE", refillRate: 5, }), ],});
Deno.serve( { port: 3000 }, arcjet.handler(async function (request) { // Replace `userId` with your authenticated user ID. const userId = "user123"; const decision = await arcjet.protect(request, { requested: 5, userId, });
if (decision.isDenied()) { return new Response("Forbidden", { status: 403 }); }
return new Response("Hello world"); }),);Decision
Section titled “Decision”The ArcjetDecision that protect resolves to has the following fields:
conclusion("ALLOW","DENY", or"ERROR") — what to do with the requestid(string) — ID for the request; local decisions start withlreq_and remote ones withreq_ip(ArcjetIpDetails) — analysis of the client IP addressreason(ArcjetReason) — more info about the conclusionresults(Array<ArcjetRuleResult>) — results of each rulettl(number) — time-to-live for the decision in seconds;"DENY"decisions are cached by@arcjet/denofor this duration
This top-level decision takes the results from each "LIVE" rule into account.
If one of them is "DENY" then the overall conclusion will be "DENY".
Otherwise, if one of them is "ERROR", then "ERROR".
Otherwise, it will be "ALLOW".
The reason and ttl fields reflect this conclusion.
To illustrate,
when a bot rule returns an error and a validate email rule returns a deny,
the overall conclusion is "DENY",
while the "ERROR" is available in the results.
The results of "DRY_RUN" rules do not affect this overall decision,
but are included in results.
The ip field is available when the Cloud API was called and contains
IP geolocation and reputation info.
You can use this field to customize responses or you can use
filter rules to make decisions based on it.
See the
IP geolocation and
IP reputation
blueprints for more info.
Errors
Section titled “Errors”Arcjet fails open so that a service issue, misconfiguration, or
network timeout does not block requests.
Such errors should in many cases be logged but otherwise treated as "ALLOW"
decisions.
The reason.message field has more info on what occured.
import "jsr:@std/dotenv/load";import arcjetDeno, { filter } from "npm:@arcjet/deno";
const arcjetKey = Deno.env.get("ARCJET_KEY");
if (!arcjetKey) { throw new Error("Cannot find `ARCJET_KEY` environment variable");}
const arcjet = arcjetDeno({ key: arcjetKey, rules: [ // This broken expression will result in an error decision: filter({ deny: ['ip.src.country is "'] }), ],});
Deno.serve( { port: 3000 }, arcjet.handler(async function (request) { const decision = await arcjet.protect(request);
if (decision.isErrored()) { console.warn("Arcjet error", decision.reason.message); }
if (decision.isDenied()) { return new Response("Forbidden", { status: 403 }); }
return new Response("Hello world"); }),);Custom logs
Section titled “Custom logs”You can use a custom log interface matching pino
to change the default behavior.
Using pino-pretty as an example:
deno add npm:pino npm:pino-prettyThen, create a custom logger that will log to JSON in production and pretty print in development:
import "jsr:@std/dotenv/load";import arcjetDeno from "npm:@arcjet/deno";import pinoPretty from "npm:pino-pretty";import pino from "npm:pino";
const arcjetKey = Deno.env.get("ARCJET_KEY");
if (!arcjetKey) { throw new Error("Cannot find `ARCJET_KEY` environment variable");}
const arcjet = arcjetDeno({ key: arcjetKey, log: pino( { // Warn in development, debug otherwise. level: Deno.env.get("ARCJET_LOG_LEVEL") || (Deno.env.get("ARCJET_ENV") === "development" ? "debug" : "warn"), }, // Pretty print in development, JSON otherwise. Deno.env.get("ARCJET_ENV") === "development" ? pinoPretty({ colorize: true }) : undefined, ), rules: [ // … ],});Custom client
Section titled “Custom client”You can pass a client to change the behavior when connecting to the Cloud API.
Use createRemoteClient to create a client.
import "jsr:@std/dotenv/load";import arcjetDeno, { createRemoteClient } from "npm:@arcjet/deno";
const arcjetKey = Deno.env.get("ARCJET_KEY");
if (!arcjetKey) { throw new Error("Cannot find `ARCJET_KEY` environment variable");}
const arcjet = arcjetDeno({ key: arcjetKey, client: createRemoteClient({ timeout: 3000 }), rules: [ // … ],});