Tutorial · cloudflare · Published 2026-08-15 · 3 min read
Cloudflare WAF custom rules
Write Cloudflare WAF custom rules with expressions and actions. Free/Pro/Business rule quotas, regex support and block vs challenge.
What a WAF custom rule does
A WAF custom rule runs in the http_request_firewall_custom phase and decides what to do with a request before it reaches the origin. You write a match expression, choose an action, and Cloudflare applies it at the edge so the attacker's request never hits your server. This is the fastest way to implement a policy like "block admin requests from outside my office" or "challenge traffic to the login form."
The custom rules layer sits alongside the managed rulesets. Managed rules cover known attack signatures automatically; custom rules are yours to write for policies the vendor rules cannot express.
Write a rule
- In the dashboard, open Security > WAF > Custom rules and select Create rule.
- Give the rule a name and an expression. A country or path match is the most common start:
(http.request.uri.path starts_with "/wp-admin/" and
not (ip.src.country in {"US" "GB"}))
- Pick an action. A country-restricted admin block usually uses Block.
- Save. The rule evaluates in order with your other custom rules, so a later rule cannot undo an earlier block.
Expressions combine the request fields with and, or, and not. Field names mirror the request, so ip.src.country, http.request.uri.path, and http.user_agent are all available. Keep each rule to one clear policy; several simple rules are easier to debug than one long expression.
Actions compared
| Action | Result |
|---|---|
| Block | Refuses the request, usually with a Cloudflare challenge or 403-style rejection |
| Challenge | Sends a managed challenge that a human can pass and a bot typically cannot |
| JS Challenge | Non-interactive JavaScript challenge, cheaper for real users |
| Managed Challenge | Lets Cloudflare pick the least intrusive challenge |
| Log | Records the match and does nothing else, useful for tuning before you enforce |
| Skip | Stops later rules from running for matched requests |
Log records a match without blocking, which is the safe way to validate a new expression against live traffic before enforcing it. It is only available on the Enterprise plan; on Free, Pro, and Business every custom rule action is a real enforcement unless you test it on a staging zone.
Plan limits
Custom rules are available on every plan, with different quotas:
| Plan | Rules | Regex | Log action |
|---|---|---|---|
| Free | 5 | No | No |
| Pro | 20 | No | No |
| Business | 100 | Yes | No |
| Enterprise | 1,000 | Yes | Yes |
The quota counts all rules in the custom phase together, active or not. If you need regular expressions on legacy code or a Log-only staging action, that is what moves you up a tier; otherwise the Free and Pro limits are enough for a focused set of hand-written policies. When you near the cap, prefer a rate limit rule for volume-based protection rather than spending another custom rule on it, and keep the security level as the baseline challenge threshold.