Block specific browsers/bots in nginx
Blocking Unwanted Bots and User-Agents in Nginx
Nginx allows administrators to block specific User-Agent strings to prevent unwanted bots, crawlers, scrapers, or malicious clients from accessing a site. This is useful for reducing server load, conserving bandwidth, and protecting content from aggressive crawling—such as by AI training bots that may not respect robots.txt.[1][2]
Common targets include malicious scanners, spam bots, and increasingly AI-related crawlers (e.g., those collecting data for large language models).[3]
Identifying Unwanted Traffic
Use log analysis tools like GoAccess to inspect access logs for high-volume traffic by User-Agent or ASN. Many AI crawlers announce themselves clearly (e.g., "meta-externalagent/1.1", "GPTBot", "ClaudeBot").[4]
Basic Blocking with if Directive
The simplest method is a conditional check inside the server {} block:
if ($http_user_agent ~* "badbot|undesired-agent") {
return 403; # or 404, 444, etc.
}
This performs a case-insensitive match (~*) and returns the specified status code.[5]
Example: Blocking Meta's AI Crawler
Many administrators report heavy traffic from Meta's crawler (User-Agent: "meta-externalagent/1.1"), used for AI data collection.[6]
To block it:
if ($http_user_agent ~* "meta-externalagent") {
return 402; # "Payment Required" - a humorous nod to content usage in AI training
}
The 402 Payment Required code is rarely used but valid; it implies the crawler should "pay" for data, popular among publishers concerned about AI scraping.[7]
After changes, test configuration and reload:
nginx -t nginx -s reload
Advanced: Using map for Multiple User-Agents
For cleaner configuration and better performance with many agents, use a map (outside server {}, in http {}):
map $http_user_agent $bad_bot {
default 0;
~*meta-externalagent 1;
~*GPTBot 1;
~*ClaudeBot 1;
~*Bytespider 1;
# Add more as needed
}
Then in server {}:
if ($bad_bot = 1) {
return 402;
}
This avoids multiple if statements and is recommended for lists of bad bots.[8]
Alternatives: Rate Limiting or Connection Closing
Instead of full blocking:
- Rate limit specific agents to reduce impact.
- Use return 444; (Nginx-specific) to close the connection without response, saving resources.
Example rate limiting:
map $http_user_agent $bot_limit {
~*meta-externalagent 1;
default 0;
}
limit_req_zone $bot_limit zone=bot_zone:10m rate=5r/m;
server {
...
limit_req zone=bot_zone burst=10 nodelay;
}
Complementary: robots.txt
Many crawlers respect robots.txt. For Meta's agent:
User-agent: meta-externalagent Disallow: /
However, server-level blocking is more reliable for non-compliant bots.[9]
External links
- Nginx if directive documentation
- GoAccess - Log Analyzer for Identifying Bots
- Dark Visitors - List of AI Bots and User-Agents
- Nginx Ultimate Bad Bot Blocker
- ↑ https://www.xmodulo.com/block-specific-user-agents-nginx-web-server.html How to block specific user agents on Nginx web server, 2013-10-11
- ↑ https://www.cyberciti.biz/faq/unix-linux-appleosx-bsd-nginx-block-user-agent/ HowTo: Nginx Block User Agent, 2012-06-27
- ↑ https://darkvisitors.com/ Dark Visitors - A list of known AI agents and bots
- ↑ https://goaccess.io/ GoAccess - Visual Web Log Analyzer
- ↑ https://stackoverflow.com/questions/22144092/how-to-block-a-specific-user-agent-in-nginx-config How to block a specific user agent in nginx config
- ↑ https://developers.facebook.com/docs/sharing/webmasters/web-crawlers/ Meta Web Crawlers, Meta Platforms, Inc.
- ↑ https://blog.cloudflare.com/introducing-ai-crawl-control/ Introducing AI Crawl Control, Cloudflare, September 3, 2025
- ↑ https://www.reddit.com/r/nginx/comments/1dilzny/block_user_agents_without_if_constructs/ Block user agents without if constructs, Reddit, June 18, 2024
- ↑ https://developers.facebook.com/docs/sharing/webmasters/web-crawlers/ Meta Web Crawlers
