XF Bot Guard

XF Bot Guard 1.4.1

No permission to download
A false 404 error with the path /bot-guard/collect has appeared in Google's console. Any recommendations on how to best resolve this? So far, the only thing I can think of is editing the template and adding a robots directive to prevent indexing the page with the error.

I will figure out a patch to make it ignored that JSON endpoint.

Thing is, while Google etc. Is excluded from judgement (presuming you have the options enabled ti allow it) it will still be fingerprinted. Just no actions taken against it.

That's basically what its chatty about.
 
your custom CAPTCHA provider
There is still an oddity regarding that, but it is not an issue of Bot Guard but rather a misbehavior of Xen Foro: When you switch the Captcha provider in XF -> options -> registration XF will forget whatever values you had entered for the now deselected provider. I.e. it will forget the API Key and Secret for CF turnstile if you switch to a different provider.
As a consequence, in Bot Guard one can only use either the default provider or a provider that works w/o configuration (which is i.e. true for hCaptcha or, if installed, Altcha). It will however then fall back to the standard config for that provider (whereas with Altcha you could provide a custom secret or for hCaptcha use an API Key for a somewhat improved captcha). The "forgetting" may even be intentional by XF, yet it does somewhat undermine the idea for using a different provider within Bot Guard than during the registration process.
 
Last edited:
I have both of these installed:

XF Bot Guard 1.2.7

XF Surge Guard 1.0.3

Do we need both? Somehow I thought they were the same thing but I just realized they are different.
 
So I got this installed, but a little overwhelmed by the out-of-the-gate adjustments needed to stop all these bots? Are you supposed to pick a preset right off the bat or wait?
 
Do we need both?
Define "need". It depends from your setup and situation if any or both of them are advantagous.
Somehow I thought they were the same thing but I just realized they are different.
Would not make sense to have two identical add ons from the same developer, would it? They tackle different things with different methods, though both deal with bots and scrapers.
 
So I got this installed, but a little overwhelmed by the out-of-the-gate adjustments needed to stop all these bots?
This is what the presets are for.
Are you supposed to pick a preset right off the bat or wait?
This depends from your setup and situation. If you use i.e. Cloudflare you need different settings from if you not use it. Other than that the default values seem to work pretty well but obviously you have the choice if you want i.e. to use a captcha and which one.

This add-on has a pretty high level of complexity and adjustability and most settings are intended for people that know what they are doing. Some are however necessary for the thing to work properly and this depends from your setup. The provided documentation is very good, so probably you should read it.
 
Define "need". It depends from your setup and situation if any or both of them are advantagous.

Would not make sense to have two identical add ons from the same developer, would it? They tackle different things with different methods, though both deal with bots and scrapers.
@smallwheels I thought he changed the name and it was the same add-on. All this time I didn't realize I had two. My bad!
 
There is still an oddity regarding that, but it is not an issue of Bot Guard but rather a misbehavior of Xen Foro: When you switch the Captcha provider in XF -> options -> registration XF will forget whatever values you had entered for the now deselected provider. I.e. it will forget the API Key and Secret for CF turnstile if you switch to a different provider.
As a consequence, in Bot Guard one can only use either the default provider or a provider that works w/o configuration (which is i.e. true for hCaptcha or, if installed, Altcha). It will however then fall back to the standard config for that provider (whereas with Altcha you could provide a custom secret or for hCaptcha use an API Key for a somewhat improved captcha). The "forgetting" may even be intentional by XF, yet it does somewhat undermine the idea for using a different provider within Bot Guard than during the registration process.

Thanks for this report. This is on me for testing with hCaptcha as my 'other' provider choice... which requires no config. I missed this entirely! Good news is, looks like I can provide an option to extend XenForo CAPTCHA option saving so it won't actually delete the old one, just because you switched the provider radio option.
 
Do we need both? Somehow I thought they were the same thing but I just realized they are different.

I run both because they solve related, but different, problems.

XF Bot Guard is the smarter application-layer defence. It has more runtime overhead because it evaluates the visitor, their request, browser behaviour, session continuity, crawler verification, rate, and other signals before deciding whether to allow, validate, challenge, or deny the request. It is the sharper tool for identifying suspicious guests, scrapers, fake browsers, and abusive bot traffic.

