Search Console API bez próbkowania: jak pobrać pełne dane o zapytaniach

4 września, 2026

Raport „Skuteczność” wygląda na komplet danych, dopóki nie zaczniesz go sumować. Kliknięcia z listy zapytań rzadko zgadzają się z sumą na wykresie, a lista urywa się na tysiącu wierszy. To nie błąd interfejsu, tylko konsekwencja tego, jak Google udostępnia dane. API potrafi oddać znacznie więcej, ale tylko wtedy, gdy zapytasz we właściwy sposób.

Poniżej: gdzie realnie leżą limity, jak działa paginacja, kiedy dzielić zapytanie po datach albo po adresach URL i jak zbudować własną historię, która nie zniknie po szesnastu miesiącach.

Skąd biorą się braki w danych o zapytaniach

Rozbieżność między sumą kliknięć na wykresie a sumą w tabeli ma dwa niezależne źródła i warto je rozdzielić, zanim zaczniesz debugować własny skrypt.

Pierwsze to anonimizacja. Google nie pokazuje zapytań, które zadała zbyt mała liczba unikalnych użytkowników. Takie wyszukiwania wliczają się do sumy zbiorczej, ale nie pojawiają się w wymiarze query. Na małych i średnich serwisach potrafi to być większość ruchu, więc lista zapytań nigdy nie zsumuje się do liczby z wykresu. Żadna sztuczka po stronie API tego nie odblokuje: to decyzja o ochronie prywatności, nie limit techniczny.

Drugie źródło to zwykłe obcięcie listy. Interfejs webowy zwraca maksymalnie 1000 wierszy na widok, a API domyślnie 1000 wierszy na wywołanie. Tu już da się działać: paginacja i podział zapytania pozwalają zejść znacznie głębiej. To właśnie ta część jest odzyskiwalna i jej poświęcamy resztę tekstu.

Limity API: dzienne, na zapytanie i na wiersze

Search Console API ma trzy warstwy limitów i mylenie ich ze sobą jest najczęstszą przyczyną nieudanych integracji.

Rodzaj limituWartość orientacyjnaCo się dzieje po przekroczeniu
Wiersze na jedno wywołanie25 000 (domyślnie 1000)Odpowiedź jest po cichu obcinana
Zapytania na minutę (per projekt)rząd 1200Kod 429, wymagany backoff
Zapytania dzienne (per projekt)rząd 30 000Kod 429 do końca doby
Zakres historii16 miesięcyStarsze daty zwracają pustą tablicę

Najważniejszy jest pierwszy wiersz tabeli. Parametr rowLimit przyjmuje wartość do 25 000, ale jeśli go nie ustawisz, dostaniesz 1000 wierszy i żadnego ostrzeżenia. To cicha awaria: skrypt działa, zwraca dane, a ty przez tydzień analizujesz jedną czwartą tego, co masz. Ustawiaj rowLimit jawnie w każdym wywołaniu.

Warto też zrozumieć, przeciwko czemu naliczane są limity dzienne. Kwota jest wspólna dla projektu w Google Cloud, a nie dla pojedynczej usługi w Search Console. Jeśli obsługujesz dwadzieścia domen z jednego projektu, dzielą one tę samą pulę. Przy większym portfolio serwisów rozsądnie jest rozdzielić klientów na osobne projekty, zamiast walczyć z kodem 429 po południu.

Aktualne wartości limitów i pełną specyfikację metody znajdziesz w dokumentacji metody searchanalytics.query w Google Search Central. Traktuj liczby powyżej jako rząd wielkości do zaplanowania architektury, a nie jako gwarancję.

Paginacja i poprawne użycie startRow

Paginacja w tym API jest prosta, ale ma jedną pułapkę, która psuje wyniki po cichu. Kolejne strony pobierasz, zwiększając startRow o wartość rowLimit, aż odpowiedź zwróci mniej wierszy, niż wynosi limit.

  1. Wywołanie pierwsze: startRow: 0, rowLimit: 25000.
  2. Jeśli wróciło dokładnie 25 000 wierszy, pobierz kolejne: startRow: 25000.
  3. Powtarzaj, aż liczba zwróconych wierszy będzie mniejsza niż rowLimit. To sygnał końca zbioru.
  4. Nie zatrzymuj się na pustej odpowiedzi tylko po jednej próbie, jeśli wcześniej dostałeś kod 5xx. Rozróżnij „koniec danych” od „błąd sieci”.

