---
title: Values · Cloudflare Ruleset Engine docs
description: Learn about values in Cloudflare's Rules language, including
  string, boolean, array, and map types, and how to use them in rule
  expressions.
lastUpdated: 2025-08-22T14:24:45.000Z
chatbotDeprioritize: false
source_url:
  html: https://developers.cloudflare.com/ruleset-engine/rules-language/values/
  md: https://developers.cloudflare.com/ruleset-engine/rules-language/values/index.md
---

When an HTTP request reaches the Cloudflare global network, Cloudflare creates a table of field–value pairs against which to match expressions. This table exists for as long as the current request is being processed.

The values that populate the lookup tables of the Rules language are drawn from a variety of sources:

* **Primitive properties** are obtained directly from the request (`http.request.uri.path`, for example).
* **Derived values** are the product of a transformation, composition, or basic operation. For example, the transformation `lower(http.request.uri.path)` converts the value of `http.request.uri.path` to lowercase.
* **Computed values** are the product of a lookup, computation, or other intelligence. For example, Cloudflare uses a machine learning process to dynamically calculate attack scores, represented by `cf.waf.score*` fields.

Besides these values, expressions may also contain literal values. These are static, known values that you incorporate into expressions to compare them with values from request/response fields with or without any transformations.

When working with values in rule expressions, keep in mind the information in the following sections.

## String values and regular expressions

Strings are sequences of bytes enclosed by specific delimiters.

