Лучшие практики гео-таргетированного скрейпинга SERP: uule, gl, hl и прокси

Практическое руководство для SEO-инженеров: как собирать локализованные SERP Google с точностью до города, конструировать параметр uule, синхронизировать gl/hl с IP-географией и ротировать резидентные прокси через ProxyHat.

Geo-Targeted SERP Scraping Best Practices for Local SEO Data
В этой статье

Лучшие практики гео-таргетированного скрейпинга SERP начинаются с одного простого факта: один и тот же поисковый запрос в Google возвращает разные результаты в зависимости от того, откуда он отправлен. Запрос «pizza near me» из Нью-Йорка и из Берлина даст принципиально разные органические результаты, локальные пакеты (Local Pack) и карты. Если вы строите систему rank-tracking для клиентов в нескольких городах, таргетинга на уровне страны недостаточно — вам нужна точность до города, а иногда и до района.

Почему один запрос даёт разные результаты по локации

Google определяет релевантность результатов на основе множества сигналов, среди которых геолокация пользователя — один из ключевых. Согласно документации Google Search, поисковая система учитывает IP-адрес, историю местоположений, явные параметры URL и настройки аккаунта. Для SEO-инженеров это означает: нельзя собрать «каноничный» SERP без явного указания локации.

Таргетинг только на уровне страны (через параметр gl=us) скрывает критические различия. Запрос «plumber» в Чикаго и в Майами покажет разных локальных подрядчиков, разные Local Pack и даже разные органические результаты, потому что Google применяет локальный алгоритм даже для запросов без явного гео-модификатора. По данным BrightLocal, 76% пользователей, ищущих локальный бизнес, просматривают результаты с привязкой к городу — это означает, что ваши клиенты видят именно локальный SERP, а не национальный.

Уровни гео-точности

УровеньПараметрТочностьКогда использовать
СтранаglНациональный SERPБренд-трекинг, общий рейтинг
Язык интерфейсаhlТекст интерфейсаМультиязычные рынки (Канада, Швейцария)
Домен Googlegoogle_domainРегональный доменgoogle.de, google.co.jp, google.com.br
Город/районuuleТочный городLocal SEO, rank-tracking по городам

Параметры локализации SERP: gl, hl, google_domain, lr, uule, pws

Google принимает несколько параметров URL для управления локализацией. Вот полный набор, который нужно использовать в продакшене:

  • gl — код страны (ISO 3166-1 alpha-2), например gl=us, gl=de, gl=jp. Влияет на национальную версию SERP.
  • hl — язык интерфейса, например hl=en, hl=de, hl=ja. Не путать с языком результатов — это язык кнопок и подсказок.
  • google_domain — домен поисковика, например google.com, google.de, google.co.jp. Должен соответствовать gl.
  • lr — ограничение языка результатов (lang_en, lang_de, lang_ja). Полезно для мультиязычных стран.
  • uule — закодированная каноническая локация (город/район). Самый мощный параметр для локального SEO.
  • pws=0 — отключает персонализацию. Критично для получения воспроизводимого базового SERP.

Конструкция параметра uule

Параметр uule (User-Location Lat-Enc) — это base64-кодированная строка с каноническим названием места. Формат строго фиксирован:

uule = "w+CAIQICI" + base64(canonical_place_name)

Где w+CAIQICI — фиксированный префикс (8 символов), за которым следует base64-представление канонического названия города в формате Google. Например, для Нью-Йорка каноническое имя — Brooklyn, New York, NY, для Берлина — Berlin, Germany. Длина base64-строки добавляется как однобайтовый символ перед base64-полезной нагрузкой.

Вот Python-функция для генерации uule:

import base64

def build_uule(place_name: str) -> str:
    """Конструирует параметр uule для Google SERP.
    
    Args:
        place_name: Каноническое название места,
                    например 'Brooklyn, New York, NY' или 'Berlin, Germany'.
    Returns:
        Строка uule, готовая для URL-параметра.
    """
    prefix = "w+CAIQICI"
    encoded = base64.b64encode(place_name.encode("utf-8")).decode("ascii")
    # Длина base64-строки как однобайтовый символ
    length_byte = chr(len(encoded))
    return prefix + length_byte + encoded

# Примеры
uule_nyc = build_uule("Brooklyn, New York, NY")
uule_berlin = build_uule("Berlin, Germany")
uule_tokyo = build_uule("Tokyo, Tokyo, Japan")

