Monitor a site behind Cloudflare or a WAF
A blocked check tells you the monitor could not reach the endpoint. It does not, by itself, tell you the application is down. Find the blocking rule, then make a small exception for a dedicated health route.
Start with the failed response
Open a failed check and inspect its status, response body and headers. Match its time and Cloudflare Ray ID, when present, to Security Events in your Cloudflare dashboard. A 403 alone does not identify Turnstile, a firewall rule or a geographic restriction.
- 1020: a Cloudflare firewall rule denied access.
- 1000 or 1016: investigate prohibited-IP or origin-DNS configuration.
- 522 or 523: investigate reachability between Cloudflare and the origin.
cf-mitigated: challenge: the request received a bot challenge. An HTTP probe does not run a browser to solve it.
Use a dedicated monitoring header
UptimeSignal does not offer fixed source IPs or a US-only checking guarantee. Checks run on Cloudflare Workers, and their source can vary. Do not allow all Cloudflare IP space just to admit one monitor.
- Create a minimal route such as
https://api.example.com/healththat returns the expected status without exposing diagnostics or accepting state changes. - Generate a random token for this route only. For example, run
openssl rand -hex 32locally. Use the generated value in both configurations below. - Edit the monitor, open its custom headers, and add
X-UptimeSignal-Tokenwith that value. Keep the method as GET or HEAD for this example.
Use a dedicated, revocable value. Never reuse a password, general API key or account credential. Custom header values currently remain visible in monitor configuration and owner API/edit responses; they are not a masked credential vault.
Scope the Cloudflare exception
In your zone's Security rules, create a custom rule. Replace the hostname, path and placeholder below. The header name in the expression is lowercase.
(http.host eq "api.example.com"
and http.request.uri.path eq "/health"
and http.request.method in {"GET" "HEAD"}
and any(http.request.headers["x-uptimesignal-token"][*]
eq "REPLACE_WITH_RANDOM_TOKEN"))
Select Skip and only the security features responsible for the block. If a later custom rule is blocking the request, select the remaining-custom-rules option and place this exception before that rule. Managed Rules, rate limiting and Super Bot Fight Mode have separate skip choices. Leave logging enabled while verifying the match.
This is a WAF exception, not application authentication. Your origin still decides whether the request is authorized. Keep the exception limited to this hostname, route and method; rotate the token if it is exposed.
Know what Skip cannot bypass
Cloudflare's free Bot Fight Mode cannot be skipped by a custom rule. Super Bot Fight Mode can. If the free feature is responsible, this rule alone will not solve it. Review that feature's configuration or use a dedicated health endpoint with suitable protection; do not disable site-wide controls without understanding their effect.
A rule that already blocked the request cannot be undone by a later exception. Other protections and your origin can also reject a request. Use the event details to identify the actual layer instead of widening the exception until the check passes.
Verify the narrow exception
- Confirm the next monitor check reaches the health route and returns the expected status.
- Confirm the matching Security Event belongs to this rule and route.
- Check that requests with a missing or incorrect token do not receive this exception.
- Check that the token grants no exception on another route or method.
Request reference
A monitor uses the method selected in its configuration, with GET as the default. The default User-Agent is UptimeSignal/1.0 (https://uptimesignal.io). Custom headers can override it. The checker does not explicitly set an Accept header; do not use that as an identity guarantee. POST, PUT and PATCH can carry the configured body and Content-Type.
Checks follow HTTP redirects. Put the health route directly on its final hostname and avoid redirecting requests that carry a token to a different host.