> ## Documentation Index
> Fetch the complete documentation index at: https://usefoil.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Verdicts & scoring

> Understand Foil verdicts and risk scores, how human, bot, and inconclusive map to score ranges, and how to apply them in your backend policy.

Every Foil session produces a **verdict** (`human`, `bot`, or `inconclusive`) and a **risk score** (integer `0` – `100`). Your backend uses these to decide what to do.

## Verdicts

| Verdict        | Score range | Meaning                                  | Suggested action                 |
| -------------- | ----------- | ---------------------------------------- | -------------------------------- |
| `human`        | 0 – 39      | Real user behavior detected              | Allow                            |
| `inconclusive` | 40 – 69     | Not enough evidence for a confident call | Challenge or gather more context |
| `bot`          | 70 – 100    | Automated or non-human behavior detected | Block or rate-limit              |

## Risk score

The risk score is an integer from `0` (definitely human) to `100` (definitely bot). It's normalized via a sigmoid function, so scores cluster near the extremes — most sessions score below 10 or above 90.

Use the score for granular policy when the verdict alone isn't enough:

```
if risk_score < 10  → fast-path allow (no friction)
if risk_score < 40  → allow (human verdict)
if risk_score < 70  → challenge (inconclusive)
if risk_score >= 70 → block (bot verdict)
```

## Evaluation phases

Foil evaluates sessions in two phases:

| Phase        | When                            | What it uses                                 | Confidence                            |
| ------------ | ------------------------------- | -------------------------------------------- | ------------------------------------- |
| `snapshot`   | Immediately on session creation | Environment probes, fingerprint, anti-tamper | Good for deterministic signals        |
| `behavioral` | After user interaction          | Mouse, keyboard, touch, timing patterns      | Higher confidence for ambiguous cases |

<Note>
  If you call `getSession()` before the user interacts with the page, you'll get a snapshot-phase result. For highest confidence, wait for at least a few seconds of user interaction.
</Note>

## Preliminary vs final

| Status        | Meaning                                           |
| ------------- | ------------------------------------------------- |
| `preliminary` | Early result, may be updated as more data arrives |
| `final`       | Complete evaluation, won't change                 |

Snapshot-phase results are usually `preliminary`. Behavioral-phase results are `final`.

## Automation attribution

When Foil identifies the specific automation tool, the session includes attribution details:

| Category       | Examples                               |
| -------------- | -------------------------------------- |
| `automation`   | Playwright, Puppeteer, Selenium        |
| `ai-agent`     | browser-use, OpenAI Operator           |
| `crawler`      | Googlebot, Bingbot                     |
| `verified-bot` | Legitimate crawlers with Web Bot Auth  |
| `fabricated`   | Anti-detect browsers, spoofed profiles |

Attribution includes the framework name, variant, organization (if known), and a confidence score.

## Using verdicts in your API

The sealed token returns the `Decision` shape directly:

```json theme={"dark"}
{
  "verdict": "bot",
  "risk_score": 94,
  "phase": "behavioral",
  "is_provisional": false
}
```

The session **detail** endpoint (`GET /v1/sessions/:id`) renames these fields into a more descriptive, action-oriented vocabulary. (The **list** endpoint, `GET /v1/sessions`, keeps the sealed-token names — `verdict`, `phase`, `is_provisional` — in its `latest_decision` summary.)

| Sealed token field | Session API field            | Values                                                                            |
| ------------------ | ---------------------------- | --------------------------------------------------------------------------------- |
| `verdict`          | `decision.automation_status` | `human` → `human`, `bot` → `automated`, `inconclusive` → `uncertain`              |
| `risk_score`       | `decision.risk_score`        | `0` – `100` integer (same scale)                                                  |
| `phase`            | `decision.evaluation_phase`  | `snapshot` or `behavioral` (may be `null` on sessions that haven't evaluated yet) |
| `is_provisional`   | `decision.decision_status`   | `true` → `preliminary`, `false` → `final`                                         |

The underlying data is identical — only the field names and the `automation_status` / `decision_status` value labels differ.

## Policy recommendations

1. **Start with report-only** — log verdicts without blocking for the first week
2. **Treat `inconclusive` as an opportunity** — challenge with CAPTCHA or email verification, don't block
3. **Wait for behavioral phase** on high-value actions when possible
4. **Use the score for edge cases** — a `bot` verdict at `71` is weaker than one at `98`
5. **Keep your Foil decision in your audit trail** — log the sessionId alongside the business action

## What's next

* [Detection categories](/detection-categories) — what signals feed into the score
* [Server verification](/server-verification) — verify handoffs on your backend
* [Sessions API](/api-reference/sessions) — full session detail response
