After Experiencing a Spike in Access from AI, I Tried Countermeasures That Avoid Blocking AI as Much as Possible, Such as Adjusting robots.txt

After Experiencing a Spike in Access from AI, I Tried Countermeasures That Avoid Blocking AI as Much as Possible, Such as Adjusting robots.txt

Anthropic's ClaudeBot caused a traffic spike of 50,000 requests per hour, 1,500 per minute. Here is how we revised robots.txt and AWS WAF settings in response, avoiding blocking AI crawlers as much as possible.
2025.02.24

This article was published more than one year ago. Please be aware that the information may be outdated.

This page has been translated by machine translation. View original

A spike in access classified under the AI category occurred in the AWS WAF Bot Control rules.
Requests to dynamically generated article pages were recorded at 50,000 per hour, and 1,500 per minute at peak.

This post introduces our investigation into the cause of a volume of requests comparable to the total number of articles published on our site (over 50,000), and the countermeasures we implemented.

Checking CloudWatch Metrics

To identify the cause, we analyzed the AWS WAF metrics.

Surge in bot:category AI

The number of requests in the AI category rose markedly, reaching 50,000 per hour.

No significant fluctuations were observed in other categories (search_engine: Google, Bing, etc.; social_media: X, Facebook, etc.).

WAF label AI 3 months

  • LabelNamespace="awswaf:managed:aws:bot-control:bot:category"
  • LabelName="ai",search_engine, social_media

bot:name claudebot

During the request surge, the "AI" category and the bot:name "ClaudeBot" matched.
From this, we concluded that requests from Anthropic had surged.

WAF_ai_claudebot

  • LabelNamespace="awswaf:managed:aws:bot-control:bot:name"
  • LabelName="claudebot"

Access Log Analysis

For more detailed analysis and to consider countermeasures, we analyzed the CloudFront access logs (standard access logs v2) stored in CloudWatch Logs using Logs Insights.

Aggregation by IP and UserAgent

From the access logs during the request surge period, we determined the IP addresses that had the ClaudeBot UserAgent.

fields @timestamp, @message
| parse @message /\"time-taken\":\"(?<timetaken>[^\"]+)\"/ 
| parse @message /\"c-ip\":\"(?<clientip>[^\"]+)\"/ 
| parse @message /\"cs\(User-Agent\)\":\"(?<useragent>[^\"]+)\"/ 
| parse @message /\"x-edge-response-result-type\":\"(?<edge_response_result_type>[^\"]+)\"/ 
| filter tolower(useragent)  like /claudebot/
| stats count() as request_count, 
        sum(timetaken) as total_time, 
        avg(timetaken) as avg_time 
  by clientip,useragent
| sort request_count desc
| limit 10000

Aggregation by IP and UA

  • The number of recorded IPs was 1,888
  • Each IP address generated roughly 100 to 200 requests.

Number of Concurrent Access IPs

For the ClaudeBot logs, we checked the number of unique IP addresses per second.

fields @timestamp, @message
| parse @message /\"time-taken\":\"(?<timetaken>[^\"]+)\"/ 
| parse @message /\"c-ip\":\"(?<clientip>[^\"]+)\"/ 
| parse @message /\"cs\(User-Agent\)\":\"(?<useragent>[^\"]+)\"/ 
| filter tolower(useragent) like /claudebot/
| stats count(*) as total_requests,
        count_distinct(clientip) as unique_ips
  by bin(1s)
| sort by unique_ips desc

Number of unique IPs

  • Up to 32 unique IP addresses accessed simultaneously, suggesting that requests may have been made with a concurrency of around 30.

Aggregation by URL

We attempted to check the requested URIs.

fields @timestamp, @message
| parse @message /\"time-taken\":\"(?<timetaken>[^\"]+)\"/ 
| parse @message /\"cs\(User-Agent\)\":\"(?<useragent>[^\"]+)\"/ 
| parse @message /\"cs-uri-stem\":\"(?<uri>[^\"]+)\"/ 
| parse @message /\"sc-status\":\"(?<status>[^\"]+)\"/ 
| filter tolower(useragent) like /claudebot/
| stats count() as request_count, 
        sum(timetaken) as total_time, 
        avg(timetaken) as avg_time 
  by uri,useragent, status
| sort total_time desc

Aggregation by URL

  • 25,000 requests to legitimate article pages were confirmed.

Aggregation by x_host_header

Because multiple accesses to the same article were observed, we attempted to aggregate by the requested host (host header).

fields @timestamp, @message
| parse @message /\"time-taken\":\"(?<timetaken>[^\"]+)\"/ 
| parse @message /\"cs\(User-Agent\)\":\"(?<useragent>[^\"]+)\"/ 
| parse @message /\"x-host-header\":\"(?<x_host_header>[^\"]+)\"/ 
| parse @message /\"sc-status\":\"(?<status>[^\"]+)\"/ 
| filter tolower(useragent) like /claudebot/
| stats count() as request_count, 
        sum(timetaken) as total_time, 
        avg(timetaken) as avg_time 
  by x_host_header,useragent, status