print(f"NYC:  {uule_nyc}")
print(f"Berlin: {uule_berlin}")
print(f"Tokyo: {uule_tokyo}")

Всегда добавляйте pws=0 к запросу, чтобы отключить персонализацию на основе истории поиска. Без этого параметра результаты будут непредсказуемо варьироваться между запусками.

Согласованность параметров и IP-географии

Критическое правило, которое часто упускают: Google кросс-проверяет параметры локализации с IP-адресом запроса. Если вы отправляете gl=us&uule=...New York с IP-адреса из Франкфурта, Google может:

  • Проигнорировать uule и показать немецкие результаты.
  • Показать смешанный SERP с элементами обеих локаций.
  • Пометить запрос как подозрительный и вернуть CAPTCHA.

Поэтому запросы должны маршрутизироваться через резидентные прокси из той же локации, что и целевые параметры. ProxyHat поддерживает таргетинг по стране и городу через имя пользователя:

# Резидентный прокси для США, Нью-Йорк
http://user-country-US-city-newyork:pass@gate.proxyhat.com:8080

# Резидентный прокси для Германии, Берлин  
http://user-country-DE-city-berlin:pass@gate.proxyhat.com:8080

# Резидентный прокси для Японии, Токио
http://user-country-JP-city-tokyo:pass@gate.proxyhat.com:8080

Подробности по доступным локациям — на странице локаций ProxyHat.

Пример 1: Сбор SERP с uule и ротацией резидентных IP

Ниже — полный пример на Python с использованием curl_cffi для имперсонализации TLS-отпечатка Chrome и ProxyHat-прокси для гео-таргетинга:

import base64
import time
import logging
from curl_cffi import requests as cffi_requests
from urllib.parse import urlencode, quote_plus

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger("serp_scraper")

# --- Конфигурация локаций ---
LOCALES = [
    {
        "label": "NYC",
        "gl": "us", "hl": "en", "google_domain": "google.com",
        "uule_place": "Brooklyn, New York, NY",
        "proxy_user": "user-country-US-city-newyork",
        "proxy_pass": "YOUR_PASSWORD",
    },
    {
        "label": "Berlin",
        "gl": "de", "hl": "de", "google_domain": "google.de",
        "uule_place": "Berlin, Germany",
        "proxy_user": "user-country-DE-city-berlin",
        "proxy_pass": "YOUR_PASSWORD",
    },
    {
        "label": "Tokyo",
        "gl": "jp", "hl": "ja", "google_domain": "google.co.jp",
        "uule_place": "Tokyo, Tokyo, Japan",
        "proxy_user": "user-country-JP-city-tokyo",
        "proxy_pass": "YOUR_PASSWORD",
    },
]

PROXY_GATEWAY = "gate.proxyhat.com"
PROXY_PORT = 8080


def build_uule(place_name: str) -> str:
    """Конструирует uule: фиксированный префикс + length byte + base64."""
    prefix = "w+CAIQICI"
    encoded = base64.b64encode(place_name.encode("utf-8")).decode("ascii")
    length_byte = chr(len(encoded))
    return prefix + length_byte + encoded


def build_serp_url(query: str, locale: dict) -> str:
    """Собирает URL Google SERP с параметрами локализации."""
    uule = build_uule(locale["uule_place"])
    params = {
        "q": query,
        "gl": locale["gl"],
        "hl": locale["hl"],
        "google_domain": locale["google_domain"],
        "uule": uule,
        "pws": "0",
        "num": "20",
        "output": "serp",
    }
    base = f"https://www.{locale['google_domain']}/search"
    return f"{base}?{urlencode(params)}"


def fetch_serp(query: str, locale: dict) -> str:
    """Отправляет запрос SERP через резидентный прокси ProxyHat.
    Использует curl_cffi для имперсонализации TLS-отпечатка Chrome.
    """
    proxy_url = (
        f"http://{locale['proxy_user']}:{locale['proxy_pass']}"
        f"@{PROXY_GATEWAY}:{PROXY_PORT}"
    )
    serp_url = build_serp_url(query, locale)

    logger.info(f"[{locale['label']}] Fetching: {query}")

    try:
        response = cffi_requests.get(
            serp_url,
            proxies={"http": proxy_url, "https": proxy_url},
            impersonate="chrome120",
            timeout=30,
            allow_redirects=True,
        )
        response.raise_for_status()
        logger.info(f"[{locale['label']}] Status: {response.status_code}, len={len(response.text)}")
        return response.text
    except Exception as e:
        logger.error(f"[{locale['label']}] Error: {e}")
        raise