Pułapka dotyczy stabilności sortowania. API zwraca wiersze posortowane malejąco po kliknięciach, ale przy remisach kolejność nie jest gwarantowana między wywołaniami. W ogonie długiego zbioru, gdzie tysiące zapytań ma po jednym kliknięciu albo zero, kolejne strony mogą powtórzyć te same wiersze i pominąć inne. Dlatego po zebraniu wszystkich stron zawsze deduplikuj po kluczu złożonym z wartości wymiarów, na przykład para zapytanie plus strona, a nie po numerze wiersza.

Podział zapytań po datach i po stronach

Sposób na zejście poniżej limitów jest zawsze ten sam: zamiast jednego dużego zapytania wysyłasz wiele małych, których zbiory wyników się nie przecinają. Dwa naturalne wymiary podziału to czas i adresy URL.

Podział po datach

Zamiast pytać o 28 dni naraz, pytaj o każdy dzień osobno. Zapytanie dzienne prawie nigdy nie dobija do 25 000 wierszy, a przy okazji dostajesz dane w rozdzielczości dziennej, których agregat by nie dał. Koszt to 28 wywołań zamiast jednego, co przy limicie rzędu 30 000 dziennie jest bez znaczenia.

Uwaga na strefę czasową: Search Console operuje na czasie pacyficznym Stanów Zjednoczonych, a nie na czasie lokalnym serwisu. Jeśli twój magazyn danych zakłada polskie daty, dzień będzie systematycznie przesunięty. Zapisuj datę dokładnie w takiej postaci, w jakiej zwróciło ją API, a konwersję rób dopiero na etapie raportu.

Podział po stronach

Gdy nawet pojedynczy dzień jest za duży, dziel po adresach URL. Najpierw pobierz listę stron z wymiarem page, potem dla każdej z nich pobierz zapytania z filtrem dimensionFilterGroups na dokładny adres. Ta technika ma dodatkową zaletę: wyniki są od razu przypisane do konkretnego URL, więc nie musisz później rozplątywać par zapytanie plus strona.

Trzeba tylko pilnować liczby wywołań. Serwis z 5000 stron pomnożony przez 28 dni to 140 000 zapytań, czyli grubo ponad dzienny limit. W praktyce dzieli się po stronach tylko te adresy, które w agregacie przekroczyły próg, na przykład 200 wyświetleń, a resztę zostawia w zapytaniu zbiorczym. Ta sama zasada porządkuje zresztą inne integracje danych, o czym pisaliśmy w tekście o tym, jak praktycznie połączyć API GA4 i Search Console.

Filtrowanie po kraju, urządzeniu i typie wyszukiwania

Filtry to nie tylko wygoda analityczna, to również narzędzie do rozbijania dużych zbiorów na mniejsze porcje. Trzy pola, które w praktyce zmieniają najwięcej:

  • searchType (w nowszej wersji type): domyślnie web. Grafika, wideo, wiadomości i wyniki dyskusji to osobne zbiory. Jeśli nie ustawisz tego pola jawnie, nigdy nie zobaczysz ruchu z Google Grafiki, choć w interfejsie masz go pod ręką.
  • country: filtr po kodzie ISO trzyliterowym, na przykład pol. Dla polskiego serwisu z ogonem zagranicznych wyświetleń to jedyny sposób, żeby pozycje i CTR opisywały realny rynek, a nie mieszankę rynków.
  • device: podział na MOBILE, DESKTOP i TABLET. Uśredniona pozycja bez tego podziału bywa myląca, bo jedno urządzenie potrafi ciągnąć średnią w drugą stronę.

Filtry łączysz w dimensionFilterGroups. W obrębie jednej grupy warunki działają jak koniunkcja, a operator equals jest bezpieczniejszy niż contains, który przy adresach URL potrafi złapać też podstrony potomne. Jeśli filtrujesz po dokładnym adresie, użyj equals i pełnego URL razem z protokołem oraz z ukośnikiem na końcu (albo bez, zależnie od tego, jaką formę kanoniczną ma twój serwis, byle konsekwentnie).

Składowanie danych i budowa własnej historii

Minimalny schemat tabeli to: data, zapytanie, strona, kraj, urządzenie, typ wyszukiwania, kliknięcia, wyświetlenia, pozycja. Klucz unikalny na komplecie wymiarów pozwala robić upsert i bezpiecznie powtarzać przerwane pobrania. Trzy zasady, które oszczędzają najwięcej problemów później:

  1. Pobieraj z opóźnieniem 3 dni. Dane z ostatnich dni są niekompletne i dopełniają się jeszcze przez kilkadziesiąt godzin. Zapisanie ich jako finalnych zafałszuje historię na zawsze.
  2. Nadpisuj okno ruchome. Przy każdym uruchomieniu odśwież ostatnie 5 do 7 dni, nie tylko nowy dzień. Wtedy dopełnienia trafią do bazy.
  3. Nie przechowuj wyliczonego CTR. Zapisuj kliknięcia i wyświetlenia, a CTR licz w raporcie. Uśrednianie zapisanych CTR między dniami daje wartości, które nie mają sensu.