XF Surge Guard is more of a load-shedding tool. It does not try to determine who the visitor is in the same way Bot Guard does. Instead, it looks for repeated unauthenticated guest requests that have already proven to be wasteful, such as bad routes, soft 404s, permission failures, scanner-style probes, or broken links. Once a pattern qualifies, it can temporarily return a lightweight early response before XenForo fully boots, routes, dispatches, queries, or renders the page.

So, in plain terms: Bot Guard is for deciding whether a visitor looks legitimate. Surge Guard is for stopping XenForo from repeatedly wasting resources on garbage guest requests that have already shown themselves to be low-value.
 
So I got this installed, but a little overwhelmed by the out-of-the-gate adjustments needed to stop all these bots? Are you supposed to pick a preset right off the bat or wait?

Yes - the presets are there specifically so you do not have to hand-tune everything immediately after install.

I would not recommend turning everything on blindly, though. The safest first step is to go to:

XF Bot Guard → Advanced → Health check

Make sure the basics look good first:

  • CAPTCHA provider
  • Real visitor IP / proxy handling
  • JavaScript assets
  • Template modification
  • Page-cache checks

Once that looks healthy, for most forums I would start with:

Cautious first rollout + SEO-sensitive overlay

The cautious preset starts with guest-only protection, a higher challenge threshold, and extra diagnostics, so you can watch the dashboard/event log without being too aggressive straight away.

The SEO overlay helps keep legitimate crawlers, sitemap/robots access, AI search/user-triggered fetchers, and social preview metadata handling in a safer state.

If the site is already under heavy bot pressure, use Active bot storm instead of Cautious, still with the SEO overlay. Just expect it to challenge more traffic.

I would only use Observe-only if you want reporting first without actually challenging or denying visitors.

I would reserve Origin survival mode for a real server-pressure emergency, because it can temporarily return 503s to unknown first-hit visitors.

So the usual path is:

Health check first → Cautious first rollout + SEO-sensitive overlay → watch the logs → move to Balanced production once things look healthy.
 
Yes - the presets are there specifically so you do not have to hand-tune everything immediately after install.

I would not recommend turning everything on blindly, though. The safest first step is to go to:

XF Bot Guard → Advanced → Health check

Make sure the basics look good first:

  • CAPTCHA provider
  • Real visitor IP / proxy handling
  • JavaScript assets
  • Template modification
  • Page-cache checks

Once that looks healthy, for most forums I would start with:

Cautious first rollout + SEO-sensitive overlay

The cautious preset starts with guest-only protection, a higher challenge threshold, and extra diagnostics, so you can watch the dashboard/event log without being too aggressive straight away.

The SEO overlay helps keep legitimate crawlers, sitemap/robots access, AI search/user-triggered fetchers, and social preview metadata handling in a safer state.

If the site is already under heavy bot pressure, use Active bot storm instead of Cautious, still with the SEO overlay. Just expect it to challenge more traffic.

I would only use Observe-only if you want reporting first without actually challenging or denying visitors.

I would reserve Origin survival mode for a real server-pressure emergency, because it can temporarily return 503s to unknown first-hit visitors.

So the usual path is:

Health check first → Cautious first rollout + SEO-sensitive overlay → watch the logs → move to Balanced production once things look healthy.
Thank you! It's already done incredible things for my CPU usage after a few hours! Amazing add-on!
 
Thank you! It's already done incredible things for my CPU usage after a few hours! Amazing add-on!

That's wonderful news!

I would really appreciate if you could share your experience by way of leaving a rating / review for the add-on. You can do so here: https://xenforo.com/community/resources/xf-bot-guard.10508/ (and at the top right, near the download button, will be an option to add your rating)

Also... if anyone else reading hasn't done this and found the add-on amazing... please do the same 🙏 and if you don't love it, please let me know why in the discussion here, so I can improve XF Bot Guard :)
 
For me /bot-guard/collect always returns 400 Bad Request due to nonce mismatch. Every user who was challenged was never able to complete verification (/bot-guard/solve redirects back to validating browser). Tried to debug /bot-guard/collect, but apparently actionCollect is never actually reached, as the nonce is checked elsewhere.

This occurred regardless whether page caching / session caching were enabled or not.

Then I tried to determine why users were being challenged to begin with. From what I could tell, one of the (several) problematic $context elements at issue was related to "cookie continuity", but it was not obvious where the add-on attempted to even set cookies.

Unfortunately I was unable to debug this further due to all the early exits the add-on performs.

