Data processed by OpenWAF Verify
Last updated: October 29, 2026
This is an English translation provided for convenience. In case of any discrepancy, the Spanish version prevails.
Draft, pending legal review. This text describes what OpenWAF Verify does today, checked against its code. It has not yet been reviewed by a lawyer and may change.
In short
- OpenWAF Verify checks that a browser did the work of a challenge. It does not try to identify the person.
- Signals are evaluated in the edge node’s memory and dropped. Per-network counters live there for about 10 minutes. What Verify keeps after that is counts per site and per minute, with no IP address, for 30 days.
- The «Check my browser» troubleshooting page keeps one record per check, with the network but never the full IP address, for 7 days, for support (section 2.9).
- No canvas, WebGL, audio or font fingerprints, no high-entropy client hints, no persistent device identifier and nothing that follows a visitor across sites.
- The only cookie on your site is
__waf_pass, set by the challenge page. The widget sets no cookie. The «Check my browser» page uses a short test cookie on its own domain. - You are the controller and OpenWAF is your processor under the Data Processing Agreement. The draft DPA annex for Verify describes the same processing in contract form.
1. What OpenWAF Verify is
Verify is the challenge engine of the OpenWAF edge. It has three parts, all served on your own host under /__waf/ by the edge nodes that already proxy your site. The visitor’s browser never contacts another domain for it.
- Challenge page. An interstitial page that a rule, the register-flood gate, AI Crawl Control, the WAF score or under attack mode shows before a page. The browser solves a proof of work and gets the
__waf_passcookie. See the browser challenge documentation. - Widget. A box you add to a form. The browser solves the same proof of work and gets a single-use token for your form. See the Verify widget documentation.
- Siteverify. The call your server makes to check that token, on your own host through the edge or on the control plane. See the siteverify reference.
Risk scoring adds a score from 0 to 100 to each challenge. It is on in log mode (counts only, nothing applied) unless you turn it off. See risk scoring.
When a check fails, the challenge page and the widget link to «Check my browser», a troubleshooting page at verify.openwaf.dev (section 2.9). Visitors only open it by following that link, or one sent by support.
2. What is processed
2.1 On every challenge
| Data | What for | How long |
|---|---|---|
| IP address of the visitor | To bind the challenge to the visitor’s network, to look up its network (ASN) in a database on the node, to check it against the node’s threat feeds and the WAF’s IP reputation, and for per-IP rate limits of the Verify endpoints. | In memory while the request is handled. Rate-limit counters: one-minute sliding windows, at most about two minutes. |
| Network prefix: the IPv4 /24 or IPv6 /64 of the address | The challenge, the token and the pass are valid only from that network. Per-network counters of recent challenges, failures and replays. | The challenge, the token and the counters use a hash of it; the __waf_pass cookie holds the prefix itself (section 4). Counters: about 10 minutes in the node’s memory. |
| Network (ASN) of the address | Whether it belongs to a list of hosting and datacenter networks; per-ASN counters of failed solves. | Counters: about 10 minutes in the node’s memory. |
| Proof of work: the solutions and the time between issue and solve | To check the work and to spot solves faster than a browser can do them, or solves that keep taking the same time. | Checked and dropped. The solve time feeds a histogram per site and minute. |
| Host and path of the request | To issue the challenge for the right site and rule. | Not kept by Verify. |
2.2 With risk scoring on
User-Agentand low-entropy headers every browser sends:Accept-Language,Sec-Fetch-Mode,Sec-CH-UA,Sec-CH-UA-Mobile,Sec-CH-UA-Platform. The edge never sendsAccept-CHto ask for more hints.- TLS ClientHello of the connection. The node reads it once, when the TLS handshake starts, and drops the raw bytes. From it the node keeps, for that connection only, a few traits and the JA4 fingerprint (FoxIO’s published algorithm, for example
t13d1516h2_8daaf6152771_e5627efa2ab1). The traits (TLS version, first ALPN value, GREASE values, theapplication_settingsandrecord_size_limitextensions, the number of cipher suites) are compared in memory with the browser theUser-Agentclaims, for thetls_mismatchsignal. Verify keeps neither the traits nor the JA4. When the request reaches the node through a TLS-terminating proxy that the node trusts, such as Cloudflare, or over plain HTTP, the node does not see the visitor’s ClientHello and computes nothing. - Answers of the browser checks, one yes or no per check (section 2.5).
The score is the sum of fixed weights of the signals that fired. The signals are a closed list of names. Server side: asn_hosting, ip_feed, ip_reputation, net_velocity, net_failures, asn_failures, net_replay, tls_mismatch, headers_missing, client_hints_mismatch, ua_automation, webdriver, solve_too_fast, solve_timing_repeat. Browser checks: cdp_runtime, native_patched, headless_env, worker_mismatch, click_dynamics, client_tampered. cdp_input is reserved and never fires. pat_valid lowers the score and fires only when Private Access Tokens are enabled (section 2.7). What each one looks at is in the signal list.
The counters behind net_*, asn_failures and the timing signals are kept per edge node, for every site that node serves, so a network that floods one site raises its score on another for about 10 minutes. They are not shared between nodes.
2.3 Challenge page
- The page sends back the challenge, the solutions and the answer of the browser checks.
- When the page asks for a click (under attack mode, or a high risk level in enforce mode), it also sends how the box was activated (pointer or keyboard) and the milliseconds since the box appeared. The edge checks them and drops them.
- A correct solution sets the
__waf_passcookie (section 4).
2.4 Widget
- The page sends the site key, the action and the
cdatavalue that you set on the widget. They travel inside the challenge and the token in readable form, so don’t put personal data incdata. - With the solution, the widget sends
navigator.webdriver(whether the browser says it is automated), whether there was any pointer or key press on the page before the check (yes or no, never movements or keys) and the answer of the browser checks. In the interactive step it sends how the box was activated and the milliseconds since it appeared, as on the challenge page. - The token holds the widget, host, action,
cdata, issue and expiry times, a random nonce, the mode, the risk level (loworhigh), whether there was interaction and a hash of the network prefix. It is valid for 300 seconds and once.
2.5 Browser checks
With risk scoring on, the challenge page and the widget run a few checks about automation frameworks: a DevTools protocol client attached to the page, built-in functions replaced by a script, a headless or emulated window, a Web Worker that describes a different browser than the page, and how the verification box was activated. Each check is compared inside the page. Only one bit per check leaves it (fired or not, ran or not), packed in a 32-bit number encoded for that challenge. The values compared, such as window sizes or the Worker’s user agent, are never sent.
2.6 Siteverify
- Your server sends the widget secret, the token, optionally the visitor’s IP address (
remoteip) and optionally anidempotency_key. remoteipis only compared, by hash, with the network the token is bound to. It is not stored.- The answer to a call with an
idempotency_keyis kept in the memory of the node or control plane that answered for 300 seconds, so a retry gets the same answer. - The answer never includes the score or the signals. It says whether the token is valid, its host, action,
cdata, issue time, mode, whether there was interaction and the risk levelloworhigh.
2.7 Private Access Tokens, when enabled
Not enabled today: OpenWAF has no trusted token issuer configured, so the edge never asks for a token. When it is enabled, and only on zones with risk scoring on, the edge can ask a supporting device for a Private Access Token (Privacy Pass, RFC 9576, RFC 9577 and RFC 9578) from a public issuer, bound to that challenge and your host. The device obtains the token from its issuer on its own; the edge sends nothing to the issuer. The node checks the issuer’s signature with the issuer’s public key, shipped in its signed configuration. A valid token can only lower the risk score (signal pat_valid). It never raises it and never passes a challenge on its own. The token is checked and dropped, not stored; the analytics count only how many challenges had a valid one.
2.8 Single use
To make each challenge and token usable once on every node, the edge counts a hash of its random nonce on the node and on the control plane. These counters contain no personal data and expire with the challenge (10 minutes) or the token (300 seconds), plus 30 seconds.
2.9 «Check my browser» page
Check my browser is a troubleshooting page that OpenWAF runs at verify.openwaf.dev. The link of a failed check carries the host the visitor was on and the challenge’s short ID. Under an organization’s white-label brand there is no link. What each check means is in the Check my browser documentation.
- In the browser, the page checks whether JavaScript, Web Workers, the Verify files and cookies work, how long a short proof of work takes,
navigator.webdriver, and whether the host of the link answers (a request to/__waf/challenge/v1/pingon that host, without cookies). - The edge that serves the page sends back its clock, the visitor’s IP address and two labels for it: whether it belongs to a data centre network, and whether it is on a threat list or the edge saw attacks from it recently (yes or no, never which list or a score). The IP address is only shown to the visitor. It is not stored.
- A test cookie,
__waf_check, onverify.openwaf.dev(HttpOnly,Secure,SameSite=Lax, limited to the check path) shows whether cookies work. It lasts at most 15 minutes and is deleted when the check is recorded. - When the checks end, the edge records the check: a random check ID, the time, the host that served the check, the host and challenge ID of the link, the network (the /24 or /64, never the full IP address), the browser family and major version (for example
chromium/156, not the full user agent), whether the test cookie came back, the two network labels and the results, each from a fixed list of values. The record is kept for 7 days on the edge node that served the page, and is also written to its log. - The record is only used by OpenWAF support, to find out why a check fails when the visitor or the site sends us its check ID. The text the visitor can copy for support shows the network instead of the IP address.
The page reads nothing about the device beyond what it shows the visitor: no canvas, WebGL, audio or font data.
3. What Verify never collects
- Canvas, WebGL, audio or font fingerprints, or the list of plugins.
- High-entropy client hints (full browser version, device model, architecture, platform version).
- Pointer movements, key presses or the text typed in your forms. The check of how the verification box was activated runs in the page and sends only its yes or no.
- Persistent device identifiers or identifiers that link a visitor across sites. Verify sets no cookie on any other domain and loads nothing from one.
4. The __waf_pass cookie
Set by the challenge page after a correct solution. The widget sets no cookie.
| Attribute | Value |
|---|---|
| Content | Expiry, the network prefix (for example 198.51.100.0/24), the host or zone it is valid for and the issue time, signed with a key of your zone. Nothing else identifies the visitor. |
| Lifetime | pass_ttl_minutes of the zone: 12 hours by default, from 5 minutes to 7 days. While under attack mode is on, the lifetime set for that mode (also 5 minutes to 7 days). |
| Flags | HttpOnly, Secure, SameSite=Lax, Path=/. |
| Domain | The host that issued it, or the whole zone (Domain=example.com) with pass_scope: zone. |
5. Purpose
Verify processes these data only to protect your service: to tell browsers from automated traffic, to slow down floods, credential stuffing and form spam, and to show you how your challenges perform. The «Check my browser» records serve only to troubleshoot failed checks for support. OpenWAF does not use them for advertising, does not build profiles of visitors, does not sell or share them, and does not use them for its own purposes, including improving its detection.
6. Where
- Challenges, tokens and passes are issued and checked on OpenWAF edge nodes in the European Union: Germany (Hetzner) and Madrid, Spain (Vultr).
- The counts per site and per minute are stored in Germany (Hetzner).
- The «Check my browser» page is served from Germany (Hetzner) through the same edge nodes, which also keep its records.
- Two paths cross Cloudflare, listed on our sub-processors page, in transit: the control-plane siteverify at
dash.openwaf.dev(the token and, if you send it,remoteip), and the traffic between edge nodes and the control plane (for Verify: hashed single-use counters and the counts, without IP addresses). Your server can avoid the first by calling siteverify on your own host. - AI Services LLC, which operates OpenWAF, is established in the United States. Access from outside the EEA relies on the Standard Contractual Clauses, as set out in section 9 of the Data Processing Agreement.
7. How long
| What | Where | How long |
|---|---|---|
| IP address, headers, ClientHello, solutions, browser-check answers | Node memory | While the request is handled |
| Per-network (hash of the /24 or /64) and per-ASN counters | Node memory | About 10 minutes (two 5-minute buckets) |
| Per-IP rate-limit counters of the Verify endpoints | Node | One-minute sliding windows, at most about two minutes |
| Single-use counters (hash of a nonce) | Node and control plane | 10 minutes for a challenge, 300 seconds for a token, plus 30 seconds |
Siteverify answers with an idempotency_key | Memory of the node or control plane | 300 seconds |
__waf_pass cookie | Visitor’s browser | 12 hours by default (5 minutes to 7 days) |
| Counts per site and minute, split by what served the challenge (the kind of rule, or the widget and its action): challenges issued, solved and failed by cause, solve-time histogram, siteverify results, risk levels, score buckets and signal names. No IP address. | Control plane (Germany) | 30 days |
| «Check my browser» records: check ID, time, hosts, challenge ID, network (/24 or /64), browser family and major version, test-cookie result, network labels and check results. No full IP address. | Edge node that served the page | 7 days, then deleted (the copy in the node log rotates like the log lines below) |
__waf_check test cookie of «Check my browser» | Visitor’s browser, on verify.openwaf.dev | Until the check is recorded, at most 15 minutes |
| Node log lines of some challenge events: under attack mode (host, IP address, method and path, a short challenge ID), failed widget checks (host, IP address, the reason, a short challenge ID, the widget) and unverified crawler claims (crawler name, IP address, host). Crawler lines, under attack failures and widget failures are logged at most once per interval, except refused ticks of the widget; under attack solves are logged each time. | Node logs | Rotated by size and overwritten, not archived |
The rule or policy that sent a visitor to the challenge (a WAF score, a rate rule, AI Crawl Control) may record its own security event, with the IP address, user agent and JA4 fingerprint, like any other security event. AI Crawl Control records its own events for AI agents and crawlers with the same fields. Those events belong to the WAF and AI Crawl Control, not to Verify, and are deleted after 30 days, as the Data Processing Agreement says. They store the JA4 as a text string in the field tls_fingerprint, never the ClientHello, and leave it empty behind a trusted proxy or over plain HTTP. When a client follows the AI Crawl Control trap, the node also marks its IP address and a hash of its JA4 within its /24 or /64 for 24 hours.
8. Roles
You decide where Verify runs and why, so you are the controller. OpenWAF processes the data on your behalf as your processor under the Data Processing Agreement. If you are an agency acting for your clients, you are their processor and OpenWAF is your sub-processor. OpenWAF does not act as a controller of these data.
9. Legal basis (draft position)
This section is a draft and has not been reviewed by a lawyer. It is not legal advice.
- GDPR. Your legitimate interest in the security of your service and your network (article 6.1.f GDPR; recital 49 names preventing unauthorised access and attacks as such an interest). The processing is limited to the data above, is short-lived and has no effect on the visitor beyond the challenge.
- ePrivacy. The challenge page and the widget read information from the visitor’s device (the browser checks and
navigator.webdriver), and the challenge page stores the__waf_passcookie. Our draft position is that this falls under the “strictly necessary” exemption of article 5.3 of Directive 2002/58/EC (in Spain, article 22.2 LSSI-CE): it is needed to provide the page or the form the visitor asked for, protected as you configured, and the data are used only for that. If a lawyer advises otherwise, we will update this page.
10. Sub-processors
Verify adds no sub-processor. It runs on the same infrastructure as the rest of OpenWAF Cloud: Hetzner (Germany) for the edge nodes, the control plane and the storage of the counts, Vultr (Madrid, Spain) for the Madrid edge node, and Cloudflare in transit as described in section 6. The full list is on the sub-processors page. No issuer of Private Access Tokens receives data from OpenWAF.
11. A paragraph for your privacy policy
You can adapt this text. Replace the bracketed parts.
To protect [this website] against automated abuse, some pages and forms use OpenWAF Verify, a security check provided by AI Services LLC (OpenWAF) as our processor. When it runs, your browser solves a small computing task, and OpenWAF’s servers in the European Union check it together with your IP address, the network it belongs to, your browser’s user agent and language headers, technical properties of your browser’s encrypted connection and a few yes/no checks about automation tools. These data are used only for security and are kept in memory for at most about 10 minutes; only counts without IP addresses are kept, for 30 days. The check may set a cookie named __waf_pass on [our domain], valid for [12 hours], so that you are not asked again. Our legal basis is our legitimate interest in keeping [this website] secure (article 6.1.f GDPR). More details: https://openwaf.dev/legal/verify-data/.
12. Contact
Questions about this page or about Verify: support@openwaf.dev. Visitors who want to exercise their rights should contact the website that showed the challenge; if they write to us, we forward the request to that customer, as section 7 of the Data Processing Agreement says.