# --- Запуск ---
if __name__ == "__main__":
    query = "best coffee shop"
    for locale in LOCALES:
        html = fetch_serp(query, locale)
        # Сохраняем для парсинга
        filename = f"serp_{locale['label']}_{int(time.time())}.html"
        with open(filename, "w", encoding="utf-8") as f:
            f.write(html)
        logger.info(f"Saved: {filename}")
        time.sleep(2)  # Вежливая задержка между локациями

Тот же запрос через curl для быстрой отладки:

# US / New York через резидентный прокси ProxyHat
curl -s \
  --proxy "http://user-country-US-city-newyork:YOUR_PASSWORD@gate.proxyhat.com:8080" \
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" \
  "https://www.google.com/search?q=best+coffee+shop&gl=us&hl=en&pws=0&num=20&uule=w+CAIQICIRQnJvb2tseW4sIE5ldyBZb3JrLCBOWQ==" \
  -o serp_nyc.html

Пример 2: Парсинг органических результатов и Local Pack с selectolax

После получения HTML нужно извлечь органические результаты и Local Pack. Используем selectolax — быстрый HTML-парсер на основе Lexbor:

from selectolax.parser import HTMLParser
import json
import re


def parse_organic_results(html: str) -> list[dict]:
    """Извлекает органические результаты из HTML SERP."""
    tree = HTMLParser(html)
    results = []

    # Google использует div.g для органических результатов
    for div in tree.css("div.g"):
        title_tag = div.css_first("h3")
        link_tag = div.css_first("a[href]")
        snippet_tag = div.css_first("div[data-sncf], .VwiC3b, span.aCOpRe")

        if not title_tag or not link_tag:
            continue

        title = title_tag.text(strip=True)
        url = link_tag.attributes.get("href", "")
        snippet = snippet_tag.text(strip=True) if snippet_tag else ""

        # Фильтруем внутренние ссылки Google
        if url.startswith("http") and "google.com" not in url.split("/")[2]:
            results.append({
                "position": len(results) + 1,
                "title": title,
                "url": url,
                "snippet": snippet,
            })

    return results


def parse_local_pack(html: str) -> list[dict]:
    """Извлекает Local Pack (3-pack) из SERP."""
    tree = HTMLParser(html)
    local_results = []

    # Local Pack обычно в div с role="main" или в .local-packed
    for item in tree.css("div.eT1oC, div[jsname] > div.g"):
        name_tag = item.css_first("span.Jr5vfb, .dbg0pd, .OSrXXb")
        rating_tag = item.css_first("span.MHleUd, span[aria-label*=rating]")
        address_tag = item.css_first("span.LrzXKn, .text")

        if not name_tag:
            continue

        name = name_tag.text(strip=True)
        rating = rating_tag.text(strip=True) if rating_tag else "N/A"
        address = address_tag.text(strip=True) if address_tag else ""

        local_results.append({
            "name": name,
            "rating": rating,
            "address": address,
        })

    return local_results


def parse_serp(html: str, locale_label: str, query: str) -> dict:
    """Полный парсинг SERP: органика + Local Pack."""
    organic = parse_organic_results(html)
    local_pack = parse_local_pack(html)

    return {
        "query": query,
        "locale": locale_label,
        "organic_count": len(organic),
        "local_pack_count": len(local_pack),
        "organic": organic[:10],  # Топ-10
        "local_pack": local_pack,
    }


# --- Использование ---
if __name__ == "__main__":
    with open("serp_NYC_1700000000.html", "r", encoding="utf-8") as f:
        html = f.read()

    data = parse_serp(html, "NYC", "best coffee shop")
    print(json.dumps(data, indent=2, ensure_ascii=False))

Пример 3: Sticky-сессии для многостраничного сбора SERP

При сборе нескольких страниц SERP (page=1, page=2, ...) важно сохранять один IP-адрес в рамках сессии. Если IP меняется между страницами, Google может показать разные результаты из-за смены геолокации. ProxyHat поддерживает sticky-сессии через флаг session-XXX в имени пользователя:

