# Boty AI nie wykonują JavaScriptu. Co widzą zamiast strony

> Crawlery asystentów AI — GPTBot, ClaudeBot, PerplexityBot i pokrewne — pobierają surowy HTML i nie uruchamiają JavaScriptu, więc treść dorenderowywana w przeglądarce dla nich nie istnieje. W udokumentowanym na forum r/TechSEO przypadku z lipca 2026 strona cennika aplikacji SaaS w Reakcie miała w surowym HTML 194 słowa i zero kwot wobec 511 słów widocznych w przeglądarce. Sprawdzenie własnej strony zajmuje jedną komendę: pobrać ją curlem i zobaczyć, co zostaje bez przeglądarki.

Autor: Robert Marczyński · Opublikowano: 2026-08-10 · Aktualizacja: 2026-08-10
Kanoniczny URL: https://ekspertodsztucznejinteligencji.pl/blog/boty-ai-nie-wykonuja-javascriptu

## Test, który boli

Wyłącz JavaScript w przeglądarce i wejdź na własną stronę. To, co widzisz, jest wszystkim, co widzi asystent AI, kiedy ktoś pyta o Twoją firmę.

Na forum r/TechSEO pod koniec lipca 2026 opisano przypadek, który tę mechanikę pokazuje na liczbach — i przy okazji pokazuje, jak łatwo się w tym pomiarze pomylić. Aplikacja SaaS w Reakcie z prerenderowaną skorupą: nagłówek i śródtytuły były w dokumencie, reszta dokładana skryptem.

Zacznę od liczby, której nikt w wątku nie podważył, bo to ona rozstrzyga. Strona cennika: **194 słowa w surowym HTML wobec 511 po wyrenderowaniu i zero kwot** — ceny dorenderowywał skrypt. Asystent zapytany o cennik nie ma czego przeczytać.

Z pomiarem strony głównej było gorzej i warto wiedzieć dlaczego. Najpierw padły liczby alarmowe: 228 znaków czytelnej treści na 19 tysięcy bajtów w tytule wątku, potem 300 słów wobec 1033 po wyrenderowaniu w komentarzu. Obie wzięły się z tego samego błędu — odczytu pustego kontenera Reacta zamiast sąsiadującego bloku prerenderu. Po sprostowaniu wyszło bliżej 617 słów według właściciela i 519 wobec 1032 według komentującego, który powtórzył skan. Różnica jest więc dwukrotna, nie kilkunastokrotna — a i tak wystarczyła, żeby model nie znał cennika.

To nie jest egzotyczny przypadek. Tak działa każda aplikacja renderowana wyłącznie po stronie klienta — a więc spora część stron zbudowanych w ostatniej dekadzie na React, Vue czy Angularze bez warstwy serwerowej.

## Dlaczego boty nie renderują

Googlebot nauczył się wykonywać JavaScript, bo Google utrzymuje w tym celu osobną infrastrukturę renderującą — kosztowną i wolną, ale istniejącą. Crawlery asystentów AI poszły inną drogą: pobierają dokument i idą dalej.

Z dokumentacji OpenAI i Anthropic nie wynika, żeby GPTBot, OAI-SearchBot, ClaudeBot, Claude-User czy Claude-SearchBot renderowały strony; obserwacje praktyków z logów serwerowych — w tym wątki z r/TechSEO z 27–28 lipca 2026 — pokazują zgodnie żądania o sam HTML, bez pobierania i wykonywania skryptów. Ma to zresztą sens ekonomiczny: renderowanie milionów stron dziennie kosztuje wielokrotnie więcej niż ich pobranie, a boty odpowiadające na żywe pytania użytkowników nie mają na to czasu — odpowiedź powstaje w sekundy.

Konsekwencja jest binarna. Treść jest w dokumencie HTML albo nie istnieje. Nie ma „częściowo widoczna”, nie ma „bot się domyśli”.

## Jak to sprawdzić u siebie

Najprościej wyłączyć JavaScript w przeglądarce i odświeżyć stronę: to, co zostaje, jest tym, z czego asystent może zbudować odpowiedź.