I understand you are trying to reduce the performance impact of failed requests, but this add-on should remove all the early exits, and ensure flow goes through XenForo's normal view system. You can still use a custom renderer or something like that to reduce the overhead.

I also found myself needing to edit files because the default fallback route (index) was not customizable. And for some reason, /solve was redirecting to the default fallback route no matter which page triggered the interstitial.
 
Yes, the issue persists with 1.2.9. This initially occurred on 1.2.6, forcing me to disable it until I could dig further.
 
For me /bot-guard/collect always returns 400 Bad Request due to nonce mismatch. Every user who was challenged was never able to complete verification (/bot-guard/solve redirects back to validating browser). Tried to debug /bot-guard/collect, but apparently actionCollect is never actually reached, as the nonce is checked elsewhere.

This occurred regardless whether page caching / session caching were enabled or not.

Then I tried to determine why users were being challenged to begin with. From what I could tell, one of the (several) problematic $context elements at issue was related to "cookie continuity", but it was not obvious where the add-on attempted to even set cookies.

Unfortunately I was unable to debug this further due to all the early exits the add-on performs.

I understand you are trying to reduce the performance impact of failed requests, but this add-on should remove all the early exits, and ensure flow goes through XenForo's normal view system. You can still use a custom renderer or something like that to reduce the overhead.

I also found myself needing to edit files because the default fallback route (index) was not customizable. And for some reason, /solve was redirecting to the default fallback route no matter which page triggered the interstitial.

Can you please provide the support bundle? Go to ACP -> XF Bot Guard -> Health check

There are many reasons this could occur, many of which typically are covered by the health check. Meanwhile, I am investigating on my end for possibilities that live outside the current set of health checks.
 
Code:
XF Bot Guard redacted support bundle
Generated at: 2026-06-14 22:46:11 UTC
Redaction: Sensitive values are redacted before display. Review before sending.

Environment
- xenforo_version: 2.3.9
- xenforo_version_id: 2030970
- php_version: 8.5.2
- php_version_id: 80502
- xf_bot_guard_version: 1.2.9
- xf_bot_guard_version_id: 1020970

Configuration
- enabled: Yes
- observe_only: No
- scope: guests
- protected_areas: all_public
- selected_routes: forums, threads
- selected_content_types: forum, node, thread
- custom_paths: None
- excluded_paths: 22 configured
- threshold: 50
- logging: Yes
- low_value_logging: No
- low_value_allow_sample_rate: 0%
- retention_hours: {
    "events": 336,
    "visitors_fingerprints_ips": 336,
    "sessions": 336,
    "counters": 336,
    "dashboard_snapshots": 17520,
    "zero_signal_ips": 2160
}
- origin_pressure: {
    "survival_mode_enabled": "No",
    "survival_retry_after_seconds": 60,
    "db_enter_pct": 70,
    "db_exit_pct": 50,
    "minimum_active_seconds": 120,
    "load1_per_core_pct": 300,
    "cpu_busy_pct": 98,
    "io_wait_pct": 30,
    "swap_out_pages_per_second": 128,
    "cache_seconds": 5
}
- event_detail_write: {
    "mode": "automatic",
    "mode_label": "Automatic under origin pressure",
    "origin_pressure_db_enter_pct": 70,
    "origin_pressure_db_exit_pct": 50,
    "origin_pressure_min_seconds": 120,
    "buffer_enter_pct": 70,
    "buffer_exit_pct": 50,
    "buffer_min_seconds": 120,
    "buffer_grace_seconds": 120,
    "buffer_shard_count": 8,
    "flush_max_rows": 5000,
    "flush_max_seconds": 20,
    "flush_rows_per_insert": 500
}
- cloudflare_edge: {
    "enabled": "No",
    "dry_run": "No",
    "raw_ip_storage": "No",
    "minimum_score": 90,
    "forgiveness_priority_cutoff": 160
}