import base64
import time
import logging
from curl_cffi import requests as cffi_requests
from urllib.parse import urlencode

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("multi_page_serp")

def build_uule(place_name: str) -> str:
    prefix = "w+CAIQICI"
    encoded = base64.b64encode(place_name.encode("utf-8")).decode("ascii")
    length_byte = chr(len(encoded))
    return prefix + length_byte + encoded


def fetch_serp_page(
    query: str,
    page: int,
    locale: dict,
    session_id: str,
) -> str:
    """Запрашивает конкретную страницу SERP с sticky-сессией ProxyHat.
    
    Sticky-сессия сохраняет один IP для всех страниц,
    обеспечивая консистентность геолокации.
    """
    # Sticky-сессия: session-ID в имени пользователя
    proxy_user = f"{locale['proxy_user']}-session-{session_id}"
    proxy_url = (
        f"http://{proxy_user}:{locale['proxy_pass']}"
        f"@gate.proxyhat.com:8080"
    )

    uule = build_uule(locale["uule_place"])
    start = (page - 1) * 10  # Google использует start= для пагинации

    params = {
        "q": query,
        "gl": locale["gl"],
        "hl": locale["hl"],
        "uule": uule,
        "pws": "0",
        "num": "10",
        "start": str(start),
    }
    serp_url = f"https://www.{locale['google_domain']}/search?{urlencode(params)}"

    logger.info(f"[{locale['label']}] Page {page}, session={session_id}")

    response = cffi_requests.get(
        serp_url,
        proxies={"http": proxy_url, "https": proxy_url},
        impersonate="chrome120",
        timeout=30,
    )
    response.raise_for_status()
    return response.text


def scrape_all_pages(
    query: str,
    locale: dict,
    max_pages: int = 3,
) -> list[str]:
    """Собирает несколько страниц SERP с одной sticky-сессией."""
    session_id = f"loc{locale['label']}{int(time.time())}"
    pages_html = []

    for page in range(1, max_pages + 1):
        try:
            html = fetch_serp_page(query, page, locale, session_id)
            pages_html.append(html)
            logger.info(f"[{locale['label']}] Page {page} OK, len={len(html)}")
        except Exception as e:
            logger.error(f"[{locale['label']}] Page {page} failed: {e}")
            break

        if page < max_pages:
            time.sleep(2.5)  # Задержка между страницами

    return pages_html


# --- Запуск ---
if __name__ == "__main__":
    locale = {
        "label": "NYC",
        "gl": "us", "hl": "en", "google_domain": "google.com",
        "uule_place": "Brooklyn, New York, NY",
        "proxy_user": "user-country-US-city-newyork",
        "proxy_pass": "YOUR_PASSWORD",
    }

    all_pages = scrape_all_pages("plumber", locale, max_pages=3)
    logger.info(f"Collected {len(all_pages)} pages for {locale['label']}")

CAPTCHA, 429 и экспоненциальный backoff

Даже с резидентными прокси Google может вернуть CAPTCHA или HTTP 429 при интенсивном скрейпинге. Вот стратегия обработки с экспоненциальным backoff, повторными попытками и переключением прокси:

import time
import random
import logging
from curl_cffi import requests as cffi_requests

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("serp_retry")

# Словарь пулов прокси по странам
PROXY_POOLS = {
    "US": [
        "http://user-country-US-city-newyork-session-s1:PASS@gate.proxyhat.com:8080",
        "http://user-country-US-city-chicago-session-s2:PASS@gate.proxyhat.com:8080",
        "http://user-country-US-city-miami-session-s3:PASS@gate.proxyhat.com:8080",
    ],
    "DE": [
        "http://user-country-DE-city-berlin-session-s1:PASS@gate.proxyhat.com:8080",
        "http://user-country-DE-city-munich-session-s2:PASS@gate.proxyhat.com:8080",
    ],
}

MAX_RETRIES = 5
BASE_DELAY = 2.0  # секунд