Test w terminalu wymaga jednej ostrożności, o której warto wiedzieć, zanim się go użyje. Samo `curl … | wc -w` policzy wszystko: znaczniki, atrybuty, wstawiony arkusz stylów i skrypty — na tej stronie zawyża czterokrotnie: liczy około siedmiu tysięcy „słów”, gdy realnej treści jest niecałe dwa tysiące. (Dokładne wartości zmieniają się przy każdej redakcji tego tekstu — dlatego podaję rząd wielkości, a nie liczbę do przepisania.) Żeby zmierzyć treść, trzeba najpierw odsiać skrypty i znaczniki:

```
curl -s https://twojadomena.pl | python3 -c "
import sys, re
t = sys.stdin.read()
t = re.sub(r'(?is)<(script|style)[^>]*>.*?</\1>', ' ', t)
print(len(re.sub(r'<[^>]+>', ' ', t).split()))"
```

Wynik porównaj z liczbą słów widocznych na ekranie. Jeżeli surowy dokument ma ich wyraźnie mniej — jak w przypadku z r/TechSEO, gdzie na stronie cennika brakowało wszystkich kwot — asystenci odpowiadają o Twojej firmie z okrojonej wersji strony albo wcale.

Drugi test celuje w to, co boli najbardziej: stronę z liczbami. Cennik, parametry, terminy. Tu jednak uwaga, na której sam się potknąłem: polski skład wstawia między liczbę a jednostkę twardą spację, więc `grep '300 zł'` ze zwykłą spacją nie znajdzie kwoty stojącej w treści. Na moim cenniku w widocznym tekście, po odsianiu znaczników i skryptów, ten wzorzec daje zero trafień — osiem, które łapie na surowym dokumencie, pochodzi z metaopisów i danych strukturalnych, nie z tabeli cen. Wzorzec dopuszczający twardą spację znajduje w treści dziesięć wystąpień: pięć kwot, każdą w tabeli i w odpowiedzi FAQ. Dlatego wzorzec musi dopuszczać oba znaki:

```
curl -s https://twojadomena.pl/cennik | python3 -c "
import sys, re
t = re.sub(r'(?is)<(script|style)[^>]*>.*?</\\1>', ' ', sys.stdin.read())
t = re.sub(r'<[^>]+>', ' ', t)
print(re.findall(r'[0-9][0-9\\s\\u00a0.,]*(?:zł|PLN)', t)[:10])"
```

Jeśli lista wróci pusta, a na ekranie kwoty są, wstawia je skrypt i bot ich nie zobaczy.

Ten serwis przechodzi oba testy: jest generowany statycznie, więc cała treść — z pięcioma kwotami cennika, które powyższa komenda znajduje w tabeli i w odpowiedziach — stoi w wysyłanym HTML, a strona działa także z całkowicie wyłączonym JavaScriptem. Wersja dla bota i wersja dla człowieka to ten sam dokument; skrypty, które framework dokłada, niczego do treści nie dopisują. To nie była decyzja estetyczna, tylko dokładnie ten rachunek.

## Co zrobić, gdy strona jest po złej stronie granicy

Kolejność według kosztu i skutku.

Najtaniej: uzupełnić HTML tam, gdzie boli najbardziej. Jeżeli cała aplikacja jest kliencka, czasem wystarczy, żeby kilka stron krytycznych — oferta, cennik, kontakt — istniało jako strony statyczne z pełną treścią.

Docelowo: przenieść renderowanie na serwer (SSR) albo do builda (SSG). Frameworki, w których strony klienckie powstają, umieją to od lat; różnica nie wymaga zmiany technologii, tylko zmiany miejsca, w którym powstaje dokument.

Równolegle warto wiedzieć, dokąd zmierza konwencja, i rozróżnić dwie drogi, które łatwo pomylić. Cloudflare ogłosił w lutym 2026 „Markdown for Agents”: konwersję po stronie serwera, uruchamianą nagłówkiem `Accept: text/markdown` na tym samym adresie — agent prosi o markdown, sieć zamienia HTML w locie. W sierpniu 2026 wpisał ten mechanizm w szerszą wizję agentowego internetu. Prostszy wariant tej samej idei to bliźniak pod adresem z końcówką `.md`, publikowany jako zwykły plik statyczny. Ten serwis realizuje wariant prostszy: każda strona treściowa ma bliźniaka, ten tekst też — negocjacji nagłówkiem nie obsługujemy, bo wymagałaby funkcji działającej przy każdym żądaniu.

