Block specific browsers/bots in nginx

From OISecWiki

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]

  1. ↑ 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
  2. ↑ https://www.cyberciti.biz/faq/unix-linux-appleosx-bsd-nginx-block-user-agent/ HowTo: Nginx Block User Agent, 2012-06-27
  3. ↑ https://darkvisitors.com/ Dark Visitors - A list of known AI agents and bots
  4. ↑ https://goaccess.io/ GoAccess - Visual Web Log Analyzer
  5. ↑ 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
  6. ↑ https://developers.facebook.com/docs/sharing/webmasters/web-crawlers/ Meta Web Crawlers, Meta Platforms, Inc.
  7. ↑ https://blog.cloudflare.com/introducing-ai-crawl-control/ Introducing AI Crawl Control, Cloudflare, September 3, 2025
  8. ↑ https://www.reddit.com/r/nginx/comments/1dilzny/block_user_agents_without_if_constructs/ Block user agents without if constructs, Reddit, June 18, 2024
  9. ↑ https://developers.facebook.com/docs/sharing/webmasters/web-crawlers/ Meta Web Crawlers