We hadden Cloudflare Bot Fight Mode actief. Opvallend verkeer bereikte de website toch.
Volgens onze ervaring als beheerder werkten browser-challenges ook niet betrouwbaar. Hetzelfde gold voor een eerder geprobeerde aanpak genaamd „precursor“. Uiteindelijk was niet nog een generieke botfunctie doorslaggevend, maar een regel die precies was afgestemd op de daadwerkelijk waargenomen requestpatronen.
Onze AI-agenten hebben twee verschillende scrapingpatronen uit het verkeer gedestilleerd en vertaald naar een gerichte Cloudflare-blokkeerstrategie. De regels combineren browserkenmerken, Fetch Metadata, bronnetwerken, referrers, instappagina's en Cloudflares markering van geverifieerde crawlers. Passende requests worden direct aan de edge beëindigd met HTTP 403.
We publiceren bewust niet de volledige fingerprints. Een anti-scrapingregel is geen goede plek voor een openbaar changelog voor de scrapers.
Wat ons überhaupt opviel
De eerste aanwijzing kwam niet uit één enkel beveiligingsevent, maar uit de combinatie van meerdere meetpunten.
Een Minilytics-snapshot toonde 544 directe sessies bij nul gemeten uitgaande conversies. Tussen twee afgeronde uren stegen de directe sessies van 24 naar 163.
Tegelijkertijd zag Cloudflare in een onderzocht venster van 30 minuten ongeveer 17.700 HTTP-verzoeken, waarvan er ongeveer 15.400 de origin bereikten. Een origin-fragment van vijf minuten bevatte 1.980 requests van 1.238 verschillende IP-adressen.
Belangrijk is het onderscheid tussen de grootheden: een HTTP-request is geen sessie. En „nul conversies“ betekent bij ons in deze context nul geactiveerde geconfigureerde uitgaande events – niet aangetoonde nul verkopen of nul omzet.
We hadden daarmee echter genoeg signaal om het verkeer nauwkeuriger uit elkaar te halen.
Patroon 1: de browser zei Chrome – de requestmetadata klopten er niet mee
De eerste grote groep roteerde massaal over IP-adressen en landen. De clients gaven zich uit voor Windows-Chrome-browsers en wisselden tussen meerdere Chrome-identiteiten.
In het onderzochte fragment hoorden 1.628 requests van 1.120 IP-adressen in 100 landen bij dit patroon. Een groot deel daarvan vroeg bovendien Next.js-paginadata op.
Dat alleen is nog geen bewijs van een bot. RSC-requests ontstaan ook bij normaal browsen op Next.js-pagina's.
Interessant werd de tegenstrijdigheid op een andere plek: de requests deden zich voor als een moderne browseridentiteit, maar een fetch-metadata-kenmerk dat we bij deze requestklasse hadden verwacht, ontbrak volledig.
Onze eerste nieuwe blokkeerlogica koppelt daarom meerdere voorwaarden:
- Request naar een Srocket-host
- GET
- passende Windows-Chrome-identiteit uit het waargenomen patroon
- ontbrekende fetch-metadata-header
- geen door Cloudflare geverifieerde bot
- geen interne Next.js- of API-paden
De concrete lijst met versies publiceren we niet.
Dat is het beslissende verschil met een grove regel als „Chrome-versie X blokkeren“: niet één eigenschap activeert de blokkade, maar de tegenstrijdigheid tussen de opgegeven browseridentiteit en de daadwerkelijk verzonden requestcontext.
Cloudflare stelt met `cf.client.bot` een veld beschikbaar dat bekende goede bots en crawlers markeert. Deze geverifieerde crawlers sluiten we uit van de blokkeerlogica.
Patroon 2: deze keer zag de browserrequest plausibel eruit
Kort daarna verscheen een tweede patroon.
Deze requests hadden browserachtige headers en gebruikten ook een gewone `Sec-Fetch-Site`-waarde. Daardoor vielen ze niet onder de eerste vingerafdruk.
Hier zat het signaal in de combinatie van herkomst, browserprofiel en doelpagina.
We zagen directe HTML-binnenkomsten uit een roterende pool van bronnetwerken. De requests gebruikten slechts enkele exact terugkerende browserprofielen, kwamen zonder referrer binnen en raakten gericht een kleine groep van onze vergelijkingspagina's.
Zulke wisselende bronnetwerken zijn ook de reden waarom IP-adressen alleen als vingerafdruk weinig waard zijn. Wie de technische achtergrond daarvan beter wil begrijpen, vindt in onze proxy-vergelijking de verschillen tussen gangbare proxytypen en aanbieders.
Onze tweede blokkeerlogica combineert daarom:
- een waargenomen bronpool
- een van de exact terugkerende browserprofielen
- GET
- lege referrer
- een kleine gedefinieerde groep getroffen binnenkomstpagina's
- geen door Cloudflare geverifieerde bot
Belangrijk: we blokkeren niet pauzeloos een compleet ASN en ook niet pauzeloos bezoekers zonder referrer. Pas de combinatie van kenmerken leidt tot de blokkade.
Ook de concrete netwerken, user agents en paginacombinaties blijven intern.
Waarom `Sec-Fetch-Site: none` geen botsignaal is
Het tweede patroon laat goed zien waarom afzonderlijke headers gevaarlijk slechte blokkeercriteria kunnen zijn.
Volgens MDN is `Sec-Fetch-Site: none` volkomen normaal browsergedrag, bijvoorbeeld wanneer iemand een URL rechtstreeks in de adresbalk invoert of een bladwijzer opent.
Een request met deze waarde is dus niet automatisch verdacht.
Daarom blokkeren we deze groep alleen wanneer bronpool, exact browserprofiel, lege referrer en getroffen landingspagina tegelijk overeenkomen.
Dat is strikter dan een generieke botregel – en bewust zo ingericht.
De AI heeft niet „één bot herkend“ – ze heeft er twee regelmodellen van gemaakt
Het interessante deel voor ons was niet dat een model naar verkeer kijkt en „bot“ zegt.
Nuttig werd de AI pas toen uit veel afzonderlijke requests twee onderscheidbare technische patronen ontstonden:
1. Identiteitsconflict: Browserprofiel en Fetch Metadata passen niet bij elkaar. 2. Bron-fingerprint: Herkomst, browserprofiel, directe toegang en doelpagina komen herhaaldelijk samen voor.
Uit deze patronen heeft onze AI-agent een Cloudflare-strategie afgeleid, die we daarna hebben getest tegen echte requests en normale browsertoegang.
Dat is voor ons de veel interessantere vorm van AI in de praktijk: niet een chatbot die security uitlegt, maar agents die echte telemetrie omzetten in een gecontroleerde edge-regel.
Elders hebben we al beschreven waarom botverkeer attributie en retargeting kan vertekenen. Tegelijkertijd laat het huidige debat over transparantieverplichtingen voor AI-crawlers zien hoe moeilijk geautomatiseerd verkeer tegenwoordig netjes is toe te wijzen.
Geen extra deployment: de regel staat direct bij Cloudflare
De definitieve oplossing draait als bestaande Cloudflare Custom Rule met de actie Block.
We hoefden daarvoor niet de applicatie opnieuw uit te rollen en ook geen extra regelslot te gebruiken. De bestaande scanner-/flood-regel is uitgebreid met de twee extra patronen.
De logica kan bewust alleen op principeniveau worden samengevat:
- Al bevestigde scanners blijven geblokkeerd.
- Patroon 1 slaat alleen aan als browseridentiteit en Fetch Metadata op de waargenomen manier met elkaar in tegenspraak zijn, het verzoek een GET is, geen geverifieerde bot wordt herkend en er geen interne framework- of API-paden worden geraakt.
- Patroon 2 slaat alleen aan bij de combinatie van een waargenomen bronnenpool, een exact terugkerend browserprofiel, een directe toegang zonder referrer en een van de getroffen instappagina's.
- Pas als een tak volledig past, volgt de actie Block.
De concrete netwerken, browserversies, user agents en de productieve Cloudflare-expressie publiceren we niet. Meer hoeft een scraper over de regel niet te weten.
Cloudflare zelf adviseert Custom Rules wanneer meerdere request-velden gecombineerd moeten worden. Een terminerende Block-actie werkt dan al op het niveau van de Custom Rules en laat passende verzoeken niet eerst doorlopen naar nagelagerde bot-mechanismen.
Wat er na het activeren gebeurde
We hebben niet alleen gecontroleerd of Cloudflare de regel accepteert. We hebben gecontroleerd of hij daadwerkelijk het gewenste patroon raakt en of normale verzoeken gewoon blijven werken.
De controletests leverden het volgende op:
- Testverzoek met de eerste vingerafdruk: Cloudflare 403
- dezelfde browserfamilie met normale navigatiekenmerken: 200
- openbare vergelijkingspagina bij normale toegang: 200
- echt event uit het tweede patroon: Custom rules / Block
- weergegeven regelmatches tijdens de controle: ongeveer 1.300
Opvallend duidelijk was het origin-verloop: bij het eerste patroon vielen de passende verzoeken van 626 in een volledige minuut naar nul in het laatste 18-seconden-interval van het onderzochte fragment.
In een latere Minilytics-controle kwamen er over 156 seconden geen nieuwe directe sessies zonder outbound-conversie bij.
Dat bewijst niet dat ongewenst verkeer voorgoed is verdwenen. Het laat wel zien dat de nieuwe regel de waargenomen patronen daadwerkelijk aan de edge heeft onderschept.
Waarom we niet beweren dat er geen false positives kunnen zijn
We hebben de regel getest met normale browserachtige toegang en bewust nauw afgebakend.
Toch zou "gegarandeerd zonder vals alarm" onzorgvuldig zijn.
Een echte directe bezoeker zou theoretisch ook meerdere kenmerken van het tweede patroon tegelijk kunnen vervullen – bijvoorbeeld vanuit een getroffen bronnetwerk, met een van de terugkerende browserprofielen en op een van de getroffen pagina's.
Daarom zien we de regel niet als universele anti-botoplossing, maar als incidentspecifieke fingerprint met gedocumenteerde terugdraaimogelijkheid.
Hetzelfde geldt voor het eerste patroon. Als scrapers hun request-identiteit wijzigen, kan ook een fingerprint aan effectiviteit verliezen.
Het voordeel zit juist daarin dat we geen magische permanente oplossing beweren: we kunnen observeren, opnieuw classificeren en de edge-regel gericht bijsturen.
Wat we uit het incident meenemen
Bot Fight Mode was niet nutteloos. Maar een generieke botafweer kon deze twee verkeerspatronen bij ons niet voldoende stoppen.
Pas de combinatie van eigen telemetrie, AI-ondersteunde patroonanalyse en een nauwkeurige Cloudflare Custom Rule maakte het verschil.
Voor andere websites zijn onze concrete fingerprints niet overdraagbaar. De methode wel:
Jaag niet op IP-adressen na. Blokkeer niet afzonderlijke headers op zichzelf. Combineer meerdere onafhankelijke request-kenmerken, sluit geverifieerde crawlers uit, test normale browsertoegang en meet daarna het effect.
Zo hebben onze AI-agenten een verkeersprobleem omgezet in een controleerbare edge-regel – zonder scrapers een universele handleiding aan te reiken.
