72% mojego ruchu to nie przeglądarka: co zmierzyłem na małej stronie

72% mojego ruchu to nie przeglądarka: co zmierzyłem na małej stronie

Ostatnio zweryfikowano: 20 października 2026
12 min czytania
Case study
500+ projektów WP
Core Web Vitals

Większość tekstów o ruchu botów to albo materiał sprzedażowy dostawcy, albo opowieść z pola bitwy z witryny na tyle dużej, żeby ktoś chciał ją zaatakować celowo. To nie jest ani jedno, ani drugie. To jedna mała strona firmowa, jedno konto Cloudflare i liczby, które znalazłem, kiedy w końcu porządnie się im przyjrzełem.

W skrócie: 72,4% żądań do mojej strony w ciągu 23 godzin nie miało rozpoznawalnego user agenta przeglądarki. Chrome odpowiadał za 19,7%. Wszystkie nazwane roboty wyszukiwarek razem, Googlebot, Bingbot i Applebot, odpowiadały za 3,5%.

To ta ostatnia liczba przewróciła moje myślenie do góry nogami. Niemal każdy argument, jaki przeczytasz o zarządzaniu robotami, dotyczy nazwanej mniejszości, a nazwana mniejszość jest błędem zaokrąglenia przy całej reszcie dobijającej się do drzwi.

#Ile ruchu na małej stronie to boty

Wszystkie liczby pochodzą z analityki GraphQL Cloudflare dla mojej własnej strefy, z 23-godzinnego okna w sierpniu 2026 roku. Nic tu nie jest modelowane ani ekstrapolowane.

KlientŻądaniaUdział
Nierozpoznane42 70072,4%
Chrome11 62819,7%
Bingbot1 5232,6%
Edge1 0641,8%
Firefox5230,9%
Googlebot3620,6%
Chrome Mobile3180,5%
Safari3010,5%
Applebot1720,3%
curl1180,2%

Przez dwa pełne dni stosunek żądań do unikalnych odwiedzających wynosił 6,5 i 6,6. Człowiek czytający dwie czy trzy strony nie generuje sześciu i pół żądania, kiedy wykluczy się zasoby statyczne, więc to ta sama historia widziana pod innym kątem.

Skrajną wersję tego widziałem wcześniej w tym samym miesiącu. Jednego dnia liczba żądań potroiła się do 173 093, podczas gdy liczba unikalnych odwiedzających stała w miejscu na 7 527. Potrojone żądania przy niezmienionej publiczności to nie wzrost, tylko przeczesywanie, i rozkład ścieżek to potwierdził: najczęściej odpytywany pojedynczy adres URL zebrał z tej sumy zaledwie 677 żądań. Coś przeszło przez cały korpus.

Dla porównania z dużym serwisem: Fundacja Wikimedia w tekście Seleny Deckelmann z 5 października 2026 przypomina swoje dane z 2025 roku, według których aktywność botów zwiększyła zużycie pasma o 50%, a boty generowały 65% najbardziej zasobożernego ruchu. Agenci, których fundacja uważa za należących do OpenAI, wysłali miliony automatycznych żądań do publicznych API i setki tysięcy zapytań do Wikidata Query Service, a ten ruch mógł przyczynić się do częściowej awarii WDQS w maju. Nikt nie wystąpił o zgody, których zasady Wikipedii wymagają od botów, a fundacja nie znalazła dowodów na naruszenie swoich systemów ani danych. Moje 23-godzinne okno pokazuje ten sam rodzaj ruchu na małej strefie, a w skali Wikimedii przekłada się on na koszty serwerów i przestoje.

#Co właściwie liczy się jako ruch botów

Mogę udowodnić, że ci klienci nie przedstawiają się jako przeglądarki. Nie mogę udowodnić, czym są, i nikt inny odpalający to samo zapytanie też nie może.

W tej kategorii mieszczą się monitory dostępności, za które płacę, testery linków, biblioteki HTTP w czyimś skrypcie, skanery bezpieczeństwa, czytniki kanałów, roboty AI budujące zbiory treningowe i agenci pobierający stronę w imieniu człowieka, który zadał pytanie. Część tego ruchu jest dla mnie użyteczna. Część jest obojętna. Odrobina jest wroga.

