User-Agent Rules
User-Agent Rules allow you to block or challenge requests based on the User-Agent header. This is useful for blocking known bad bots, scrapers, or outdated clients.
Overview
Access the UA Rules API through cf.Zones.UaRules:
public class BotBlockingService(ICloudflareApiClient cf)
{
public async Task BlockBadBotAsync(string zoneId, string userAgent)
{
await cf.Zones.UaRules.CreateAsync(zoneId,
new CreateUaRuleRequest(
Mode: UaRuleMode.Block,
Configuration: new UaRuleConfiguration("ua", userAgent),
Description: "Block known bad bot"
));
}
}
Creating UA Rules
Block a User-Agent
var rule = await cf.Zones.UaRules.CreateAsync(zoneId,
new CreateUaRuleRequest(
Mode: UaRuleMode.Block,
Configuration: new UaRuleConfiguration("ua", "BadBot/1.0"),
Description: "Block BadBot scraper"
));
Challenge Suspicious User-Agents
var rule = await cf.Zones.UaRules.CreateAsync(zoneId,
new CreateUaRuleRequest(
Mode: UaRuleMode.Challenge,
Configuration: new UaRuleConfiguration("ua", "curl"),
Description: "Challenge curl requests"
));
Block with Pattern Matching
User-Agent matching supports partial matches:
// Blocks any User-Agent containing "scraper"
var rule = await cf.Zones.UaRules.CreateAsync(zoneId,
new CreateUaRuleRequest(
Mode: UaRuleMode.Block,
Configuration: new UaRuleConfiguration("ua", "scraper"),
Description: "Block scrapers"
));
Listing UA Rules
List All Rules
await foreach (var rule in cf.Zones.UaRules.ListAllAsync(zoneId))
{
Console.WriteLine($"{rule.Id}: {rule.Configuration.Value} -> {rule.Mode}");
}
List with Pagination
var page = await cf.Zones.UaRules.ListAsync(zoneId,
new ListUaRulesFilters { PerPage = 50 });
foreach (var rule in page.Items)
{
Console.WriteLine($"{rule.Description}: {rule.Mode}");
}
Getting a Specific Rule
var rule = await cf.Zones.UaRules.GetAsync(zoneId, ruleId);
Console.WriteLine($"User-Agent: {rule.Configuration.Value}");
Console.WriteLine($"Mode: {rule.Mode}");
Console.WriteLine($"Paused: {rule.Paused}");
Updating UA Rules
var updated = await cf.Zones.UaRules.UpdateAsync(zoneId, ruleId,
new UpdateUaRuleRequest(
Mode: UaRuleMode.ManagedChallenge,
Description: "Updated to managed challenge"
));
Pause a Rule
var updated = await cf.Zones.UaRules.UpdateAsync(zoneId, ruleId,
new UpdateUaRuleRequest(Paused: true));
Deleting UA Rules
await cf.Zones.UaRules.DeleteAsync(zoneId, ruleId);
Models Reference
UaRule
| Property | Type | Description |
|---|---|---|
Id |
string |
Unique identifier |
Mode |
UaRuleMode |
Action to take |
Configuration |
UaRuleConfiguration |
User-Agent pattern |
Paused |
bool |
Whether the rule is paused |
Description |
string? |
Optional description |
UaRuleMode (Extensible Enum)
The action to take when a User-Agent rule matches. This is an extensible enum that supports custom values for forward compatibility.
| Known Value | Description |
|---|---|
Block |
Block the request |
Challenge |
Present CAPTCHA challenge |
JsChallenge |
Present JavaScript challenge |
ManagedChallenge |
Cloudflare-managed challenge |
// Using known values
UaRuleMode.Block
UaRuleMode.Challenge
UaRuleMode.JsChallenge
UaRuleMode.ManagedChallenge
// Future-proof: accepts unknown values from API
UaRuleMode customMode = "new-mode";
UaRuleConfiguration
| Property | Type | Description |
|---|---|---|
Target |
string |
Always "ua" |
Value |
string |
User-Agent pattern to match |
User-Agent Matching
- Matching is case-insensitive
- Matching is substring-based (pattern can appear anywhere in User-Agent)
- Example: Pattern
"bot"matches"Googlebot","bingbot","MyBot/1.0"
Common Patterns
Block Known Bad Bots
var badBots = new[]
{
"AhrefsBot",
"MJ12bot",
"DotBot",
"SemrushBot",
"BLEXBot"
};
foreach (var bot in badBots)
{
await cf.Zones.UaRules.CreateAsync(zoneId,
new CreateUaRuleRequest(
Mode: UaRuleMode.Block,
Configuration: new UaRuleConfiguration("ua", bot),
Description: $"Block {bot}"
));
}
Challenge Empty User-Agents
await cf.Zones.UaRules.CreateAsync(zoneId,
new CreateUaRuleRequest(
Mode: UaRuleMode.Challenge,
Configuration: new UaRuleConfiguration("ua", ""),
Description: "Challenge empty User-Agent"
));
Audit Existing Rules
public async Task<List<string>> GetBlockedUserAgentsAsync(string zoneId)
{
var blocked = new List<string>();
await foreach (var rule in cf.Zones.UaRules.ListAllAsync(zoneId))
{
if (rule.Mode == UaRuleMode.Block && !rule.Paused)
{
blocked.Add(rule.Configuration.Value);
}
}
return blocked;
}
Required Permissions
| Permission | Scope | Level |
|---|---|---|
| Firewall Services | Zone | Write |
Best Practices
- Be specific with User-Agent patterns to avoid blocking legitimate traffic
- Use Challenge instead of Block for uncertain cases
- Monitor traffic before and after adding rules
- Document rules with clear descriptions
- Review periodically - bot User-Agents change over time