Health checks
- Source: Stored/local diagnostics only. Building this bundle does not run a live Cloudflare API check.
- [ok] Add-on toggle: Enabled - Bot Guard is enabled.
- [ok] JavaScript collector: Enabled - The bundled collector is configured to load.
- [ok] CAPTCHA configuration: Cloudflare Turnstile - Bot Guard inherits XenForo CAPTCHA provider: Cloudflare Turnstile.
- [ok] Secure random generator: Available - PHP random_bytes() is available for Bot Guard token generation.
- [ok] PAGE_CONTAINER template modification: Enabled - The collector include is available on public pages.
- [ok] Collector JavaScript asset: Present - js/zee/botguard/botguard.js
- [ok] Bundled FingerprintJS asset: Present - js/zee/botguard/fingerprintjs/fp.min.js
- [ok] DigitalPoint Cloudflare guest page caching: Inactive - DigitalPoint Cloudflare add-on is not active.
- [warning] Shared full-page cache probe: Not checked - No cached shared-cache probe result is available. Run the live cache probe action to test public HTML caching.
- [warning] Cloudflare Edge Enforcement: Disabled - Cloudflare Edge Enforcement is disabled.
- [ok] Cloudflare dry run: Disabled - Cloudflare sync can write managed list changes.
- [ok] Effective Cloudflare sync mode: Live writes enabled - Cloudflare sync can write managed list changes.
- [warning] Cloudflare managed setup: Incomplete - Cloudflare Edge Enforcement setup is incomplete. Detailed configuration state requires viewBotGuardSensitive.
- [ok] Active local candidate count: 0 - Local active edge candidate aggregate count.
- [ok] Pending sync backlog size: 0 - Aggregate number of local rows waiting to be added to or removed from Cloudflare.
- [ok] Failed sync row count: 0 - Aggregate local rows with recent sync failures. Detailed diagnostics require viewBotGuardSensitive.
- [warning] Last successful sync age: Never - Cloudflare sync has not completed yet.
- [ok] Audit event logging: Enabled - Security audit rows can be retained.
- [ok] Low-value audit rows: Suppressed by default - Ordinary allow/skip rows are suppressed unless sampled.
- [ok] Low-value allow sample rate: 0% - Sampled low-value rows are retained only when low-value logging is disabled and this is greater than zero.
- [ok] Request gate fail-open evidence: None recorded - No request-gate fail-open marker is currently recorded in local health state.
- [ok] Event detail write mode: Automatic under origin pressure - Supplementary event detail rows write directly unless cached shared origin pressure is active.
- [warning] Origin pressure mode: Unknown - Could not read cached origin pressure state.
- [ok] Buffer path writable: Writable - The event detail buffer path is writable: [redacted-path]
- [ok] Pending detail files: 0 / 0 B - No pending event detail buffer files.
- [ok] Processing detail files: 0 - No detail files are currently processing.
- [ok] Failed detail files: 0 / 0 B - No failed detail buffer files.
- [ok] Last detail flush: 2026-06-14 22:46:09 / 2ms - Rows inserted last flush: 0. Rows failed last flush: 0.
- [ok] Event retention: 336 hours - Raw event rows older than this are removed by the cleanup cron. Manual visitor reports are retained for their 24-hour scoring window.
- [ok] Visitor/fingerprint-IP retention: 336 hours - Inactive visitor rows and fingerprint/IP relationship rows use the same visitor retention window. Lower values reduce long-horizon relationship memory.
- [ok] Session retention: 336 hours - Inactive session rows older than this are removed by cleanup, while unexpired trusted sessions are preserved.
- [ok] Counter retention: 336 hours - Operational counter buckets are cleaned by the normal cleanup cron after the configured raw retention window.
- [ok] Dashboard snapshot retention: 17520 hours - Compact hourly dashboard report snapshots are retained independently from raw event/session/visitor/counter data.
- [ok] Raw cleanup batching: Enabled - Cleanup deletes run in bounded batches of up to 1,000 rows, with a hard 5,000-row query limit, a 50,000-row per-table run cap, and a 20-second cleanup run budget. Partial runs resume naturally on the next cron run.
- [ok] Last cleanup run: No run recorded - A cleanup summary will be shown here after the cleanup cron has completed at least once with this version.
- [ok] Zero-signal IP pruning: Enabled / 2160 hours - Only stale xf_zee_botguard_ip rows with zero risk, zero reputation, no CAPTCHA history, no fingerprint/dynamic/protected-route activity, and NULL metadata are eligible for cleanup. Reputation-bearing or challenge-history IP rows are retained.
- [ok] Physical disk reclaim: 0 B reusable reported - No Bot Guard table with data currently shows notable reusable InnoDB space in cheap metadata. Bot Guard cleanup may remove old rows, but MySQL/InnoDB may not return disk space to the operating system until affected tables are rebuilt. Run OPTIMIZE TABLE or an equivalent online rebuild during a low-traffic maintenance window only if you need to reclaim disk immediately. Run one table at a time on l
- [ok] Known crawler trust: Disabled - Known crawler trust is disabled by default.
- [ok] Origin lockdown acknowledgement: Not acknowledged - Trusted proxy-derived known crawler, country and ASN headers are ignored unless this acknowledgement is recorded.
- [ok] Verified crawler IP allowlist: Enabled - Official crawler/fetcher CIDR ranges are allowed when matched locally.
- [ok] Known crawler source table: 12 rows approx / 48 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Known crawler range table: 2,866 rows approx / 1 MB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Known crawler sources: 12 enabled sources / 12 refreshed successfully / 2,886 ranges - Official crawler/fetcher source refresh state looks healthy.
- [ok] ASN range cache table: 0 rows approx / 80 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] ASN range cache: 0 configured ASNs - No decimal ASN entries are configured in the excluded or forced challenge network lists.
- [ok] Network CIDR JSON source table: 0 rows approx / 64 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Network CIDR JSON range table: 0 rows approx / 96 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Network CIDR JSON sources: 0 configured sources - No additional excluded or forced challenge CIDR JSON sources are configured.
- [ok] Reverse DNS hosting cache table: 0 rows approx / 80 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Reverse DNS hosting scoring: Enabled / 0 cached rows / 0 confirmed hosting matches / 0 recent resolver errors / 0 stale pending - Reverse-DNS hosting/datacenter scoring is enabled and the cache state looks healthy.
- [ok] Event table: 38 rows approx / 144 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Event detail table: 38 rows approx / 64 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Counter table: 42 rows approx / 64 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Contextual canary registry table: 0 rows approx / 112 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Dashboard snapshot table: 0 rows approx / 64 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Dashboard snapshot metric table: 0 rows approx / 48 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Dashboard snapshot cron: Active hourly at :10 - Snapshot cron is configured and active.
- [warning] Latest dashboard snapshot: None - Dashboard snapshot table exists but no trusted snapshots have been generated yet.
- [warning] Dashboard snapshot backfill: No snapshots - Dashboard snapshot table exists but no trusted snapshots have been generated yet.
- [ok] Dashboard snapshot integrity: Clean - No premature snapshots, orphan metric rows, failed snapshot rows, stale backfill current-state rows, or ok non-empty snapshots without metrics were detected.
- [ok] Dashboard snapshot pruning: 17520 hours - Snapshot pruning is configured separately from raw cleanup and deletes metric rows before snapshot header rows.
- [ok] Hash secret / globalSalt: Available - Hashing is available for privacy-preserving identifiers.