| sort total_time desc

Aggregation by x_host_header

Requests using a hostname different from the hostname of the public URL were confirmed.

Individual Requests

We determined the IP addresses whose UserAgent contained "claudebot" and checked the content of their requests.

fields @timestamp, @message
| parse @message /\"time-taken\":\"(?<timetaken>[^\"]+)\"/ 
| parse @message /\"c-ip\":\"(?<clientip>[^\"]+)\"/ 
| parse @message /\"cs\(User-Agent\)\":\"(?<useragent>[^\"]+)\"/ 
| filter tolower(useragent)  like /claudebot/
| filter clientip  like /172.71.##.##/
| limit 100

Individual request log

  • The number of requests per minute from a single IP address was about 10

Countermeasures

robots.txt

Following Anthropic's guide, we added a setting to robots.txt requesting a 1-second crawl delay (Crawl-delay).
We attempted to describe a rule to curb excessive crawling.

$ curl -s https://dev.classmethod.jp/robots.txt | grep 'Crawl-delay:'
Crawl-delay: 1

We support the non-standard Crawl-delay extension in robots.txt to limit crawling activity. For example:

User-agent: ClaudeBot
Crawl-delay: 1

Does Anthropic crawl data from the web, and how can site owners block the crawler?

Alternative Domain

About half of this spike in access was directed at an alternative URL that is not the legitimate public FQDN. This alternative URL had been used for operation verification by stakeholders before the service launched, and for external monitoring of performance after launch.

Previously, we had set "x-robots-tag: noindex".

< HTTP/2 200 
< date: Fri, 21 Feb 2025 **:**:** GMT
< content-type: text/plain
(...)
< x-robots-tag: noindex

Since this had no effect on AI crawlers, we adjusted the Cloudflare rules and changed the setting to a 301 redirect to the legitimate site.

< HTTP/2 301 
< date: Fri, 21 Feb 2025 **:**:** GMT
< content-type: text/html
(...)
< location: https://dev.classmethod.jp/

After the number of redirects subsides, we plan to retire the FQDN in question.

Block

Using AWS WAF rate-based rules and custom keys, it is possible to block when more than a certain number of requests occur within a specified period.

Our current policy is to avoid blocking as much as possible, but in case the spike in access continues without any effect from robots.txt and the like, we have prepared the following rule so that it can be added to the AWS WAF ACLs.

  • Rate limiting using the bot-control determination label (Block is triggered at 100 or more per minute)
{
    "Name": "rate-limit-claudebot",
    "Priority": 250,
    "Statement": {
        "AndStatement": {
            "Statements": [
                {
                    "LabelMatchStatement": {
                        "Scope": "LABEL",
                        "Key": "awswaf:managed:aws:bot-control:bot:name:claudebot"
                    }
                },
                {
                    "RateBasedStatement": {
                        "Limit": 100,
                        "AggregateKeyType": "CUSTOM_KEYS",
                        "CustomKeys": [
                            {
                                "Type": "LABEL_NAMESPACE",
                                "Key": "awswaf:managed:aws:bot-control:bot:name"
                            }
                        ],
                        "TimeWindow": 60
                    }
                }
            ]
        }
    },
    "Action": {
        "Block": {}
    },
    "VisibilityConfig": {
        "SampledRequestsEnabled": true,
        "CloudWatchMetricsEnabled": true,
        "MetricName": "RateLimitClaudeBotRule"
    }
}

Results (added on 2/27)

After updating robots.txt, the number of requests from ClaudeBot decreased to about 20 to 50 per hour.

claudebot_access count

On social media, a case was introduced in which iFixit's site received requests on the scale of one million from ClaudeBot and dealt with it using robots.txt.

https://x.com/tmiyatake1/status/1816660039442293048

Proper robots.txt settings are considered effective for controlling ClaudeBot's crawling.

Summary

Although it is easy to configure AWS WAF to exclude AI agents, doing so could be detrimental to both readers and authors, for example by removing our site's article content from AI-powered search or preventing the latest updates from being reflected, so our policy is to avoid blocking measures as much as possible.

This time we tried controlling crawl frequency with robots.txt, and we have also started preparing "llms.txt", clearly stating instructions for LLMs (large language models) as a measure to guide AI crawlers.

https://dev.classmethod.jp/articles/llms-txt-for-ai-crawlers/

This spike in access also revealed points to improve on the infrastructure side. As future measures, we plan to strengthen the robustness of the entire system through a combined approach, including optimizing the backend systems, using CloudFront's VPC support to prevent direct access to the origin, and advanced AWS WAF configuration.


Claudeならクラスメソッドにお任せください

クラスメソッドは、Anthropic社とリセラー契約を締結しています。各種製品ガイドから、業種別の活用法、フェーズごとのお悩み解決などサービス支援ページにまとめております。まずはご覧いただき、お気軽にご相談ください。

サービス詳細を見る

Share this article

AWSのお困り事はクラスメソッドへ