Skip to content

Filters reference

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.

Arcjet filter rules is available on all pricing plans.

Allow or deny filters are configured using one or more expressions:

  • allow - A list of expressions that will result in an ALLOW decision if the request matches. If none of the expressions match, the request will be denied.
  • deny - A list of expressions that will result in a DENY decision if the request matches. If none of the expressions match, the request will be allowed.
  • These lists are mutually-exclusive, so you can only use one or the other.

They are constructed with the filters(options) function and configured by FilterOptionsAllow or FilterOptionsDeny:

type FilterOptions =
| {
allow: ReadonlyArray<string>;
deny?: never | undefined;
mode?: ArcjetMode | undefined;
}
| {
allow?: never | undefined;
deny: ReadonlyArray<string>;
mode?: ArcjetMode | undefined;
};
type ArcjetMode = "LIVE" | "DRY_RUN";

Example: Allow non-VPN, US-based GET requests

Section titled “Example: Allow non-VPN, US-based GET requests”

In this example, the expression matches non-VPN GET requests from the US. Requests matching the expression are allowed and all others are denied.

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

Example: Matching VPN, Tor, or Curl requests

Section titled “Example: Matching VPN, Tor, or Curl requests”

This example matches VPN or Tor traffic and basic Curl requests.

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

To use it as a filter deny rule so that any requests matching the expression are denied (and all others allowed), you would configure Arcjet like this:

filter({
deny: [
'ip.src.vpn or ip.src.tor or lower(http.request.headers["user-agent"]) matches "curl"',
],
mode: "LIVE",
}),

Example: Matching requests from specific countries

Section titled “Example: Matching requests from specific countries”

This example matches requests from the European Union:

ip.src.country in {"AT" "BE" "BG" "CY" "CZ" "DE" "DK" "EE" "ES" "FI" "FR" "GR" "HR" "HU" "IE" "IT" "LT" "LU" "LV" "MT" "NL" "PL" "PT" "RO" "SE" "SI" "SK"}

To use it as a filter allow rule so that only requests matching the expression are allowed (and all others denied), you would configure Arcjet like this:

filter({
allow: [
'ip.src.country in {"AT" "BE" "BG" "CY" "CZ" "DE" "DK" "EE" "ES" "FI" "FR" "GR" "HR" "HU" "IE" "IT" "LT" "LU" "LV" "MT" "NL" "PL" "PT" "RO" "SE" "SI" "SK"}',
],
mode: "LIVE",
}),
FieldTypeExample value
http.hoststring"example.com"
http.request.cookieMap<string>{NEXT_LOCALE: "en-US", …}
http.request.headersMap<string>{"user-agent": "Mozilla/5.0 (Macintosh; …"}
http.request.methodstring"GET"
http.request.uri.argsMap<string>{q: "search"}
http.request.uri.pathstring"/quick-start"
ip.src.accuracy_radiusstring"2"
ip.src.asnum.countrystring"US"
ip.src.asnum.domainstring"google.com"
ip.src.asnum.namestring"Google, LLC."
ip.src.asnum.typestring"business"
ip.src.asnumstring"15169"
ip.src.citystring"Mountain View"
ip.src.continent.namestring"North America"
ip.src.continentstring"NA"
ip.src.country.namestring"United States"
ip.src.countrystring"US"
ip.src.crawler.namestring""
ip.src.crawlerbooleanfalse
ip.src.hostingbooleanfalse
ip.src.latstring"37.33939"
ip.src.lonstring"-121.89496"
ip.src.mobilebooleanfalse
ip.src.postal_codestring"94043"
ip.src.proxybooleanfalse
ip.src.regionstring"California"
ip.src.relaybooleanfalse
ip.src.servicestring""
ip.src.timezone.namestring"America/Los_Angeles"
ip.src.torbooleanfalse
ip.src.vpnbooleanfalse
ip.srcIp8.8.8.8

All ip.src.* fields reflect information about the client IP address (the request source IP). These fields require data from our IP reputation database so a call to the Arcjet API is required. Other fields are analyzed locally.