Warning/error health rows
- [warning] Shared full-page cache probe: Not checked - No cached shared-cache probe result is available. Run the live cache probe action to test public HTML caching.
- [warning] Cloudflare Edge Enforcement: Disabled - Cloudflare Edge Enforcement is disabled.
- [warning] Cloudflare managed setup: Incomplete - Cloudflare Edge Enforcement setup is incomplete. Detailed configuration state requires viewBotGuardSensitive.
- [warning] Last successful sync age: Never - Cloudflare sync has not completed yet.
- [warning] Origin pressure mode: Unknown - Could not read cached origin pressure state.
- [warning] Latest dashboard snapshot: None - Dashboard snapshot table exists but no trusted snapshots have been generated yet.
- [warning] Dashboard snapshot backfill: No snapshots - Dashboard snapshot table exists but no trusted snapshots have been generated yet.

Recent event summaries
- #38 2026-06-14 22:45:26 UTC decision=observe event_type=sensitive_route risk=0 route=api/auth/validate-sso
- #37 2026-06-14 22:45:15 UTC decision=observe event_type=error_route risk=0 route=bot-guard/collect
- #36 2026-06-14 22:45:15 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect
- #35 2026-06-14 22:45:14 UTC decision=observe event_type=error_route risk=0 route=bot-guard/collect
- #34 2026-06-14 22:45:14 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect
- #33 2026-06-14 22:45:13 UTC decision=allow event_type=verified_crawler_allow risk=0 route=whats-new/studio-pages/1308047
- #32 2026-06-14 22:45:02 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect
- #31 2026-06-14 22:44:59 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect
- #30 2026-06-14 22:44:57 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect
- #29 2026-06-14 22:44:56 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect

