# Rule operators

> Every targeting operator with an example.

A condition tests one user attribute against a value with one operator. These are
the seven operators, with identical behaviour in every SDK. For how conditions
combine into rules, see [Targeting rules](/docs/concepts/targeting).

## The operators

| Operator | Matches when | Example | Matches |
|---|---|---|---|
| `equals` | the attribute equals the value | `plan` equals `enterprise` | `plan = "enterprise"` |
| `not_equals` | the attribute does not equal the value | `plan` not_equals `free` | any plan except `free` |
| `contains` | the attribute contains the value as a substring | `email` contains `@acme` | `bob@acme.com` |
| `ends_with` | the attribute ends with the value | `email` ends_with `@acme.com` | `bob@acme.com` |
| `in_list` | the attribute equals one of the listed values | `country` in_list `US, CA, GB` | `country = "CA"` |
| `gt` | the attribute is numerically greater than the value | `age` gt `18` | `age = 21` |
| `lt` | the attribute is numerically less than the value | `cart_total` lt `100` | `cart_total = 42` |

## How values are compared

Targeting is forgiving about types because user attributes arrive as strings,
numbers, or booleans depending on your code. The rules:

- **String operators** (`equals`, `not_equals`, `contains`, `ends_with`,
  `in_list`) compare **as strings**. The attribute and the value are both coerced
  to text first, so a numeric `plan_tier` of `2` matches a value of `"2"`.
  Booleans coerce to lowercase `"true"` / `"false"`.
- **Numeric operators** (`gt`, `lt`) parse **both sides as numbers**. If either
  side isn't a number, the condition simply doesn't match (it never errors). A
  leading-number string like `"30kg"` parses as `30`.

## A missing attribute never matches

If the user context doesn't contain the attribute a condition names, that
condition is **false** — full stop. For example, a condition on `plan` against a
user object with no `plan` key does not match (it isn't treated as empty or
default). Pass every attribute you intend to target on.

## Cross-language parity

Operator behaviour and the string/number coercion above are part of the
SDK-parity contract and pinned by shared test vectors — Python and JavaScript
resolve every condition identically.

## Next

- [Evaluation order](/docs/reference/evaluation-order) — how matched conditions
  resolve to a value.
- [Targeting rules](/docs/concepts/targeting) — AND/OR composition.