Na koniec proporcja, żeby nie przestrzelić w drugą stronę: to nie jest wezwanie do „optymalizacji pod boty”. To wezwanie do oddawania treści w dokumencie. Wszystko, co [pisałem o wyborze źródeł przez modele](/blog/jak-modele-ai-wybieraja-zrodla), dzieje się dopiero wtedy, gdy bot ma co czytać.

## Najczęstsze pytania

**Które boty AI nie wykonują JavaScriptu?**

Według zgodnych obserwacji praktyków z lipca 2026 dotyczy to całej klasy: GPTBot i OAI-SearchBot (OpenAI), ClaudeBot, Claude-User i Claude-SearchBot (Anthropic) oraz PerplexityBot. Pobierają dokument HTML takim, jakim odsyła go serwer, bez uruchamiania skryptów. Googlebot potrafi renderować JavaScript, ale to wyjątek z własną infrastrukturą renderującą, nie reguła dla botów AI.

**Jak sprawdzić, co bot AI widzi na mojej stronie?**

Najprościej wyłączyć JavaScript w przeglądarce i odświeżyć stronę — to, co zostanie, jest tym, z czego asystent może zbudować odpowiedź. W terminalu uważaj na skróty: samo `curl … | wc -w` liczy też znaczniki i skrypty, więc zawyża wynik kilkukrotnie. Sensowny pomiar wymaga odsiania skryptów i znaczników przed liczeniem, a najostrzejszy test to sprawdzenie, czy w surowym HTML strony cennika w ogóle są kwoty.

**Czy strona w React albo Vue jest niewidoczna dla AI?**

Nie sam framework decyduje, tylko sposób renderowania. Aplikacja renderowana wyłącznie po stronie klienta (CSR) jest dla botów AI pusta. Ten sam React z renderowaniem serwerowym (SSR) albo generowaniem statycznym (SSG) oddaje pełny HTML i jest widoczny w całości. Różnica nie dotyczy technologii, tylko miejsca, w którym powstaje dokument.

**Czy warto serwować botom osobną wersję strony?**

Rozsądniejsze jest serwowanie wszystkim tego samego pełnego HTML — to usuwa problem u źródła i nie ryzykuje rozjazdu wersji. Rosnącą praktyką uzupełniającą jest udostępnianie agentom tej samej treści w markdownie, tańszej w konsumpcji. Robi się to dwiema drogami: konwersją po stronie serwera na żądanie z nagłówkiem Accept: text/markdown (tak działa ogłoszony przez Cloudflare w lutym 2026 mechanizm Markdown for Agents) albo prościej — publikując bliźniaka pod adresem z końcówką .md.


## Źródła

- r/TechSEO — obserwacje z logów: boty AI pobierają wyłącznie surowy HTML (27.07.2026): https://old.reddit.com/r/TechSEO/comments/1v87b58/our_findings_around_aeo_some_anecdotes_and/
- r/TechSEO — przypadek SaaS w React: cennik 194 słowa wobec 511 i zero kwot w surowym HTML; pierwotne 228 znaków i 300/1033 sprostowane w wątku do ok. 617 słów (właściciel) i 519/1032 (komentujący), 28.07.2026: https://old.reddit.com/r/TechSEO/comments/1v8m6s8/found_out_our_saas_homepage_was_invisible_to_ai/
- OpenAI — dokumentacja crawlerów (GPTBot, OAI-SearchBot, ChatGPT-User): https://platform.openai.com/docs/bots
- Anthropic — dokumentacja crawlerów i skutki ich blokowania (ClaudeBot, Claude-User, Claude-SearchBot): https://support.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-crawling
- Cloudflare — Introducing Markdown for Agents (12.02.2026): https://blog.cloudflare.com/markdown-for-agents/
- Cloudflare — standardy agentowego internetu (6.08.2026): https://blog.cloudflare.com/the-agentic-internet/