Cloudflare rules support two formats for specifying literal strings: [quoted literal strings](#quoted-string-syntax) and [raw strings](#raw-string-syntax). These formats have different delimiters and escaping mechanisms.

While you can use either of the two string formats to specify regular expressions in an expression, Cloudflare recommends that you use the [raw string syntax](#raw-string-syntax), since the quoted string syntax has complex escaping rules and can lead to unexpected behaviors if not thoroughly tested.

Regular expression matching is performed using the Rust regular expression engine.

### Quoted string syntax

When using the quoted string syntax, a string literal is delimited by `"` (double quote) characters. This format requires that you escape special characters `"` and `\` using `\"` and `\\`, respectively.

The quoted string syntax has the following additional escaping requirements:

* When used to specify a regular expression on the right-hand side of the [regex operator](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/#comparison-operators) (`matches` or `~`), the string is parsed using regex escaping rules.
* When used on the right hand-side of expressions with other operators, or in [function parameters](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/), the string is parsed using basic escaping rules.

```txt
# Test if URI path contains 'a"b'
http.request.uri.path matches "a\"b"


# Test if URI path contains 'a"#b'
http.request.uri.path matches "a\"#b"


# Replace 'a' with '\' (backslash)
regex_replace(http.host, "a", "\\")
```

Warning

In some situations you will need to double-escape a string — for example, when using the [`regex_replace()`](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#regex_replace) function with a regular expression matching a backslash (`\`).

In this case, you must do the basic escaping required by strings as function parameters (using `\\` for each `\` character) and also the regex escaping (using `\\` for each `\` character), since the backslash has a special meaning in regular expressions.

Therefore, to replace a backslash (`\`) with the `a` character using `regex_replace()` you would use the following expression:

```txt
regex_replace(http.host, "\\\\", "a")
```

To avoid this situation, Cloudflare recommends that you use the [raw string syntax](#raw-string-syntax) for specifying regular expressions.

### Raw string syntax

To specify a string (or regular expression) using the raw string syntax you use special delimiters:

* The initial delimiter is composed of an `r` character, optionally followed by one or more `#` characters (up to 255), followed by a `"` (double quote) character.
* The ending delimiter is a `"` (double quote) character followed by the same number of `#` characters as in the initial delimiter (from 0 to 255).

In a raw string there are no special characters, so all characters up to the ending delimiter are interpreted as is (there are no escape sequences).

Unlike the quoted string syntax, the raw string syntax is always the same, regardless of the context where it is being used (for example, as a regular expression with a [regex operator](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/#comparison-operators) or as a parameter of a [function call](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/)).

```txt
# Test if URI path contains 'a"b'
http.request.uri.path matches r#"a"b"#


# Test if URI path contains 'a"#b'
http.request.uri.path matches r##"a"#b"##


# Replace '\' (backslash) with 'a'
# You must still escape the '\' character in the following raw string because it has a special meaning in regular expressions
regex_replace(http.host, r"\\", "a")


# Test if URI path ends with '/api/login.aspx'
# You must still escape the '.' character in the following raw string because it has a special meaning in regular expressions ("any character")
http.request.uri.path matches r"/api/login\.aspx$"
```

### Case sensitivity and regular expressions in values

Since the evaluation of string literal values in expressions is case-sensitive, consider writing more than one simple expression to capture variants.

Cloudflare Business and Enterprise customer plans have access to the `matches` [comparison operator](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/#comparison-operators) which supports regular expressions, so that you can capture multiple variants of a value with a single expression.

### Regular expression limits

Cloudflare has a few limits in place regarding regular expressions. One of those limits is that each rule supports a maximum of 64 regular expressions (regexes), regardless of your domain's plan.

You can use the following strategies to reduce the number of regular expressions in a rule:

* Use the [`contains`](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/#comparison-operators) operator.
* Use the [`wildcard`](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/#wildcard-matching) / [`strict wildcard`](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/#wildcard-matching) operators.
* Use the [`starts_with()`](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#starts_with) and [`ends_with()`](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/#ends_with) functions.

## Boolean values

Simple expressions using boolean fields do not require operator notations or values. You only need to insert the field on its own, as shown in the `ssl` example below.

```sql
ssl
```

This simple expression matches requests where the value of the `ssl` field is `true`.

To match requests where `ssl` is `false`, use the boolean `not` operator :

```sql
not ssl
```

## Arrays

The Cloudflare Rules language includes [fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/) of `Array` type and [functions](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/) with `Array` arguments and return values.

You can access individual array elements using an index (a non-negative value) between square brackets (`[]`). Array indexes start at `0` (zero).

Use the special notation `[*]` when specifying an expression that will be evaluated for each array element (like the [`map` high-order function](https://wikipedia.org/wiki/Map_\(higher-order_function\))). This special index notation will unpack the array, call the enclosing function for all its elements individually, and return a new array containing all the individual return values.

### Examples

Consider the `http.request.headers.names` field with type `Array<String>` in the following examples:

* Obtain the first element in the array:\
  `http.request.headers.names[0]`

* Check if the first array element is equal to `Content-Type` (case sensitive):\
  `http.request.headers.names[0] == "Content-Type"`

* Check if any array element is equal to `Content-Type` (case sensitive):\
  `any(http.request.headers.names[*] == "Content-Type")`

* Check if any array element is equal to `Content-Type`, ignoring the case:\
  `any(lower(http.request.headers.names[*])[*] == "content-type")`

In the last example, the `lower()` function includes the `[*]` notation so that the function is evaluated for each array element. This function, used along `[*]`, returns a new array where each element of the input array is converted to lowercase. Then, the string comparison uses `[*]` to transform the array resulting from applying `lower()` to each header name into an array of boolean values. Finally, `any()` evaluates to true if at least one of these array elements is true.

### Notes

It is not possible to define your own arrays. You can only use arrays returned by fields, either directly or modified by functions.

Accessing an out-of-bounds array index produces a "missing value". A missing value has the following behavior:

* Any comparison `<expr> <op> <literal>` where `<expr>` evaluates to a missing value will evaluate to false.
* Function calls like `function(<expr>)`, where `<expr>` evaluates to a missing value, will return a missing value in most cases, but the exact behavior can vary per function.

You can only use `[*]` multiple times in the same expression if applied to the same array. Also, you can only use `[*]` in the first argument of a function call.

The Rules language [operators](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/) do not directly support arrays or the `[*]` operator — however, they support indexed array elements like `array_value[0]`. For example, you cannot use `[*]` with the `==` operator outside the context of an enclosing function call:

* `http.request.headers.names[*] == "Content-Type"` — **Invalid** expression
* `any(http.request.headers.names[*] == "Content-Type")` — **Valid** expression

## Maps

A map, also called associative array, is a data structure that stores a collection of key-value pairs, where the key must be a `String` and the value can be of any type (for example, a `String` or an array of values). All values in a map must have the same type.

The Cloudflare Rules language includes several [fields](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/) of `Map` data type. The type notation for map fields, for example `Map<Array<String>>`, indicates the data type of the values associated with keys (an `Array` of `String` elements). This means that when you access the value of key `"foo"` you will get either an array of `String` elements or a [missing value](#notes-1).

To access a value in a map, enter the key between square brackets (`[]`):

```txt
<MAP_FIELD>[<KEY>]
```

For maps where the values have an `Array` type, you cannot directly use [operators](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/) with the obtained (array) value, since these operators do not support arrays directly. To use an operator on an item of the array, use the special notation `[*]` when specifying an expression. This special index notation will unpack the array, call the enclosing function for all its elements individually, and return a new array containing all the individual return values.

### Examples

The following example is based on the [`http.request.headers`](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.headers/) field with a data type of `Map<Array<String>>`, where array elements are of `String` data type.

If an incoming HTTP request included a single `Accept: application/json` HTTP header, the following expressions would evaluate to the indicated values:

```txt
http.request.headers["accept"]     # ==> ["application/json"]
http.request.headers["accept"][0]  # ==> "application/json"


any(http.request.headers["accept"][*] == "application/json") # ==> true
any(http.request.headers["accept"][*] == "text/plain")       # ==> false
```

The following example is based on the [`http.request.uri.args`](https://developers.cloudflare.com/ruleset-engine/rules-language/fields/reference/http.request.uri.args/) field with a data type of `Map<Array<String>>`, where array elements are of `String` data type.

If an HTTP request included three `filter` URI arguments `waf`, `botm`, and `cdn`, the following expressions would evaluate to the indicated values:

```txt
# Example request URL:
# https://example.com/?filter=waf&filter=botm&filter=cdn


http.request.uri.args["filter"]          # ==> ["waf", "botm", "cdn"]


len(http.request.uri.args["filter"][1])  # ==> 4


# Check if the length of all 'filter' values is always 3 or 4
all(len(http.request.uri.args["filter"][*])[*] in {3 4})      # ==> true


# Check if the length of 'filter' values (if any) is never 3 or 4
all(not len(http.request.uri.args["filter"][*])[*] in {3 4})  # ==> false


# Check if the http.request.uri.args map contains a "filter" key
len(http.request.uri.args["filter"]) >= 0     # ==> true


# Check if the http.request.uri.args map does not contain an "order" key
not len(http.request.uri.args["order"]) >= 0  # ==> true
```

For more information on `any()`, `all()`, `len()`, and other available functions, refer to [Functions](https://developers.cloudflare.com/ruleset-engine/rules-language/functions/).

### Notes

It is not possible to define your own maps. You can only use maps returned by fields.

Accessing a non-existing key in a map produces a "missing value". A missing value has the following behavior:

* Any comparison `<expr> <op> <literal>` where `<expr>` evaluates to a missing value will evaluate to false.
* Function calls like `function(<expr>)`, where `<expr>` evaluates to a missing value, will return a missing value in most cases, but the exact behavior can vary per function.

## Lists

Lists allow you to create a group of items and refer to them collectively, by name, in your expressions. Each list type supports items of a specific data type. All items in a list must have the same data type. For details on the available list types, refer to [Lists](https://developers.cloudflare.com/waf/tools/lists/#supported-lists).

To refer to a list in a rule expression, use `$<list_name>` and specify the `in` [operator](https://developers.cloudflare.com/ruleset-engine/rules-language/operators/). Only one value in the list has to match the left-hand side of the expression (before the `in` operator) for the simple expression to evaluate to `true`. If there is no match, the expression will evaluate to `false`.

The following example expression filters requests from IP addresses that are in an [IP list](https://developers.cloudflare.com/waf/tools/lists/custom-lists/#ip-lists) named `office_network`:

```sql
(ip.src in $office_network)
```

List names can only include lowercase letters, numbers, and the underscore (`_`) character. For guidance on creating and managing lists, refer to [Lists](https://developers.cloudflare.com/waf/tools/lists/).

### Inline lists

Inline lists allow you to directly include a list of values in a simple expression that uses the `in` operator.

Elements in an inline list can be strings, integers, or IP addresses/ranges. All elements of an inline list must have the same data type and they must be literal values. To specify inline list elements, enter them individually, separating elements with a space. Inline lists can contain duplicate values.

Additionally, for some data types you can use ranges as elements:

* For integer values, enter ranges in the form `<start_value>..<end_value>`. An inline list can contain both integer ranges and integer values.

* For IP addresses, you can enter:

  * Explicit IP ranges in the form `<start_address>..<end_address>` (for example, `198.51.100.3..198.51.100.7`).
  * CIDR ranges (for example, `192.0.2.0/24` or `2001:0db8::/32`).

  An inline list can contain explicit IP ranges, CIDR ranges, and individual IP addresses.

```sql
http.host in {"example.com" "example.net"}


ip.src in {198.51.100.1 198.51.100.3..198.51.100.7 192.0.2.0/24 2001:0db8::/32}


tcp.dstport in {8000..8009 8080..8089}
```
