Sie wollen wissen, welche Bots Ihre Website crawlen: welche KI-Crawler, wie oft und auf welchen Seiten sie einen 404 bekommen. Ein Tool bietet an, es Ihnen zu zeigen, und der Einrichtungsdialog verlangt ein Cloudflare-API-Token mit Workers Scripts Edit. Mit diesem Token legt es einen eigenen Worker an und richtet eine Route ein, die ihn bei jeder Anfrage an Ihre Website ausführt.
So arbeitet Ahrefs Bot Analytics, und genauso Known Agents (früher Dark Visitors), Profound und Scrunch. Der Worker ist kurz und tut, was er verspricht. Die Route davor ist der Teil, der verändert, wie Ihre Website läuft, und keiner dieser Einrichtungsdialoge nennt die Kosten.
Dieser Artikel zeigt, was diese Route im Free-Tarif von Cloudflare bewirkt, was Cloudflare Ihnen ohne sie schon liefert und wie Sie Bots selbst in einem Worker protokollieren, den Sie bereits haben. Jedes Limit unten ist am 30. September 2026 an der Dokumentation von Cloudflare geprüft, und jede Traffic-Zahl stammt von dieser Website, 301.sh, die im Free-Tarif läuft.
Was der Worker tut
Ahrefs verlangt drei Berechtigungen: Account Workers Scripts Edit, Zone Workers Routes Edit
und Zone Read. Der Einrichtungsdialog nennt drei Schritte: „Find the zone matching“ Ihre
Website, „Deploy the Ahrefs analytics worker“, „Set up a route to run on all requests“. Dazu
der Satz: „Your token is used once and not stored.“ Die manuelle Einrichtung in
der Dokumentation nutzt
das Routenmuster *yourwebsite.com/*.
Der Worker reicht jede Anfrage mit fetch(event.request) unverändert durch. Wenn die
Antwort draußen ist, schickt er einen Bericht in event.waitUntil, die Seite wartet also
nicht darauf. Der Bericht enthält die vollständige URL samt Query-String, die IP des
Besuchers aus cf-connecting-ip, den User-Agent, den Referer, die Methode, den Status und
den Content-Type. Außerdem drei Header aus Web Bot Auth: signature, signature-input und
signature-agent. Mit ihnen
weist ein signierter KI-Agent nach, wer er ist, und sie sind
der interessanteste Teil der Nutzlast.
Known Agents und Profound veröffentlichen Worker derselben Bauart. Der von Profound
überspringt /checkout, /cart, /admin und /api, bevor er berichtet
(Dokumentation). Der von
Ahrefs berichtet alles.
Was die Route kostet
Jede Anfrage wird zu einem Worker-Aufruf. Der Workers-Free-Tarif erlaubt 100.000
Anfragen am Tag, zurückgesetzt um Mitternacht UTC
(Limits). Eine Route auf
*example.com/* trifft die Seite und jedes Bild, jedes Stylesheet, jedes Skript und jede
Schrift, die die Seite lädt. Eine Seite mit zwanzig Dateien verbraucht bei einem Besuch
einundzwanzig Anfragen dieses Kontingents. Der Bericht des Workers ist ein Subrequest, und
Subrequests berechnet Cloudflare nicht; der Aufruf selbst zählt.
Statische Dateien sind nicht mehr gratis. Läuft Ihre Website auf Workers Static Assets, schreibt Cloudflare: „Requests to static assets are free and unlimited“, und berechnet nur Anfragen, die einen Worker aufrufen (Abrechnung). Ein Routen-Worker davor lässt jede einzelne davon einen Worker aufrufen.
So sieht der Unterschied auf 301.sh aus. In den sieben Tagen bis zum 30. September hat die
Zone rund 19.200 Anfragen ausgeliefert, und unser eigener Worker lief 2.421 Mal, weil er nur
auf Seiten-URLs läuft und die statischen Dateien ohne ihn hinausgehen. Eine Route auf /*
hätte bei allen 19.200 einen Worker ausgeführt, achtmal so oft. Diese Website bleibt so oder
so weit unter 100.000 am Tag. Eine Website mit 10.000 Seitenaufrufen am Tag und zwanzig
Dateien pro Seite nicht.
Die Route läuft vor Ihrem eigenen Worker. Die Dokumentation von Cloudflare zu Custom
Domains: „Any Workers running on routes before your Custom Domain can optionally call the
Worker registered on your Custom Domain by issuing fetch(request)“
(Custom Domains).
Auf einer Website, die schon einen eigenen Worker hat, ist der Worker des Tools also der
erste Code, der jede Anfrage sieht. Wie das Paar aufs Kontingent angerechnet wird, sagt die
Dokumentation nicht.
Wissen Sie, was bei 100.000 passiert. Nach dem Tageslimit läuft eine Route entweder
offen weiter, „Bypasses the Worker. Requests behave as if no Worker is configured“, oder sie
schließt, „Returns a Cloudflare 1027 error page“. Der Modus ist ein Schalter an der Route.
Welchen eine neue Route bekommt, sagt die Dokumentation nicht, und die Routenanfrage in der
manuellen Einrichtung von Ahrefs setzt ihn nicht. Öffnen Sie Workers & Pages, suchen Sie die
Route, die das Tool angelegt hat, und prüfen Sie ihn. Eine Route, die schließt, macht aus
einer Traffic-Spitze eine Fehlerseite für die ganze Website.
Die spezifischere Route gewinnt. „The most specific route pattern wins“
(Routen). Haben
Sie schon einen Worker auf www.example.com/* oder example.com/api/*, gehen diese
Anfragen an Ihren Worker, und das Analytics-Tool sieht sie nie. Nichts sagt Ihnen, dass sie
fehlen.
Die Daten jedes Besuchers gehen hinaus. Die Route kann einen Bot nicht von einem Menschen unterscheiden, bevor sie läuft, also geht der Bericht auch für Menschen hinaus: ihre IP, die Seite, die sie geöffnet haben, der Query-String mit allem, was Ihre Website hineinschreibt. Damit wird das Tool zum Auftragsverarbeiter personenbezogener Daten Ihrer Besucher, und Ihre Datenschutzerklärung muss das womöglich nennen.
Das Token kann mehr, als die Aufgabe braucht. Die Dokumentation von Ahrefs schlägt ein Token auf All accounts und All zones vor und nennt eine Einschränkung nur als Alternative. Workers Scripts Edit auf einem Konto erlaubt dem Inhaber, beliebige Worker hochzuladen. Legen Sie das Token für die eine Zone an, die das Tool braucht, und löschen Sie es, sobald der Worker läuft. „Not stored“ müssen Sie dann nicht mehr glauben.
Was das Aufheben des Kontingents kostet
Der Workers-Paid-Tarif kostet $5 im Monat pro Konto, mit 10 Millionen Anfragen inklusive, danach $0,30 pro weitere Million (Preise). Ein Tageslimit gibt es in Paid nicht, der Ausfallmodus spielt dann keine Rolle mehr. Für die meisten Websites ist die Kontingentfrage damit für $5 erledigt. An den übrigen Punkten oben ändert es nichts: statische Dateien werden weiter als Aufrufe berechnet, und die Daten gehen weiter hinaus.
Was Cloudflare Ihnen schon zeigt
Bevor Sie einen Worker hinzufügen, sehen Sie nach, was Cloudflare für die Zone schon aufzeichnet.
| Werkzeug | Tarif | Was es zeigt |
|---|---|---|
| GraphQL Analytics API | alle Tarife; in Free 31 Tage zurück, bis zu 30 Tage pro Abfrage | jeden Bot nach User-Agent und von Cloudflare geprüfter Kategorie, mit Pfad und Antwortstatus |
| AI Crawl Control | alle Tarife; Referral-Daten in bezahlten Tarifen | KI-Crawler nach Betreiber, die meistgecrawlten Pfade, Statuscodes der Antworten |
| Security Analytics | alle Tarife; in Free die letzten sieben Tage | einzelne Anfragen als Stichprobe, mit ihren Eigenschaften und Scores |
| Bot Analytics | Business und Enterprise | Bot-Scores und Traffic geprüfter Bots |
| Logpush | Enterprise | jede Anfrage, in Ihren eigenen Speicher |
AI Crawl Control ist die Antwort im Dashboard für KI-Crawler. Die API antwortet für jeden Bot, und sie ist die Zeile, die wir an unserer eigenen Zone geprüft haben.
Die API fragen
Auf 301.sh, einer Free-Zone, listet der settings-Knoten der GraphQL-API userAgent,
verifiedBotCategory, clientRequestPath und edgeResponseStatus unter den Feldern von
httpRequestsAdaptiveGroups. Das reicht für die Frage, welche geprüften Bots diese Woche
einen 404 bekommen haben:
query ($zone: String!, $since: Time!, $until: Time!) {
viewer {
zones(filter: { zoneTag: $zone }) {
httpRequestsAdaptiveGroups(
limit: 50
filter: {
datetime_geq: $since
datetime_lt: $until
verifiedBotCategory_neq: ""
edgeResponseStatus: 404
}
orderBy: [count_DESC]
) {
count
dimensions { verifiedBotCategory userAgent clientRequestPath }
}
}
}
}
Schicken Sie sie per POST an https://api.cloudflare.com/client/v4/graphql, mit einem Token,
das Zone Analytics Read hat, und mit Zonen-ID und Zeitraum in den Variablen. Ohne die Zeile
edgeResponseStatus sehen Sie den gesamten Traffic geprüfter Bots. Für die Bots, die
Cloudflare nicht geprüft hat, filtern Sie stattdessen auf verifiedBotCategory: "" und
userAgent_like: "%bot%".
Auf unserer Zone kamen in den sieben Tagen bis zum 30. September rund 1.400 von 19.200
Anfragen von geprüften Bots aus neun Kategorien. Vorn lagen die Crawler der Suchmaschinen,
dann KI-Crawler, SEO-Tools und Aggregatoren. Die 404-Abfrage fand zwei Dinge, die man
beheben oder wissen sollte. DuckDuckBot fragte dreizehnmal nach /favicon.ico; die Website
hatte nur /favicon.svg und hat seit dieser Abfrage beides. KI-Crawler fragten nach
Adressen wie /2018-gopherconuk-slides, die es auf dieser Website nie gab.
Die Abfrage nach ungeprüften Bots fand noch etwas anderes. Ein Client mit dem User-Agent
Claude-SearchBot/1.0 fragte 36 Mal nach /api/uploads/..%2F..%2F.env, einem Pfad, der aus
einem Upload-Ordner zu einer Datei mit Geheimnissen hinaufklettern will. Cloudflare hat ihn
nicht geprüft, und kein Suchmaschinen-Crawler braucht diesen Pfad. Ein Tool, das nur nach
User-Agent zählt, bucht diese 36 Anfragen auf Anthropic.
Die Werte der Kategorien sind die Namen aus dem Dashboard mit Leerzeichen, etwa
"AI Crawler" und "Search Engine Crawler". Ein Filter auf "AICrawler" liefert nichts und
keinen Fehler.
Was die API nicht liefert, ist eine Historie über 31 Tage hinaus und die Header von Web Bot Auth. Dafür brauchen Sie ein eigenes Protokoll.
Bots im Worker protokollieren, den Sie schon haben
Läuft auf Ihrer Website schon ein Worker für die Seiten, schreiben Sie das Protokoll dort
hinein. Die Anfrage ruft diesen Worker ohnehin auf, das Protokoll kostet also keinen
zusätzlichen Aufruf, und Sie entscheiden, was Ihr Konto verlässt. 301.sh ist so gebaut: Sein
Worker läuft zuerst nur auf Seiten-URLs, festgelegt mit run_worker_first in
wrangler.toml, und Bilder und Styles gehen ohne ihn als kostenlose statische Dateien
hinaus.
Workers Analytics Engine gibt es im Free-Tarif: 100.000 geschriebene Datenpunkte und 10.000 Leseabfragen am Tag (Preise). Der Workers-Paid-Tarif für $5 im Monat hebt das auf 10 Millionen Datenpunkte im Monat an. Binden Sie ein Dataset ein:
# wrangler.toml
[[analytics_engine_datasets]]
binding = "BOTS"
dataset = "bot_hits"
Dann zeichnen Sie Bots auf dem Rückweg auf:
const BOT = /bot|crawl|spider|slurp|GPTBot|ClaudeBot|PerplexityBot|Bytespider|CCBot|meta-externalagent/i;
export default {
async fetch(request, env, ctx) {
const response = await handle(request, env, ctx); // your existing logic
const ua = request.headers.get("user-agent") ?? "";
const verified = request.cf?.verifiedBotCategory ?? "";
if (verified || BOT.test(ua)) {
env.BOTS.writeDataPoint({
indexes: [verified || "unverified"],
blobs: [
ua.slice(0, 256),
new URL(request.url).pathname,
String(response.status),
request.headers.get("signature-agent") ?? "",
],
doubles: [1],
});
}
return response;
},
};
Drei Details zählen.
Geschrieben werden nur Bots. Anfragen von Menschen erreichen das Dataset nie, es steht also nichts Personenbezogenes darin, das Sie offenlegen müssten, und die 100.000 Datenpunkte am Tag gehen an den Traffic, den Sie untersuchen wollen.
verifiedBotCategory ist die Prüfung von Cloudflare, der User-Agent ist die Behauptung
des Bots. Jeder kann GPTBot in einen Header schreiben. Cloudflare füllt
request.cf.verifiedBotCategory nur für Bots, die es geprüft hat. Schreiben Sie beides und
vergleichen Sie.
Auf writeDataPoint wird nicht gewartet. Die Funktion kehrt sofort zurück, und die
Laufzeit speichert den Punkt im Hintergrund, genau wie beim
Zählen von Klicks auf eine Weiterleitung. Dort
steht auch die Leseseite: eine SQL-Abfrage, und SUM(_sample_interval) statt COUNT().
Welche Bots einen 404 bekommen:
SELECT index1 AS category, blob1 AS agent, blob2 AS path,
SUM(_sample_interval) AS hits
FROM bot_hits
WHERE blob3 = '404' AND timestamp >= NOW() - INTERVAL '7' DAY
GROUP BY category, agent, path
ORDER BY hits DESC
LIMIT 50
Hat Ihre Website heute keinen Worker, bringt einer, der nur dafür dazukommt, die
Kontingentfrage zurück. Eingrenzen können Sie ihn trotzdem: Eine Route auf die Seitenpfade
statt auf /* lässt Bilder und Styles in Ruhe.
Wo es hakt
Der reguläre Ausdruck entscheidet, was ein Bot ist. Ein Crawler, der den User-Agent eines Browsers schickt, landet nicht in Ihrem Dataset, außer Cloudflare hat ihn geprüft. Jedes Tool, das den User-Agent liest, hat dieselbe Grenze, die bezahlten eingeschlossen.
Analytics Engine hält Daten drei Monate. Für ein Jahr Historie exportieren Sie sie regelmäßig.
Die Zahlen der API sind Schätzungen. Cloudflare zieht bei hohem Volumen Stichproben und „returns an estimate derived from the sampled value“ (Sampling). Unsere Woche kam mit einem durchschnittlichen Stichprobenintervall von etwa 2,5 zurück. Gut für die Frage, welche Bots und welche Pfade; nicht für genaue Zahlen eines seltenen Ereignisses.
Einunddreißig Tage ist alles, was die API in Free vorhält. Speichern Sie ein Ergebnis pro Woche, wenn Sie einen Verlauf wollen.
Header von Web Bot Auth sind heute selten. signature-agent mitzuschreiben kostet
nichts, und die Spalte füllt sich, je mehr Agenten ihre Anfragen signieren. Eine leere Spalte
ist kein Beweis, dass keine Agenten kommen.
Wann sich 301.st lohnt
Für eine einzelne Website brauchen Sie uns nicht. Führen Sie die Abfrage oben einmal pro Woche aus, und wenn Sie eine längere Historie wollen, schreiben Sie das Protokoll in Ihren Worker.
301.st verwaltet Weiterleitungen und Traffic-Regeln über ein Portfolio von Domains. Auf den Domains, für die Sie Regeln anlegen, läuft ein Worker in Ihrem Cloudflare-Konto, es ist also derselbe Tausch wie oben beschrieben, eingegangen, um den Traffic zu lenken und nicht nur zu beobachten. Dieser Worker sortiert jede Anfrage in sieben Bot-Kategorien, von Suchmaschinen und KI-Crawlern bis zu Link-Vorschauen und Uptime-Monitoren, anhand des User-Agents und der Bot-Prüfung von Cloudflare. Eine Regel prüft diese Kategorien vor jeder anderen Regel der Domain: AI Guard blockiert oder lenkt KI-Crawler für das Training um und lässt Suchmaschinen in Ruhe, und Bot Shield hält jeden Bot von einer Domain fern, die nie gecrawlt werden soll.
Eine Ansicht, die diese Bots pro Domain zeigt, mit Pfaden und Statuscodes, bauen wir als Nächstes.