def fetch_with_retry(url: str, country: str, impersonate="chrome120") -> str | None:
    """Запрос с экспоненциальным backoff и ротацией прокси.
    
    - При 429/503 ждёт и повторяет с новым прокси из пула.
    - При CAPTCHA (302 на sorry/index) меняет прокси и повторяет.
    - При 200 возвращает HTML.
    """
    pool = PROXY_POOLS.get(country, [])
    if not pool:
        raise ValueError(f"No proxy pool for country: {country}")

    for attempt in range(1, MAX_RETRIES + 1):
        proxy_url = random.choice(pool)
        try:
            response = cffi_requests.get(
                url,
                proxies={"http": proxy_url, "https": proxy_url},
                impersonate=impersonate,
                timeout=30,
                allow_redirects=False,  # Не следуем за CAPTCHA-редиректами
            )

            # Проверяем CAPTCHA-редирект
            if response.status_code == 302 and "sorry" in response.headers.get("location", ""):
                logger.warning(f"Attempt {attempt}: CAPTCHA redirect detected")
                delay = BASE_DELAY * (2 ** (attempt - 1)) + random.uniform(0, 1)
                time.sleep(delay)
                continue

            # Rate limiting
            if response.status_code in (429, 503):
                delay = BASE_DELAY * (2 ** (attempt - 1)) + random.uniform(0, 1)
                logger.warning(f"Attempt {attempt}: HTTP {response.status_code}, retry in {delay:.1f}s")
                time.sleep(delay)
                continue

            response.raise_for_status()
            logger.info(f"Attempt {attempt}: OK, len={len(response.text)}")
            return response.text

        except Exception as e:
            logger.error(f"Attempt {attempt}: {e}")
            delay = BASE_DELAY * (2 ** (attempt - 1))
            time.sleep(delay)

    logger.error(f"All {MAX_RETRIES} attempts failed for {url}")
    return None


# --- Использование ---
if __name__ == "__main__":
    serp_url = (
        "https://www.google.com/search?q=plumber&gl=us&hl=en&pws=0&num=10"
        "&uule=w+CAIQICIRQnJvb2tseW4sIE5ldyBZb3JrLCBOWQ=="
    )
    html = fetch_with_retry(serp_url, "US")
    if html:
        print(f"Success! HTML length: {len(html)}")
    else:
        print("Failed after all retries")

Советы по продакшен-надёжности

  • Пер-страновые пулы прокси: держите минимум 3-5 IP на каждую локацию. Это позволяет ротировать при CAPTCHA без потери гео-точности.
  • Задержки 1-3 секунды между запросами к одному домену. Случайный джиттер снижает вероятность rate-limit.
  • Логирование метрик: записывайте success rate, latency, код ответа для каждого прокси. ProxyHat dashboard показывает статистику по сессиям.
  • Circuit breaker: если пул прокси для страны даёт >30% ошибок за 5 минут, ставьте его на паузу и переключайтесь на резервный.
  • Мониторинг CAPTCHA: если доля CAPTCHA превышает 5%, снижайте частоту запросов на 50%.

Сравнение типов прокси для SERP-скрейпинга

Тип проксиSuccess rate (Google)Гео-точностьСтоимостьРекомендация
Дата-центровые~40-60%СтранаНизкаяНе рекомендуется для Google
Резидентные~90-95%Страна + ГородСредняяОптимальный выбор
Мобильные~95-98%СтранаВысокаяДля критичных задач

ProxyHat предоставляет все три типа. Для гео-таргетированного SERP-скрейпинга рекомендуется резидентный план с поддержкой city-level таргетинга. Подробнее о применении — в разделе SERP tracking и web scraping.

Юридические и этические ограничения

Сбор публичных данных из SERP Google находится в серой правовой зоне. robots.txt Google запрещает автоматический доступ к /search. Технически это не имеет силы закона, но Google ToS прямо запрещают автоматизированные запросы. В деле hiQ Labs v. LinkedIn (9th Circuit, 2022) суд постановил, что сбор публично доступных данных не нарушает CFAA, но это не освобождает от ответственности за нарушение ToS конкретной платформы.

Практические рекомендации:

  • Соблюдайте разумные лимиты частоты запросов (не более 1 req/sec на IP).
  • Не собирайте персональные данные без правового основания (GDPR/CCPA).
  • Если используете данные коммерчески, рассмотрите официальное API — Google Custom Search API (100 запросов/день бесплатно, далее $5/1000 запросов).
  • Храните собранные данные не дольше, чем необходимо для бизнес-задачи.

Полная документация по настройке прокси доступна на docs.proxyhat.com.

Ключевые выводы