Jeśli nie chcesz budować własnego magazynu od zera, część tej pracy da się zamknąć w gotowym przepływie no-code, tak jak w naszym opisie automatycznego raportu SEO wysyłanego z Make do Slacka. Do pracy ad hoc, gdy potrzebujesz zadać danym pytanie, a nie zbudować pipeline, wygodniejszym podejściem bywa wystawienie GSC i GA4 jako narzędzi dla asystenta, co opisaliśmy w tekście o MCP dla marketera, spinającym GSC, GA4 i WordPressa.

Typowe błędy i kody odpowiedzi

Większość awarii w integracjach z tym API sprowadza się do kilku powtarzalnych sytuacji.

ObjawPrawdopodobna przyczynaCo zrobić
403 z komunikatem o uprawnieniachKonto serwisowe nie jest dodane jako użytkownik usługiDodaj adres konta serwisowego w ustawieniach usługi w Search Console
429Przekroczony limit minutowy lub dziennyBackoff wykładniczy, rozłożenie pobrań w czasie, osobny projekt Cloud
Pusta tablica rowsBrak danych dla zakresu albo zła forma adresu usługiSprawdź prefiks: sc-domain:example.pl to co innego niż https://example.pl/
Dokładnie 1000 wierszyNieustawiony rowLimitUstaw jawnie i wprowadź paginację
400 przy filtrachZły format wartości, na przykład dwuliterowy kod krajuKody krajów są trzyliterowe, urządzenia wielkimi literami

W zadaniach automatycznych uwierzytelniaj się kontem serwisowym z przepływem OAuth 2.0 w wariancie dla serwerów, a nie tokenem użytkownika. Ten drugi wygasa i pipeline padnie w najmniej wygodnym momencie.

Podsumowanie

Kompletu danych o zapytaniach nie da się pobrać, bo anonimizacja jest nieodwracalna. Da się natomiast pobrać wszystko, co Google w ogóle udostępnia, a to zwykle kilka razy więcej niż widać w interfejsie: rowLimit ustawiony jawnie, paginacja po startRow z deduplikacją, podział po dniach (przy dużych serwisach także po adresach URL) i zapis u siebie z trzydniowym opóźnieniem.

Najtańszy pierwszy krok: dorzuć do istniejącego skryptu jawny rowLimit i porównaj liczbę zwróconych wierszy z tą sprzed zmiany. Jeśli wcześniej dostawałeś równe 1000, właśnie odzyskałeś dane, o których nie wiedziałeś, że ci ich brakuje.

FAQ

Ile wierszy realnie zwraca Search Console API na jedno wywołanie?

Do 25 000, jeśli ustawisz parametr rowLimit jawnie. Bez tego parametru dostaniesz 1000 wierszy i żadnego komunikatu o obcięciu, co jest najczęstszą przyczyną niekompletnych raportów.

Dlaczego suma kliknięć z listy zapytań nie zgadza się z sumą na wykresie?

Bo Google ukrywa zapytania zadane przez zbyt małą liczbę unikalnych użytkowników. Te kliknięcia wliczają się do sumy zbiorczej, ale nie pojawiają się w wymiarze query. Tej różnicy nie da się usunąć żadnym parametrem API.

Jak daleko wstecz sięgają dane w API?

Szesnaście miesięcy. Starsze zakresy zwracają pustą tablicę wyników. Jeśli chcesz mieć historię dłuższą niż półtora roku, musisz pobierać dane cyklicznie i zapisywać je we własnej bazie.

Kiedy dzielić zapytania po adresach URL zamiast po datach?

Gdy pojedynczy dzień nadal dobija do limitu 25 000 wierszy. Podział po stronach stosuj wybiórczo, tylko dla adresów powyżej progu wyświetleń, bo iloczyn liczby stron i liczby dni bardzo szybko przekracza dzienny limit wywołań.

Dlaczego API zwraca pustą odpowiedź, choć w interfejsie widzę dane?

Najczęściej z powodu złej formy adresu usługi. Usługa typu domena zapisywana jest jako sc-domain:example.pl i wymaga zakodowania dwukropka, a usługa typu prefiks jako pełny adres z protokołem. Pomyłka nie zwraca błędu, tylko pustą tablicę.