Current page context
- source: support_bundle
Also note, it says:
- [warning] Shared full-page cache probe: Not checked - No cached shared-cache probe result is available. Run the live cache probe action to test public HTML caching.
But my health page says different:
[OK] | Shared full-page cache probe | Checked 2026-06-14 22:47:33 | No definite shared full-page cache HIT evidence was observed. Bot Guard route: no shared cache HIT evidence observed; Board/homepage: no shared cache HIT evidence observed
 
Code:
XF Bot Guard redacted support bundle
Generated at: 2026-06-14 22:46:11 UTC
Redaction: Sensitive values are redacted before display. Review before sending.

Environment
- xenforo_version: 2.3.9
- xenforo_version_id: 2030970
- php_version: 8.5.2
- php_version_id: 80502
- xf_bot_guard_version: 1.2.9
- xf_bot_guard_version_id: 1020970

Configuration
- enabled: Yes
- observe_only: No
- scope: guests
- protected_areas: all_public
- selected_routes: forums, threads
- selected_content_types: forum, node, thread
- custom_paths: None
- excluded_paths: 22 configured
- threshold: 50
- logging: Yes
- low_value_logging: No
- low_value_allow_sample_rate: 0%
- retention_hours: {
    "events": 336,
    "visitors_fingerprints_ips": 336,
    "sessions": 336,
    "counters": 336,
    "dashboard_snapshots": 17520,
    "zero_signal_ips": 2160
}
- origin_pressure: {
    "survival_mode_enabled": "No",
    "survival_retry_after_seconds": 60,
    "db_enter_pct": 70,
    "db_exit_pct": 50,
    "minimum_active_seconds": 120,
    "load1_per_core_pct": 300,
    "cpu_busy_pct": 98,
    "io_wait_pct": 30,
    "swap_out_pages_per_second": 128,
    "cache_seconds": 5
}
- event_detail_write: {
    "mode": "automatic",
    "mode_label": "Automatic under origin pressure",
    "origin_pressure_db_enter_pct": 70,
    "origin_pressure_db_exit_pct": 50,
    "origin_pressure_min_seconds": 120,
    "buffer_enter_pct": 70,
    "buffer_exit_pct": 50,
    "buffer_min_seconds": 120,
    "buffer_grace_seconds": 120,
    "buffer_shard_count": 8,
    "flush_max_rows": 5000,
    "flush_max_seconds": 20,
    "flush_rows_per_insert": 500
}
- cloudflare_edge: {
    "enabled": "No",
    "dry_run": "No",
    "raw_ip_storage": "No",
    "minimum_score": 90,
    "forgiveness_priority_cutoff": 160
}