Гео-таргетированный скрейпинг SERP требует согласованности трёх уровней: параметров URL (gl/hl/uule), IP-географии (прокси) и TLS-отпечатка (имперсонализация браузера). Без согласованности любого из уровней результаты будут искажены.

  • uule — ключевой параметр для локального SEO. Без него вы получаете национальный SERP, а не городской. Всегда добавляйте pws=0 для воспроизводимости.
  • Резидентные прокси обязательны для Google SERP. Дата-центровые IP блокируются в 40-60% случаев. ProxyHat резидентные прокси через gate.proxyhat.com:8080 с city-level таргетингом обеспечивают ~90-95% success rate.
  • Sticky-сессии через флаг session-XXX сохраняют IP между страницами, что критично для консистентности многостраничных SERP.
  • Экспоненциальный backoff с ротацией прокси — минимальный набор для продакшена. Circuit breaker и пер-страновые пулы повышают надёжность до уровня SaaS.
  • Соблюдайте ToS: сбор SERP нарушает условия Google. Оценивайте риски и рассмотрите официальное API для критичных задач.

FAQ

Что такое гео-таргетированный скрейпинг SERP?

Это сбор результатов поиска Google с привязкой к конкретной локации — стране, региону или городу. Для точного гео-таргетинга используют параметры gl, hl, google_domain и uule, а запросы маршрутизируют через резидентные прокси из той же локации, чтобы IP-география совпадала с целевым рынком.

Почему гео-таргетированный скрейпинг важен для пользователей прокси?

Google возвращает разные результаты в зависимости от IP-адреса, языка интерфейса и явных параметров локализации. Если IP-география не совпадает с параметром gl или uule, Google может проигнорировать их или показать смешанные результаты. Резидентные прокси из нужной локации обеспечивают согласованность и снижают риск блокировок.

Какой тип прокси лучше всего подходит для гео-таргетированного скрейпинга SERP?

Резидентные прокси — оптимальный выбор. Они используют IP-адреса реальных ISP, что делает их неотличимыми от обычных пользователей. Мобильные прокси подходят для высокой анонимности, но дороже. Дата-центровые прокси часто блокируются Google. ProxyHat предоставляет резидентные прокси с таргетингом по стране и городу через gate.proxyhat.com:8080.

Как избежать блокировок при гео-таргетированном скрейпинге SERP?

Используйте ротацию IP между запросами, задержки 1-3 секунды, экспоненциальный backoff при 429/503, имперсонализацию браузера (TLS fingerprint Chrome), согласованность параметров gl/hl/uule с IP-географией, и уважайте robots.txt. Sticky-сессии помогают для многостраничных запросов, сохраняя один IP.

Часто задаваемые вопросы

Что такое гео-таргетированный скрейпинг SERP?

Это сбор результатов поиска Google с привязкой к конкретной локации — стране, региону или городу. Для точного гео-таргетинга используют параметры gl, hl, google_domain и uule, а запросы маршрутизируют через резидентные прокси из той же локации, чтобы IP-география совпадала с целевым рынком.

Почему гео-таргетированный скрейпинг важен для пользователей прокси?

Google возвращает разные результаты в зависимости от IP-адреса, языка интерфейса и явных параметров локализации. Если IP-география не совпадает с параметром gl или uule, Google может проигнорировать их или показать смешанные результаты. Резидентные прокси из нужной локации обеспечивают согласованность и снижают риск блокировок.

Какой тип прокси лучше всего подходит для гео-таргетированного скрейпинга SERP?

Резидентные прокси — оптимальный выбор. Они используют IP-адреса реальных ISP, что делает их неотличимыми от обычных пользователей. Мобильные прокси подходят для высокой анонимности, но дороже. Дата-центровые прокси часто блокируются Google. ProxyHat предоставляет резидентные прокси с таргетингом по стране и городу через gate.proxyhat.com:8080.

Как избежать блокировок при гео-таргетированном скрейпинге SERP?

Используйте ротацию IP между запросами, задержки между запросами (1-3 секунды), экспоненциальный backoff при 429/503, имперсонализацию браузера (TLS fingerprint Chrome), согласованность параметров gl/hl/uule с IP-географией, и уважайте robots.txt. Sticky-сессии помогают для многостраничных запросов, сохраняя один IP.

Готовы начать?

Резидентные, ISP и мобильные прокси в 148+ странах. Создайте бесплатный аккаунт.

Создать бесплатный аккаунт
← Вернуться в Блог