Uczciwy nagłówek nie brzmi więc „72% mojego ruchu to boty, które mnie atakują”. Brzmi: 72% mojego ruchu nie działa w przeglądarce, a ta różnica zmienia to, co należy z tym zrobić.

#Czy robots.txt zmniejsza obciążenie serwera

Najpierw poszedłem szukać problemu z robots.txt, bo to najtańsza rzecz do sprawdzenia i naprawdę częsta usterka: robots.txt jest serwowany osobno dla każdego protokołu i każdej subdomeny, więc http, www i domena główna mogą się po cichu ze sobą nie zgadzać. Moje były identyczne, bajt w bajt, wszystkie przekierowywały na jeden kanoniczny adres.

Warto to powiedzieć wprost, bo czysty wynik też jest wynikiem. Gdybym opublikował tylko to, co naprawiłem, dostałbyś zniekształcony obraz tego, jak często taka praca cokolwiek znajduje.

Druga rzecz warta powiedzenia: robots.txt nie zmniejsza obciążenia. To prośba o współpracę skierowana do klientów, którzy go czytają. Wszystko, co go ignoruje, i tak trafia na serwer i i tak zużywa to, co działa na ścieżce żądania. Obciążenie realnie zmniejszają warstwy oceniane, zanim uruchomi się kod aplikacji.

Ten tekst dotyczy tego, co dociera do serwera, czyli warstwy, którą musi zaprojektować programista WordPress.

#Dlaczego Cloudflare nie cachuje stron HTML

Wyciągając te liczby, zauważyłem współczynnik trafień w cache na brzegu sieci: około 4%, na stronie, której każda podstrona jest prerenderowana na etapie builda. Powinno być odwrotnie.

Każda strona wysyła to:

cache-control: public, max-age=60, s-maxage=3600, stale-while-revalidate=86400

I każda strona wracała z cf-cache-status: DYNAMIC. Prosiłem o godzinę cache’owania na brzegu sieci i ani razu jej nie dostałem.

Dwie przyczyny, a wyjaśniają to dopiero razem.

Cloudflare domyślnie nie cachuje HTML. Domyślny poziom cache obejmuje listę statycznych rozszerzeń, a HTML na niej nie ma, niezależnie od tego, co mówi serwer źródłowy. Wysłanie s-maxage nie sprawia, że HTML staje się cache’owalny; sprawia to reguła cache.

Moja własna funkcja zablokowała resztę. Serwuję markdownową reprezentację każdej strony agentom, którzy proszą o nią przez Accept: text/markdown. To oznacza, że jeden adres URL ma dwie reprezentacje. Żeby cache był bezpieczny, klucz cache musi zawierać Accept, a standardowy klucz cache Cloudflare zawiera wyłącznie Vary: Accept-Encoding. Naiwne włączenie cache’owania prędzej czy później podałoby agentowi zapisaną stronę HTML albo podałoby człowiekowi zapisany Markdown, co jest gorsze niż brak cache’u w ogóle.

To jest ta część warta uogólnienia: koszt był niewidoczny, bo należał do funkcji, z której byłem dumny. Nikt nie audytuje ceny własnego dobrego pomysłu.

Naprawą była reguła cache warunkowana nagłówkiem żądania: cachuj strony, ale tylko wtedy, gdy Accept nie prosi o Markdown. Wtedy klucz cache nigdy nie musi nieść Accept, bo żądania negocjujące treść są w całości wyłączone z cache’owania. Jest ich około stu dziennie wobec dziesiątek tysięcy zwykłych odsłon.

Wchodzi to z drugą połową, która nie jest opcjonalna: czyść cache przy każdym wdrożeniu. Bez tego każde wdrożenie zostawia części publiczności nawet godzinę nieaktualnych stron, a następne, co usłyszysz, to że zmiana nie jest widoczna. Reguła cache bez kroku czyszczenia to pułapka zastawiona na samego siebie.

#Czy cache na brzegu sieci pomaga przy skokach ruchu crawlerów

Przy max-age=60 cache na brzegu sieci niewiele zmienia dla powracającego człowieka. Zmienia to, co dzieje się wtedy, gdy coś przeczesuje całą stronę.