Arcjet only ever makes a single call to our Cloud API regardless of the rule configuration. The Arcjet API has been designed for high performance and low latency, and is deployed to multiple regions around the world. The SDK will automatically use the closest region which means the total overhead is typically no more than 20-30ms, often significantly less. See the Architecture reference for details.

OperatorExample expression
and (&&)http.request.method eq "GET" and http.request.uri.path eq "/quick-start"
containshttp.request.uri.path contains "quick-start"
eq (==)http.request.method eq "GET"
ge (>=)len(http.request.uri.args["q"]) ge 1
gt (>)len(http.request.uri.args["q"]) gt 0
inip.src in { 185.199.108.153 185.199.109.153 }
le (<=)len(http.request.uri.args["q"]) le 3
lt (<)len(http.request.uri.args["q"]) lt 4
matches (~)http.request.headers["user-agent"] matches "Chrome"
ne (!=)http.request.method ne "GET"
not (!)not ip.src.vpn
or (||)ip.src.vpn or ip.src.relay
strict wildcardhttp.request.uri.path strict wildcard "/articles/*"
wildcardhttp.request.uri.path wildcard "/articles/*"
xor (^^)ip.src.vpn xor ip.src.relay
FunctionExample
lenlen(http.request.uri.args["q"]) gt 0
lowerlower(ip.src.country) contains "be"
upperupper(http.request.headers["user-agent"]) contains "CHROME"

String values are enclosed in double quotes (").

Double quotes within the string must be escaped with a backslash (\").

http.host eq "example.com"

Boolean values are either true or false. You can negate a boolean value with the not (!) operator.

ip.src.vpn
not ip.src.vpn

IP addresses are a special type which must not be quoted like strings.

ip.src eq 185.199.108.153
ip.src in { 185.199.108.153 185.199.109.153 185.199.110.153 185.199.111.153 }
ip.src in { 192.0.2.0/24 }

Maps (or associative arrays) are a collection of keys to values.

They cannot be written literally in the expression language, but they exist for the fields http.request.cookie, http.request.headers, and http.request.uri.args.

http.request.headers["user-agent"] matches "Chrome"

Arcjet provides a single protect function that is used to execute your protection rules.

This function returns a Promise that resolves to an ArcjetDecision object. This contains the following properties:

  • id (string) - The unique ID for the request. This can be used to look up the request in the Arcjet dashboard. It is prefixed with req_ for decisions involving the Arcjet cloud API. For decisions taken locally, the prefix is lreq_.
  • conclusion (ArcjetConclusion) - The final conclusion based on evaluating each of the configured rules. If you wish to accept Arcjet’s recommended action based on the configured rules then you can use this property.
  • reason (ArcjetReason) - An object containing more detailed information about the conclusion.
  • results (ArcjetRuleResult[]) - An array of ArcjetRuleResult objects containing the results of each rule that was executed.
  • ip (ArcjetIpDetails) - An object containing Arcjet’s analysis of the client IP address. See the SDK reference for more information.

You check if a deny conclusion has been returned by a filter rule by using decision.isDenied() and decision.reason.isFilterRule() respectively.

You can iterate through the results and check whether a filter rule was applied:

for (const result of decision.results) {
console.log("Rule Result", result);
}

Arcjet is designed to fail open so that a service issue or misconfiguration does not block all requests. The SDK will also time out and fail open after 500ms when NODE_ENV is production and 1000ms otherwise. However, in most cases, the response time will be less than 20-30ms.

If there is an error condition when processing the rule, Arcjet will return an ERROR result for that rule and you can check the message property on the rule’s error result for more information.

If all other rules that were run returned an ALLOW result, then the final Arcjet conclusion will be ERROR.

Arcjet runs the same in any environment, including locally and in CI. You can use the mode set to DRY_RUN to log the results of rule execution without blocking any requests.

We have an example test framework you can use to automatically test your rules. Arcjet can also be triggered based using a sample of your traffic.

See the Testing section of the docs for details.

  • A maximum of 10 expressions can be specified.
  • Each expression can be a maximum of 1024 bytes.