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

# Progressive challenge mode: trust first, challenge later

> Enable progressive mode to let new visitors browse freely for a configurable number of requests before a CAPTCHA challenge appears.

By default verifyngo challenges every visitor on their first request. Progressive mode takes a lighter approach: it trusts new visitors initially and only shows a CAPTCHA once they have made more than a set number of page requests within a rolling time window. This avoids interrupting visitors who are clearly browsing normally.

## How it works

1. When a visitor hits a path listed in `passive_paths`, verifyngo sets a short-lived passive cookie and proxies the request through to your upstream without a challenge.
2. Each subsequent request to a `passive_paths` route increments a per-visitor counter.
3. Once the counter exceeds `max_requests` within the `request_window`, the next request triggers a real CAPTCHA challenge.
4. After the visitor solves the CAPTCHA, verifyngo issues a full verified cookie and the visitor is never challenged again — until that cookie expires.

Requests to static assets and paths matched by `bypass_paths` do not count toward the passive request budget.

## Configuration

Enable progressive mode by adding a `progressive` block to `config.json`:

```json theme={null}
"progressive": {
  "enabled": true,
  "passive_paths": [
    "^/$",
    "^/blog",
    "^/docs"
  ],
  "passive_ttl": "30m",
  "max_requests": 50,
  "request_window": "10m"
}
```

<ParamField body="enabled" type="boolean" default="false">
  Set to `true` to turn on progressive mode.
</ParamField>

<ParamField body="passive_paths" type="array of strings">
  The URL paths (as regular expressions) that participate in passive request counting. Only requests to matching paths increment the counter and receive a passive cookie. Keep this list to real page or navigation routes.
</ParamField>

<ParamField body="passive_ttl" type="string" default="30m">
  How long the passive cookie lasts. After it expires the visitor's counter resets and they start fresh. Accepts Go duration strings such as `"15m"`, `"1h"`, or `"2h30m"`.
</ParamField>

<ParamField body="max_requests" type="integer" default="50">
  The number of passive-path requests a visitor can make before a CAPTCHA challenge is triggered. Once the count goes over this threshold within `request_window`, the next request becomes a challenge.
</ParamField>

<ParamField body="request_window" type="string" default="10m">
  The rolling window over which requests are counted. Requests older than this window do not count toward the budget. Accepts Go duration strings such as `"5m"`, `"10m"`, or `"1h"`.
</ParamField>

<Tip>
  Keep `passive_paths` to a small list of real navigation routes. If you include paths that load many sub-resources (images, scripts, API calls), the budget fills up quickly and visitors may be challenged sooner than you intend.
</Tip>

<Note>
  Progressive mode and the verified cookie work together. Once a visitor has solved the CAPTCHA they receive a verified cookie, and progressive counting stops for them entirely until the verified cookie expires.
</Note>