Moje strony przechodzą przez funkcję brzegową przy każdym żądaniu HTML, a darmowy plan pozwala na 100 000 wywołań funkcji dziennie. Mediana dnia to około 30 000. W dniu tamtego przeczesywania było to 131 255, czyli powyżej sufitu.

Cache nigdy nie był więc wydajnościowym drobiazgiem. Był różnicą między crawlem niewidocznym a crawlem, który kładzie stronę. Ta zmiana ramy stała się dostępna dopiero wtedy, gdy udział botów i współczynnik trafień w cache znalazły się na jednej stronie.

#Dlaczego przekierowanie 301 psuje żądania POST do endpointu MCP

Trzymam osobny licznik dla powierzchni czytelnej maszynowo, bo analityka przeglądarkowa jej nie widzi: agent pobierający plik JSON nie uruchamia żadnego JavaScriptu, więc narzędzie analityczne oparte na beaconie nie raportuje kompletnie nic.

Ten licznik mówi o mniej więcej 102 żądaniach agentów dziennie. Rozkład mnie zaskoczył: dwie trzecie idzie do mojego endpointu MCP, a nie do kart deklaratywnych w rodzaju agent.json czy llms.txt, którym poświęca się całą uwagę w rozmowie o widoczności w AI.

Potem powiedział mi coś gorszego. Adres bez ukośnika na końcu odpowiadał 301. Przekierowanie zamienia POST w GET i gubi ciało żądania, więc klient JSON-RPC albo nie dostaje nic, albo dostaje błąd parsowania. Zmierzone przez jeden dzień: 29 zepsutych wywołań wobec 2 udanych.

Miałem publiczny endpoint dla agentów, który dla dużej części klientów był po prostu zepsuty, i nie miałbym o tym pojęcia. Nie pojawia się w żadnym dashboardzie, do którego zagląda marketer. Nie wygenerował żadnego błędu, który ktoś by zobaczył, bo ci, wobec których zawodził, nie byli ludźmi.

Trzy próby naprawy w aplikacji nie powiodły się, bo normalizacja końcowego ukośnika po stronie platformy dzieje się przed uruchomieniem kodu aplikacji. Naprawa musiała usiąść nad przyczyną, jako reguła przepisywania na brzegu sieci. Dzień później: 12 udanych odpowiedzi na POST tam, gdzie wcześniej nie było żadnej.

#Który kod przekierowania zachowuje żądanie POST

Standard HTTP wyjaśnia, dlaczego 301 mi zaszkodził. RFC 9110, sekcja 15.4.2 zaznacza, że z przyczyn historycznych klient podążający za 301 może zmienić metodę z POST na GET, i wskazuje 308 Permanent Redirect jako kod na sytuację, w której jest to niedopuszczalne. Ta sama uwaga stoi przy 302, tyle że odsyła do 307.

Dla 307 Temporary Redirect reguła jest twarda: klient nie może zmienić metody żądania, gdy automatycznie podąża za przekierowaniem (sekcja 15.4.8). Standard ostrzega też, że 308 jest znacznie młodszy od pozostałych kodów, zdefiniowany w czerwcu 2014 roku, i może nie być wszędzie rozpoznawany (sekcja 15.4.9).

Dla endpointu JSON-RPC zostają więc dwie drogi. 308 zakłada, że każdy klient go obsługuje i wyśle ciało żądania ponownie. Wewnętrzne przepisanie adresu nie zwraca żadnego przekierowania, więc klient niczego nie musi rozstrzygać. Moja naprawa na brzegu sieci jest właśnie takim przepisaniem, więc to pytanie w ogóle do klienta nie dociera.

#Jak zmierzyć ruch botów w Cloudflare GraphQL

Nic z tego nie wymagało płatnego narzędzia. Endpoint analityki GraphQL Cloudflare odpowiada na wszystko, a całe ćwiczenie to jeden token API i garść zapytań.

Dwie pułapki kosztowały mnie czas, więc warto je nazwać.

Uprawnienie tokena nie jest tym oczywistym. Mój od dawna używany token API mógł wdrażać, czyścić cache i zarządzać regułami, a przy każdym zapytaniu analitycznym zwracał błąd uprawnień. Analityka potrzebuje konkretnie Zone / Analytics / Read, a token może być w pełni zdolny do zmieniania twojej strony, będąc jednocześnie niezdolnym do powiedzenia o niej czegokolwiek. Gorzej, token o zasięgu konta może nie przejść zwykłego sprawdzenia /user/tokens/verify, działając poprawnie dla GraphQL, więc testuj go prawdziwym zapytaniem, a nie endpointem weryfikacyjnym.