Health checks
- Source: Stored/local diagnostics only. Building this bundle does not run a live Cloudflare API check.
- [ok] Add-on toggle: Enabled - Bot Guard is enabled.
- [ok] JavaScript collector: Enabled - The bundled collector is configured to load.
- [ok] CAPTCHA configuration: Cloudflare Turnstile - Bot Guard inherits XenForo CAPTCHA provider: Cloudflare Turnstile.
- [ok] Secure random generator: Available - PHP random_bytes() is available for Bot Guard token generation.
- [ok] PAGE_CONTAINER template modification: Enabled - The collector include is available on public pages.
- [ok] Collector JavaScript asset: Present - js/zee/botguard/botguard.js
- [ok] Bundled FingerprintJS asset: Present - js/zee/botguard/fingerprintjs/fp.min.js
- [ok] DigitalPoint Cloudflare guest page caching: Inactive - DigitalPoint Cloudflare add-on is not active.
- [warning] Shared full-page cache probe: Not checked - No cached shared-cache probe result is available. Run the live cache probe action to test public HTML caching.
- [warning] Cloudflare Edge Enforcement: Disabled - Cloudflare Edge Enforcement is disabled.
- [ok] Cloudflare dry run: Disabled - Cloudflare sync can write managed list changes.
- [ok] Effective Cloudflare sync mode: Live writes enabled - Cloudflare sync can write managed list changes.
- [warning] Cloudflare managed setup: Incomplete - Cloudflare Edge Enforcement setup is incomplete. Detailed configuration state requires viewBotGuardSensitive.
- [ok] Active local candidate count: 0 - Local active edge candidate aggregate count.
- [ok] Pending sync backlog size: 0 - Aggregate number of local rows waiting to be added to or removed from Cloudflare.
- [ok] Failed sync row count: 0 - Aggregate local rows with recent sync failures. Detailed diagnostics require viewBotGuardSensitive.
- [warning] Last successful sync age: Never - Cloudflare sync has not completed yet.
- [ok] Audit event logging: Enabled - Security audit rows can be retained.
- [ok] Low-value audit rows: Suppressed by default - Ordinary allow/skip rows are suppressed unless sampled.
- [ok] Low-value allow sample rate: 0% - Sampled low-value rows are retained only when low-value logging is disabled and this is greater than zero.
- [ok] Request gate fail-open evidence: None recorded - No request-gate fail-open marker is currently recorded in local health state.
- [ok] Event detail write mode: Automatic under origin pressure - Supplementary event detail rows write directly unless cached shared origin pressure is active.
- [warning] Origin pressure mode: Unknown - Could not read cached origin pressure state.
- [ok] Buffer path writable: Writable - The event detail buffer path is writable: [redacted-path]
- [ok] Pending detail files: 0 / 0 B - No pending event detail buffer files.
- [ok] Processing detail files: 0 - No detail files are currently processing.
- [ok] Failed detail files: 0 / 0 B - No failed detail buffer files.
- [ok] Last detail flush: 2026-06-14 22:46:09 / 2ms - Rows inserted last flush: 0. Rows failed last flush: 0.
- [ok] Event retention: 336 hours - Raw event rows older than this are removed by the cleanup cron. Manual visitor reports are retained for their 24-hour scoring window.
- [ok] Visitor/fingerprint-IP retention: 336 hours - Inactive visitor rows and fingerprint/IP relationship rows use the same visitor retention window. Lower values reduce long-horizon relationship memory.
- [ok] Session retention: 336 hours - Inactive session rows older than this are removed by cleanup, while unexpired trusted sessions are preserved.
- [ok] Counter retention: 336 hours - Operational counter buckets are cleaned by the normal cleanup cron after the configured raw retention window.
- [ok] Dashboard snapshot retention: 17520 hours - Compact hourly dashboard report snapshots are retained independently from raw event/session/visitor/counter data.
- [ok] Raw cleanup batching: Enabled - Cleanup deletes run in bounded batches of up to 1,000 rows, with a hard 5,000-row query limit, a 50,000-row per-table run cap, and a 20-second cleanup run budget. Partial runs resume naturally on the next cron run.
- [ok] Last cleanup run: No run recorded - A cleanup summary will be shown here after the cleanup cron has completed at least once with this version.
- [ok] Zero-signal IP pruning: Enabled / 2160 hours - Only stale xf_zee_botguard_ip rows with zero risk, zero reputation, no CAPTCHA history, no fingerprint/dynamic/protected-route activity, and NULL metadata are eligible for cleanup. Reputation-bearing or challenge-history IP rows are retained.
- [ok] Physical disk reclaim: 0 B reusable reported - No Bot Guard table with data currently shows notable reusable InnoDB space in cheap metadata. Bot Guard cleanup may remove old rows, but MySQL/InnoDB may not return disk space to the operating system until affected tables are rebuilt. Run OPTIMIZE TABLE or an equivalent online rebuild during a low-traffic maintenance window only if you need to reclaim disk immediately. Run one table at a time on l
- [ok] Known crawler trust: Disabled - Known crawler trust is disabled by default.
- [ok] Origin lockdown acknowledgement: Not acknowledged - Trusted proxy-derived known crawler, country and ASN headers are ignored unless this acknowledgement is recorded.
- [ok] Verified crawler IP allowlist: Enabled - Official crawler/fetcher CIDR ranges are allowed when matched locally.
- [ok] Known crawler source table: 12 rows approx / 48 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Known crawler range table: 2,866 rows approx / 1 MB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Known crawler sources: 12 enabled sources / 12 refreshed successfully / 2,886 ranges - Official crawler/fetcher source refresh state looks healthy.
- [ok] ASN range cache table: 0 rows approx / 80 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] ASN range cache: 0 configured ASNs - No decimal ASN entries are configured in the excluded or forced challenge network lists.
- [ok] Network CIDR JSON source table: 0 rows approx / 64 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Network CIDR JSON range table: 0 rows approx / 96 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Network CIDR JSON sources: 0 configured sources - No additional excluded or forced challenge CIDR JSON sources are configured.
- [ok] Reverse DNS hosting cache table: 0 rows approx / 80 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Reverse DNS hosting scoring: Enabled / 0 cached rows / 0 confirmed hosting matches / 0 recent resolver errors / 0 stale pending - Reverse-DNS hosting/datacenter scoring is enabled and the cache state looks healthy.
- [ok] Event table: 38 rows approx / 144 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Event detail table: 38 rows approx / 64 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Counter table: 42 rows approx / 64 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Contextual canary registry table: 0 rows approx / 112 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Dashboard snapshot table: 0 rows approx / 64 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Dashboard snapshot metric table: 0 rows approx / 48 KB - Approximate metadata from information_schema; no full COUNT(*) was run.
- [ok] Dashboard snapshot cron: Active hourly at :10 - Snapshot cron is configured and active.
- [warning] Latest dashboard snapshot: None - Dashboard snapshot table exists but no trusted snapshots have been generated yet.
- [warning] Dashboard snapshot backfill: No snapshots - Dashboard snapshot table exists but no trusted snapshots have been generated yet.
- [ok] Dashboard snapshot integrity: Clean - No premature snapshots, orphan metric rows, failed snapshot rows, stale backfill current-state rows, or ok non-empty snapshots without metrics were detected.
- [ok] Dashboard snapshot pruning: 17520 hours - Snapshot pruning is configured separately from raw cleanup and deletes metric rows before snapshot header rows.
- [ok] Hash secret / globalSalt: Available - Hashing is available for privacy-preserving identifiers.

