Większość scraperów zawodzi, zanim serwer odczyta jakikolwiek nagłówek.
Serwer sprawdza sygnaturę połączenia, którą twój klient wysyła w sieci, i decyduje, czy jesteś przeglądarką, czy biblioteką klienta, która udaje przeglądarkę. Biblioteka requests w Pythonie, pakiet net/http w Go, zwykły curl: wszystkie przekazują charakterystyczny odcisk palca w momencie nawiązania połączenia. Strony, którym na tym zależy (Datadome, Akamai, Imperva, zarządzana część Cloudflare), odrzucają połączenie lub serwują stronę wyzwania (challenge page), zanim twój ciąg User-Agent w ogóle zacznie mieć znaczenie.
To właśnie rozwiązuje unblocker: true w FourA. W zeszłym miesiącu dopracowaliśmy elementy, które sprawiają, że działa to niezawodnie.
Co nowego
unblocker: true to pojedyncza flaga w dowolnym wywołaniu /api/single. Gdy ją włączysz, robimy trzy rzeczy: wstrzykujemy zestaw nagłówków przeglądarki, wysyłamy żądanie przez transport pasujący do tego, co prawdziwa przeglądarka wysyła w sieci, oraz dekompresujemy to, co zwraca serwer (gzip, brotli, deflate). Dwie pierwsze opcje są dostępne od wersji beta. Trzecia (automatyczna dekompresja brotli) weszła do produkcji 25 marca, a mechanizm spinania wersji wylądował następnego dnia, aby nagłówki i transport szły w parze.
Jak to działa
Oto jak wygląda żądanie:
curl -X POST "https://api.foura.ai/api/single" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"url": "https://example.com/products",
"method": "GET",
"unblocker": true
}'
Pod spodem działają trzy warstwy.
Wstrzykiwanie nagłówków. Ustawiamy pełny zestaw nagłówków przeglądarki: User-Agent, Sec-Ch-Ua, Sec-Ch-Ua-Platform, Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest, Accept, Accept-Language oraz Accept-Encoding. Kolejność ma znaczenie. Prawdziwe przeglądarki emitują je w określonej sekwencji, a biblioteki detekcji to sprawdzają.
Sygnatura połączenia. Nasz transport na poziomie bajtów pasuje do aktualnej sesji przeglądarki: ta sama kolejność rozszerzeń, te same preferencje szyfrów, te same specyfiki uścisku dłoni (handshake). Standardowy curl, biblioteka requests w Pythonie czy pakiet net/http w Go generują sygnatury oflagowywane maszynowo w ciągu milisekund na chronionej infrastrukturze.
Automatyczna dekompresja. Gdy flaga unblocker jest włączona, ustawiamy Accept-Encoding na gzip, deflate, br i transport rozpakowuje ciało odpowiedzi. Otrzymujesz z powrotem zdekodowany łańcuch znaków (lub Buffer, jeśli przekażesz returnBuffer: true). Żadnej ręcznej obsługi brotli, żadnych niezgodności nagłówków z ciałem odpowiedzi, gdy strona wybierze deflate zamiast gzip.
Dlaczego spinanie wersji jest ważne
Sygnatury połączeń są powiązane z wersją. Szczegóły sieciowe przeglądarki z tego miesiąca nie są takie same jak w zeszłym miesiącu, a strona starannie pobierająca odciski palców (fingerprinting) zauważy różnicę. Spinamy ze sobą ruchome części, aby nagłówki, obiekty navigatora i sygnatura połączenia zawsze zgłaszały tę samą wersję przeglądarki.
Jeśli brzmi to skomplikowanie, to dlatego, że takie jest. Przejechaliśmy się na niezgodności podczas marcowej migracji monorepo, kiedy jeden element sam się zaktualizował, a reszta rozjechała się z nim. Naprawa wymagała dwóch commitów: przypięcia na sztywno ruchomego elementu i braku zaufania do menedżera pakietów, że utrzyma wszystko w zgodności.
Wpływ
W wewnętrznych testach na celach z silnym fingerprintingiem (finanse, podróże, chroniony e-commerce), różnica między unblocker: false a unblocker: true to różnica między stroną wyzwania a kodem 200. Zwykły curl uderzający w zarządzane Cloudflare od razu trafia na błąd 403. Ten sam adres URL z flagą unblocker: true przechodzi, ponieważ połączenie na poziomie sieciowym wygląda jak sesja przeglądarki.
Ale dla stron bez fingerprintingu (większość publicznych API, starsze szablony CMS, wszystko chronione tylko limitami zapytań dla danego IP), pozostawienie flagi unblocker wyłączonej jest w porządku i pozwala zaoszczędzić kilka milisekund na negocjacjach. Używaj jej tam, gdzie jej potrzebujesz.
Dla zaawansowanych użytkowników
Kilka wzorców, które warto znać.
Połącz flagę unblocker z proxy rezydencjalnym, gdy cel sprawdza również reputację IP. Adresy IP z centrów danych i perfekcyjna sygnatura połączenia nadal podniosą alarm na numerach ASN na czarnej liście. Nasz endpoint proxy (/api/proxy) rotuje według domeny docelowej, więc dodanie flagi "proxy": "residential" do żądania zazwyczaj wystarcza.
Pomiń flagę unblocker przy odpytywaniu API JSON, które nie interesują się przeglądarkami. Dodatkowe nagłówki mogą faktycznie wyglądać podejrzanie dla API oczekującego klienta programistycznego, na przykład backendu odpytującego własny mikrosewis.
Jeśli strona ma antybotowe mechanizmy w JavaScript (interaktywne wyzwania Turnstile, rygorystyczny PerimeterX, Akamai Bot Manager z włączoną heurystyką), sama flaga unblocker nie wystarczy. Potrzebujesz endpointu przeglądarki, który wykonuje wyzwanie w pełnej przeglądarce. To inny produkt z innym cennikiem, opisaliśmy go w artykule Browser Tasks: How to Scrape JavaScript-Heavy Sites.
I możesz połączyć flagę unblocker z blokiem validate, aby odrzucać odpowiedzi zwracające technicznie kod 200, ale zawierające stronę wyzwania:
{
"url": "https://example.com/products",
"method": "GET",
"unblocker": true,
"validate": {
"data": { "fail": ["captcha", "Access Denied"] }
}
}
To zmienia ciche błędy w sklasyfikowane błędy, co ma znaczenie przy śledzeniu wskaźnika sukcesu na dashboard.
Co dalej
Nowa stabilna wersja przeglądarki pojawia się co cztery tygodnie. Aktualizujemy nasz stos, aby z nią współgrał. Nie musisz niczego zmieniać po swojej stronie: flaga unblocker: true nadal wskazuje na tę wersję przeglądarki, którą zweryfikowaliśmy od początku do końca.
Trudniejsza praca wciąż przed nami. Fingerprinting na poziomie HTTP/3 pojawia się już w zarządzanych systemach antybotowych, z transportem QUIC trudniej się zgrać niż ze starszym transportem, a migracja ze statycznych zestawów nagłówków w stronę w 100% dynamicznej emulacji już się zaczyna. Chronione witryny zaczęły sprawdzać kolejność ramek HTTP/2, a różnica między "biblioteką wyglądającą jak przeglądarka" a "przeglądarką" będzie się zmniejszać z obu stron. Napiszemy o tym, gdy to wprowadzimy.