Fix Uptime Monitor False Alerts From Cloudflare Bot Challenges: 5-Step Allowlist Guide
Your uptime monitor says the site is down. Cloudflare is blocking it.
The Slack alert came through at 3:17am: "Production endpoint unreachable — api.example.com returning 403." I grabbed my phone, pulled up the site in Safari. Loaded instantly. Checked Chrome. Fine. Opened my laptop, VPN'd into the office network, tried again. Still fine.
Went back to the monitoring dashboard. The probe showed consistent failures — every 60 seconds for the past 11 minutes. Our site had been "down" for almost 15 minutes according to the monitor. Zero user complaints. Zero support tickets. Zero errors in our actual error tracking.
Here's what actually happened: we'd tightened Cloudflare's bot management settings that afternoon. Enabled the "managed challenge" for suspicious traffic. Forgot that our uptime monitors are, from Cloudflare's perspective, suspicious traffic.
Every HTTP probe from Pingdom or UptimeRobot or JustAnalytics or any monitoring service looks like a bot. Because it is one. Cloudflare was doing exactly what we asked — challenging bots. We shot ourselves in the foot. If you're new to how uptime monitoring works under the hood, our how uptime checks work explained post covers the fundamentals.
This is embarrassingly common. I've made this exact mistake twice — once at my last company, once here. You'd think I'd learn. The fix is straightforward once you understand what's happening.
What's Actually Going On
When Cloudflare's bot management evaluates an incoming request, it considers several signals:
TLS fingerprint. Real browsers have distinctive TLS handshake patterns. Monitoring probes using standard HTTP libraries (curl, Node's https, Python's requests) have different fingerprints that Cloudflare flags as non-browser traffic.
JavaScript execution. Cloudflare's managed challenge serves JavaScript that a real browser executes automatically. HTTP-only probes can't run JavaScript — they just fetch HTML and move on. Dead giveaway.
Request headers. Browser requests include specific patterns of Accept headers, Accept-Language, connection handling. Probes often send minimal headers or obviously automated patterns. I once spent two hours debugging why a custom monitor kept failing before realizing it was sending literally zero Accept headers.
IP reputation. AWS, GCP, Azure — Cloudflare maintains databases of datacenter ranges and knows traffic from them is rarely end-user browsing. Your probe's IP screams "I am a server" from the moment the connection opens.
When your probe request hits Cloudflare and fails these checks, Cloudflare doesn't return your actual site. It returns one of:
- A 403 Forbidden response
- A 503 Service Unavailable (for some challenge modes)
- A 200 response containing challenge HTML instead of your page
- A redirect to a challenge URL
Your uptime monitor sees this response and correctly reports: "This isn't the expected 200 with your actual content." It's not wrong. It's just seeing what Cloudflare showed it.
The maddening part? Real users are fine. Their browsers pass the challenge invisibly. Your monitoring thinks the site is down. Your on-call engineer gets woken up at 3am for nothing. Everyone's annoyed. You lose trust in your alerts. (And honestly? Losing trust in your alerting is worse than the false alarm itself.)
Prerequisites
Before you start configuring allowlists, you need:
- Access to your Cloudflare dashboard with permission to modify WAF rules and IP Access Rules
- Your monitoring provider's probe IP addresses (most publish these publicly)
- A test endpoint to verify the fix works before relying on it
- Current WAF rule understanding (know what rules you have before modifying them)
If you're running multiple monitoring services, collect all their IP ranges now. You'll allowlist them all in one pass.
Step 1: Find Your Monitoring Provider's Probe IPs
Every major uptime service publishes their probe IP addresses. They have to — otherwise nobody could allowlist them.
JustAnalytics probe IPs:
Check the documentation at justanalytics.app/docs/uptime-probes or the settings page in your dashboard. The IP list updates when new probe regions are added, so check the live source rather than copying from a blog post that might be outdated.
Pingdom:
https://my.pingdom.com/probes/ipv4
https://my.pingdom.com/probes/ipv6
These endpoints return plain text lists of current probe IPs. Pingdom rotates IPs occasionally, so automate fetching if you're paranoid.
UptimeRobot:
Check their documentation — they publish ranges on their help site. UptimeRobot uses fewer probe locations than some providers, so the list is shorter.
Better Stack (formerly Better Uptime):
Published in their docs. They're transparent about which cloud providers host their probes.
Datadog Synthetics:
Datadog publishes their synthetic monitoring IPs. The list is long because they run from many regions.
For JustAnalytics specifically, we run probes from six regions by default: US East, US West, Europe, Asia Pacific, South America, and Australia. The IP list is available in your dashboard under Uptime → Settings → Probe IPs.
Save the IP list. You'll need it in the next step.
Step 2: Create a Cloudflare IP Access Rule
The cleanest approach is an IP Access Rule that bypasses bot challenges for your probe IPs.
In your Cloudflare dashboard:
- Select the zone (domain) you want to configure
- Go to Security → WAF → Tools
- Under IP Access Rules, click Create rule
For each probe IP or CIDR range:
- IP address/range: Enter the IP (e.g.,
203.0.113.42) or range (e.g.,203.0.113.0/24) - Action: Select "Allow"
- Zone: Apply to the specific zone or all zones
The "Allow" action tells Cloudflare to skip bot challenges for requests from this IP. Other WAF rules (SQL injection protection, XSS filtering, rate limiting based on other criteria) still apply. You're not disabling security — you're just telling Cloudflare "this IP is mine, chill out."
If you have many IPs, you can add them via the Cloudflare API:
# Add a single IP to the allowlist
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/firewall/access_rules/rules" \
-H "Authorization: Bearer {api_token}" \
-H "Content-Type: application/json" \
--data '{
"mode": "whitelist",
"configuration": {
"target": "ip",
"value": "203.0.113.42"
},
"notes": "JustAnalytics uptime probe - US East"
}'
Pro tip: Add descriptive notes to each rule. When you're debugging six months from now and see random IPs allowlisted, you'll want to know why they're there. "JustAnalytics US East" beats "uptime thing IDK."
Step 3: Verify the Fix Actually Works
Don't assume the allowlist works. Verify it.
Manual test:
If you can access one of your probe IPs directly (unlikely unless you run your own monitoring), make a request from it and confirm you get your actual page, not a challenge.
Monitoring service test:
Most uptime services let you run an on-demand check. In JustAnalytics:
- Go to your monitor settings
- Click "Test Now" or equivalent
- Check the response — you should see a 200 status with your actual content, not challenge HTML
Response body validation (this is the real test):
Configure your monitor to check for a specific string in the response body. Something like:
- Your company name in the footer
- A deliberately placed string like
<!-- health-check-ok --> - A unique element ID that only exists on your real page
If the probe receives a Cloudflare challenge page instead of your site, the string won't be present. The check fails as expected, and you know the allowlist isn't working.
This catches a subtle failure mode: Cloudflare sometimes returns 200 status codes with challenge HTML. Without body validation, your monitor sees "200 OK" and reports everything fine. Meanwhile, you're serving challenge pages to some users. Not good. Actually, kind of terrible. I learned this one the hard way when we had a "100% uptime" month that definitely wasn't 100% uptime.
Step 4: Handle Multiple Cloudflare Accounts or Zones
If you're monitoring sites across multiple Cloudflare accounts or zones, repeat the process for each. There's no cross-account IP Access Rule sharing.
For organizations managing many zones, consider:
Terraform or Pulumi: Define your probe IP allowlist as infrastructure-as-code. One source of truth, applied to all zones.
# Terraform example
resource "cloudflare_access_rule" "uptime_probe" {
zone_id = var.zone_id
mode = "whitelist"
configuration {
target = "ip"
value = "203.0.113.42"
}
notes = "JustAnalytics uptime probe"
}
Cloudflare API automation: Script the allowlist creation across all zones when probe IPs change.
(I spent a weekend building a sync script after our third "why is this zone not allowlisted" incident. Lost most of Saturday to it. Should've automated from day one, but hindsight's great like that.)
Step 5: Set Up Response Body Validation as a Safety Net
Even after allowlisting, things can break. Cloudflare updates their bot detection. Your monitoring provider adds new probe IPs you didn't know about. Someone accidentally deletes the allowlist rule.
Response body validation catches these regressions.
In your uptime monitor configuration:
- Enable response validation or "keyword" checking
- Add a string that appears on your real page but not on Cloudflare challenges
- Set the monitor to fail if the string is missing
Good strings to check for:
</html>(challenge pages might not have proper HTML structure)- Your actual page title:
<title>Your App Name</title> - A footer copyright:
© 2026 Your Company - A deliberate health string in a comment:
<!-- monitoring-ok -->
Bad strings to check for:
- Generic words that might appear in challenge pages too
- Strings that change between deploys (version numbers, timestamps)
- Strings only present on certain page variants (A/B tests)
JustAnalytics supports response body validation on all HTTP monitors. Set it up once, forget about it until it saves you from a 3am false alarm. We've covered related false-positive problems in our Safari ITP undercounting fix and alert deduplication guide.
Alternative: User-Agent Allowlisting
If your monitoring provider rotates IPs frequently or doesn't publish them, User-Agent allowlisting is a fallback.
In Cloudflare:
- Go to Security → WAF → Custom Rules
- Create a new rule with expression:
(http.user_agent contains "Pingdom" or http.user_agent contains "JustAnalytics") - Action: Skip (bypass managed challenge)
The problem: User-Agent strings are trivially spoofed. Any script kiddie can send User-Agent: Pingdom/1.0 and waltz past your bot protection. I genuinely dislike this approach. It works, sure, but it feels like leaving your door unlocked because you trust the neighborhood.
Use User-Agent rules only if:
- IP allowlisting genuinely isn't possible
- You accept the reduced security posture
- You're combining it with other detection layers
For most setups, IP allowlisting is the right answer. User-Agent is the backup.
What About Akamai, Fastly, or Other CDNs?
Same concept, different interface.
Akamai: Use the Property Manager to add probe IPs to an allowlist match condition that skips bot manager evaluation. Their UI is... an acquired taste.
Fastly: VCL conditions can match client.ip and set a header that your bot mitigation logic respects. Honestly, Fastly's VCL is one of the few CDN configs I actually enjoy writing.
AWS CloudFront with WAF: Create an IP set with probe IPs and add an allow rule that references it, positioned before your bot control rules. Rule ordering in AWS WAF is easy to mess up — ask me how I know. For teams using JustAnalytics with Cloudflare Workers at the edge, similar allowlisting logic applies.
The principle is identical across all CDNs: identify traffic from your own monitoring and exempt it from bot challenges. The UI varies, but the logic doesn't.
If you're running uptime checks against a Shopify headless store, you might hit similar issues with Shopify's built-in bot protection. Same solution applies — allowlist your probe IPs at the edge.
Common Errors and How to Fix Them
"I allowlisted the IPs but I'm still getting challenges"
Three possibilities. First, you might have allowlisted the wrong IPs — probe IP ranges change. Check your provider's current list. Second, the rule might not be applying to this zone — verify it's scoped correctly. Third, you might have conflicting rules. A "Challenge all" rule with higher priority than your allowlist overrides it.
"The monitor passes but shows wrong response time"
If Cloudflare serves the response from cache or a different edge than usual, latency measurements will vary. This isn't a challenge issue — it's normal CDN behavior. Check whether the response contains your actual content, not just whether it returns 200.
"Works for some probes but not others"
Your allowlist is incomplete. Your monitoring service might use different IP ranges for different regions. US East probes work because you allowlisted those IPs. Asia probes fail because you didn't add the Asia range. Get the complete list.
"Got blocked again after Cloudflare updated their bot rules"
Cloudflare's managed rulesets update automatically. A new rule might have introduced a check that catches your probes despite the IP allowlist. Check your WAF events log (Security → Events) to see which rule fired, then create a specific skip rule for it. This happens more often than you'd expect. Cloudflare ships updates weekly, sometimes daily.
Next Steps
Once your probes are allowlisted and body validation is configured:
-
Monitor the monitors. Check your WAF events log periodically for blocked probe requests. Catching a new block early beats another 3am alert.
-
Document your allowlist. Note which IPs are allowlisted and why. Your future self (or your replacement) will thank you.
-
Subscribe to your monitoring provider's IP change notifications. Most providers announce when they add new probe ranges. Update your allowlist proactively.
-
Consider multi-probe quorum. Even with perfect allowlisting, one probe in one region might hit edge cases. Multi-region monitoring with quorum voting — 2 of 3 probes must fail before alerting — adds another layer of false-positive protection. JustAnalytics runs 2-of-3 quorum by default. It's the difference between getting paged for a real outage versus getting paged because a single Cloudflare edge node hiccuped. Learn more in our guide to routing observability alerts to Slack, Teams, and PagerDuty.
For teams consolidating their monitoring stack, your uptime checks will live alongside error tracking, APM, and session replay in the same dashboard. When downtime correlates with a spike in JavaScript errors, you'll see both in one view. We've detailed this correlation workflow in our error and funnel drop-off guide.
If you're also monitoring third-party dependencies — Stripe, AWS services, external APIs — see our third-party outage detection guide for patterns that work alongside your primary uptime checks.
Frequently Asked Questions
Why does Cloudflare block my uptime monitor but not real browsers?
Cloudflare's bot detection looks at multiple signals: TLS fingerprint, JavaScript execution capability, request headers, and IP reputation. Real browsers pass JavaScript challenges and have "normal" TLS fingerprints. HTTP-only probes from known datacenter IPs fail both tests. Cloudflare sees an automated request from AWS or GCP, assumes it's a bot, and serves a challenge page instead of your actual site. The probe sees a 403 or a challenge HTML page and reports your site as down.
Will allowlisting probe IPs weaken my Cloudflare protection?
Slightly, but the risk is minimal if you do it right. Allowlisted IPs bypass bot challenges, not your entire WAF ruleset. SQL injection, XSS, and other attack signatures are still blocked. The exposure is that an attacker who spoofs a probe IP could bypass the bot challenge — but they'd need to know your exact probe IPs and would still hit all other WAF rules. Most uptime providers publish their IP ranges; the security tradeoff is accepted practice.
Should I use IP allowlisting or User-Agent allowlisting for my probes?
IP allowlisting is more secure and reliable. User-Agent strings are trivially spoofed — anyone can set "Pingdom/1.0" as their User-Agent. IPs are harder to forge (though not impossible with certain network attacks). Use IP allowlisting as the primary method. If your uptime provider rotates IPs frequently or doesn't publish them, User-Agent allowlisting is a fallback, but accept the reduced security posture.
How do I verify my uptime monitor is actually checking my site and not a Cloudflare challenge page?
Add response body validation to your monitor. Configure it to check for a string that only appears on your real page — your company name, a footer element, a deliberately placed health check string. If the probe receives a Cloudflare challenge page, that string won't be present and the check fails as expected. This catches the case where Cloudflare returns a 200 status with challenge HTML instead of your actual content.
Try JustAnalytics
All-in-one observability in one under-5KB script: cookieless analytics + error tracking + APM + session replay + uptime + structured logs. Replaces GA4 + Sentry + Datadog + Pingdom + LogRocket. Free tier (100K events/mo), Pro $49/month ($39 annual).
Author at JustAnalytics.