Okno czasowe ma limit. Na moim planie zbiór adaptive request odmawia każdego zapytania obejmującego więcej niż jeden dzień i trzyma mniej więcej trzy dni historii. Poproś o trzydzieści dni, a nie dostaniesz częściowej odpowiedzi, tylko błąd. Przejdź pętlą dzień po dniu i zagreguj po stronie klienta.

Kształt zapytania, które dało tabelę user agentów, jest niewielki:

{ viewer { zones(filter: {zoneTag: "YOUR_ZONE_ID"}) {
    httpRequestsAdaptiveGroups(
      limit: 12,
      filter: {datetime_geq: "2026-08-19T15:00:00Z"},
      orderBy: [count_DESC]
    ) { count dimensions { userAgentBrowser } }
} } }

Podmień userAgentBrowser na cacheStatus, edgeResponseStatus, clientRequestPath albo clientCountryName i masz resztę obrazu. Dla żądań w zestawieniu z unikalnymi odwiedzającymi httpRequests1dGroups niesie oba w jednym wierszu.

Jedno zastrzeżenie, które ma znaczenie przy czytaniu własnych wyników: userAgentBrowser to klasyfikacja Cloudflare, a nie prawda objawiona. „Nierozpoznane” znaczy, że ich parser nie dopasował znanej sygnatury przeglądarki. Robot wysyłający ciąg user agenta Chrome jest liczony jako Chrome, więc prawdziwy udział ruchu spoza przeglądarek to podłoga, a nie sufit.

#Czy blokować ruch botów na stronie

Oczywistym następnym ruchem po znalezieniu 72% jest zacząć blokować. Nie zrobiłem tego, a uzasadnienie jest warte więcej niż sama decyzja.

Nie dodałem reguł WAF ani limitów zapytań. Jedno i drugie by zadziałało i jedno i drugie siedzi we właściwej warstwie, przed kodem aplikacji. Ale nie miałem dowodu szkody. Nic nie leżało, nic nie działało wolno dla ludzi i nie ponosiłem kosztu, którego reguła cache nie usunęłaby taniej. Blokowanie ruchu, o którym nie wykazałeś, że szkodzi, wymienia realne ryzyko, czyli odcięcie czegoś, od czego zależysz, na ryzyko hipotetyczne.

Nie goniłem błędu, który naprawiał się sam. W trakcie tej pracy znalazłem 9 956 przekroczeń limitu czasu bramy w ciągu doby, rozłożonych po całej stronie, łącznie ze stronami kontaktu we wszystkich językach. Wyglądało to na sytuację alarmową. Potem rozbicie pokazało, że każde jedno miało nierozpoznany user agent: zero z Chrome, Safari, Googlebota czy Bingbota. Żaden człowiek i żadna wyszukiwarka nigdy tego nie zobaczyły. Zapisałem to i zostawiłem w spokoju. Dzień później to samo okno pokazało trzy. Gdybym to „naprawił”, naprawiałbym czyjegoś robota i wypuszczał zmianę we własnym kodzie, która niczego nie leczy.

Nie sfinansowałem drogiej pracy pod agentów. Ten sam licznik, który znalazł zepsuty endpoint, wycenił mi też zaległą listę zadań. Podpisane dokumenty tożsamości, atestacje stron trzecich, sandbox, czytelny maszynowo kontrakt: każde to tygodnie pracy i każde jest uzasadnione założeniem, że agenci robiący zakupy czytają moje pliki deklaratywne. Przy 26 żądaniach dziennie do agent.json to założenie nie przeżywa kontaktu z licznikiem. Dwa niezależne pomiary z odstępem doby były zgodne, więc decyzja opiera się teraz na pomiarze, a nie na jednym odczycie.

We wszystkich trzech przypadkach wzorzec jest ten sam. Pomiar daje prawo do nierobienia niczego, a to zastosowanie danych ma znacznie mniej uznania, niż mu się należy. Większość wartości, jaką wyciągnąłem z tego ćwiczenia, to nie były te dwie naprawy. To była wiedza, która z niepokojących liczb zasługuje na mój tydzień.