Warning/error health rows
- [warning] Shared full-page cache probe: Not checked - No cached shared-cache probe result is available. Run the live cache probe action to test public HTML caching.
- [warning] Cloudflare Edge Enforcement: Disabled - Cloudflare Edge Enforcement is disabled.
- [warning] Cloudflare managed setup: Incomplete - Cloudflare Edge Enforcement setup is incomplete. Detailed configuration state requires viewBotGuardSensitive.
- [warning] Last successful sync age: Never - Cloudflare sync has not completed yet.
- [warning] Origin pressure mode: Unknown - Could not read cached origin pressure state.
- [warning] Latest dashboard snapshot: None - Dashboard snapshot table exists but no trusted snapshots have been generated yet.
- [warning] Dashboard snapshot backfill: No snapshots - Dashboard snapshot table exists but no trusted snapshots have been generated yet.

Recent event summaries
- #38 2026-06-14 22:45:26 UTC decision=observe event_type=sensitive_route risk=0 route=api/auth/validate-sso
- #37 2026-06-14 22:45:15 UTC decision=observe event_type=error_route risk=0 route=bot-guard/collect
- #36 2026-06-14 22:45:15 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect
- #35 2026-06-14 22:45:14 UTC decision=observe event_type=error_route risk=0 route=bot-guard/collect
- #34 2026-06-14 22:45:14 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect
- #33 2026-06-14 22:45:13 UTC decision=allow event_type=verified_crawler_allow risk=0 route=whats-new/studio-pages/1308047
- #32 2026-06-14 22:45:02 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect
- #31 2026-06-14 22:44:59 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect
- #30 2026-06-14 22:44:57 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect
- #29 2026-06-14 22:44:56 UTC decision=observe event_type=collector_nonce_context_mismatch risk=0 route=bot-guard/collect

Current page context
- source: support_bundle
Also note, it says:

But my health page says different:

Are you behind Cloudflare or the like? If so, can you confirm PHP see's the IP address of your users, and not Cloudflares own IP address?

If you go to the XenForo /online/ it should be showing IP addresses that do not belong to Cloudflare.

The contant nonce mismatch may indicate this is the cause. Still digging on my end.
 
RE: cleanup cron for xf_zee_botguard_event (and likely _detail/_session too, same pattern).

I started digging into this because I noticed CPU usage ticked up a bit and free disk space has been steadily declining. That led me to check table sizes, and the BotGuard tables turned out to be the main consumer — xf_zee_botguard_event alone is ~1.6 GB with 2.4M+ rows.

I checked and the oldest row was 4.3 days old despite the 24h retention setting — and this was already the case under my previous "threads plus forums" monitoring scope, before I enabled "monitor all pages" a few hours ago. So the cleanup lag seems to be a pre-existing issue, not something newly caused by the wider monitoring scope (though the extra volume from "all pages" will make it worse).

When I manually triggered the cleanup cron, it deleted about 49K rows in that one run. Any suggestions?
 
Back
Top Bottom