#Lista kontrolna ruchu botów dla małej strony

Zmierz, zanim cokolwiek zablokujesz. Wyciągnij rozbicie na user agenty za pełną dobę. Stosunek żądań do unikalnych odwiedzających to najszybszy test zdrowego rozsądku, a jeśli jest znacznie powyżej dwóch czy trzech, przyjrzyj się bliżej.

Sprawdzaj status cache, nie nagłówki cache. cache-control to prośba. cf-cache-status, albo jego odpowiednik u twojego CDN-a, to odpowiedź. Długo wierzyłem nagłówkowi, który ani razu nie zadziałał.

Policz ruch, którego twoja analityka nie widzi. Jeśli widoczność dla agentów AI ma dla ciebie jakiekolwiek znaczenie, ten ruch pojawia się wyłącznie w logach serwera albo brzegu sieci. Moje ujawniły zepsuty endpoint, który po cichu zawodził od tygodni.

Uważaj, co nazywasz atakiem. Większość tego, co znalazłem, nie była ani złośliwa, ani użyteczna. Była obojętna. Użyteczną odpowiedzią na obojętny ruch jest sprawienie, żeby jego obsługa była tania, a nie walka z nim.

Audytuj koszt własnych funkcji. Najdroższą rzeczą, jaką znalazłem, nie był bot. Była nią funkcja, którą zbudowałem świadomie, wyceniona na zero, a która kosztowała mnie cały mój cache HTML na brzegu sieci.

Obojętny ruch botów to też powód, by audyt zgodności UE dla WordPressa trzymać osobno od wykresów vanity: warstwa kontroli i analityka to nie ta sama robota.

Następny krok

Przekuj artykuł w realne wdrożenie

Pod tym wpisem dokładam linki, które domykają intencję użytkownika i prowadzą dalej w strukturze serwisu.

Chcesz wdrożyć ten temat na swojej stronie?

Jeśli problemem są Core Web Vitals, wolny frontend albo ciężki WordPress, rozpiszę i wdrożę konkretny plan optymalizacji.

Często zadawane pytania

Najważniejsze odpowiedzi, które pomagają wdrożyć temat w praktyce.

Jaka część ruchu na małej stronie to boty?#
Na mojej własnej stronie, w pomiarze z 23 godzin w sierpniu 2026 roku, 72,4% żądań miało nierozpoznany user agent, wobec 19,7% z Chrome. To jedna strona z jednego dnia i nie należy czytać tego jako średniej branżowej, ale jest to liczba zmierzona, a nie oszacowana.
Czy Googlebot i Bingbot to największe boty na stronie?#
Na mojej nie. Googlebot, Bingbot i Applebot odpowiadały łącznie za 3,5% żądań, podczas gdy nierozpoznani klienci za 72,4%. Prawie cała dyskusja o blokowaniu robotów dotyczy nazwanej mniejszości.
Czy robots.txt zmniejsza obciążenie serwera przez boty?#
Tylko w przypadku klientów, którzy go czytają i respektują. Robot, który ignoruje robots.txt, i tak dociera do serwera i i tak zużywa wszystko, co działa na ścieżce żądania. Obciążenie zmniejszają warstwy oceniane przed aplikacją: reguły cache, WAF i limity zapytań.
Dlaczego w pełni prerenderowana strona ma niski współczynnik trafień w cache?#
Ponieważ wysłanie cache-control to prośba, a nie wynik. Cloudflare domyślnie nie cachuje HTML niezależnie od tego, co mówi nagłówek serwera źródłowego, a każda negocjacja treści na nagłówku Accept sprawia, że strony nie da się bezpiecznie zapisać w cache, dopóki nie uwzględni tego klucz cache albo reguła. Zmierzyłem 4% trafień, choć każda strona prosiła o godzinę cache'owania na brzegu sieci.
Czy analityka przeglądarkowa widzi ruch agentów AI?#
Nie. Analityka oparta na javascriptowym beaconie nie widzi klienta, który nie wykonuje JavaScriptu, a takich jest większość agentów i robotów. Ten ruch pojawia się wyłącznie w logach żądań po stronie serwera lub na brzegu sieci.

Polecane artykuły