← Назад в базу знаний

Google Search через IPv6 прокси: парсинг выдачи и обход капчи

Google Search через IPv6 прокси: парсинг выдачи и обход капчи

Google смотрит на IP-адрес раньше, чем на User-Agent. Это не догадка — это то, что видно по поведению редиректов и частоте капчи. Один и тот же запрос с одного IPv4-адреса даёт капчу на третьем-пятом обращении. С IPv6-подсети, где адрес меняется на каждый запрос, выдача отдаётся стабильно. Дальше — как это устроить без иллюзий.

Почему IPv6 меняет правила игры

IPv4-пул провайдеров давно выжжен. /24-подсеть, которую вы арендуете у VPS-хостинга, уже кто-то парсил до вас — Google это запомнил по ASN и репутации подсети. IPv6 работает иначе: провайдер выдаёт /64, а то и /48. Это 2^64 адресов. Даже если провайдер делит /48 между сотней клиентов, вам достаётся пространство, которое Google не видел в лицо.

Практическая разница в том, как Google считает «подозрительность». Для IPv4 он держит репутацию по /24 и по отдельному IP. Для IPv6 — по /64-префиксу. Если менять последние 64 бита (интерфейсный идентификатор), вы попадаете в один и тот же /64, и репутация префикса накапливается. Значит, ротация внутри /64 помогает слабо. Нужен /48 или хотя бы несколько /64.

Ещё момент: Google отдаёт разную выдачу для IPv6 и IPv4? Нет. Но он логирует, что запрос пришёл с IPv6, и это само по себе не триггер. Триггер — поведение: частота, отсутствие cookies, шаблонные заголовки.

Как выглядит капча: три сценария

Первый — `/sorry/index` с редиректом 302. Это классика: Google решает, что трафик автоматический, и отправляет на страницу «unusual traffic». Приходит HTML с формой и полем `captcha`. Иногда с `g-recaptcha`.

Второй — 429 без тела. Случается реже, обычно при жёстком флуде с одного /64. Заголовок `Retry-After` может отсутствовать, тогда пауза — на ваше усмотрение.

Третий — «тихая» деградация. Выдача приходит, но урезанная: 10 результатов вместо 20, нет блока «Похожие запросы», нет пагинации. Это хуже всего, потому что парсер не падает, а молча собирает мусор. Проверять надо не только статус-код, но и структуру HTML.

```bash

curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" \

-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \

"https://www.google.com/search?q=test&num=20"

```

Если в `redirect_url` видите `google.com/sorry` — капча. Если 200, но в теле нет `id="rso"` — тихая деградация.

Ротация адресов: как не спалиться на шаблоне

Простейший подход — брать новый адрес из /64 на каждый запрос. Работает, но недолго: Google видит, что все адреса из одного префикса, и начинает считать префикс. Второй подход — раскидывать запросы по нескольким /64 из /48. Тут уже нужно управлять пулом.

Схема, которая держится месяцами: N /64-префиксов, внутри каждого — M адресов, ротация по кругу с рандомизацией. Плюс пауза между запросами не меньше 2-3 секунд на один адрес. Не на один прокси — на один адрес. Если у вас 1000 адресов и вы шлёте 1000 запросов в секунду, каждый адрес получает один запрос — и это нормально по частоте, но подозрительно по синхронности. Рандомизируйте интервалы.

```python

import random, time, ipaddress

def gen_ipv6(prefix_48: str, used: set) -> str:

net = ipaddress.IPv6Network(prefix_48)

while True:

/64 выбираем случайно, хост-часть тоже

sub = random.randint(0, 65535)

host = random.getrandbits(64)

addr = net.network_address + (sub << 64) + host

s = str(addr)

if s not in used:

used.add(s)

return s

used = set()

for _ in range(5):

print(gen_ipv6("2001:db8:1234::/48", used))

time.sleep(random.uniform(1.5, 4.0))

```

Важно: адрес должен быть реально назначен на интерфейс или маршрутизирован через прокси. Просто сгенерировать строку и подставить в `curl --interface` не выйдет — ядро отбросит пакет, если адреса нет на интерфейсе. На Linux это делается через `ip -6 addr add` или через прокси-сервер, который сам управляет пулом.

Почему прокси, а не прямой IPv6 с VPS

Прямой IPv6 с VPS работает, пока вы не упрётесь в две вещи. Первая: провайдер VPS обычно даёт /64, а не /48. Ротация внутри /64 быстро сжигает префикс. Вторая: обратный DNS и ASN. Google видит, что адрес принадлежит хостингу, а не residential-провайдеру. Это не приговор, но добавляет веса к «подозрительности».

Прокси-пул с нормальным /48 и грамотной ротацией снимает обе проблемы. Плюс можно держать HTTP/2-соединения и переиспользовать TLS-сессии — это снижает нагрузку и выглядит естественнее. Пул вида lexic.ml как раз про это: IPv6-адреса с 2015 года, ротация по /64, стабильные TLS-фингерпринты. Для парсинга Google это удобно тем, что не нужно самому поднимать BGP и договариваться с RIR.

Но и с прокси есть грабли. Если прокси-провайдер отдаёт один и тот же TLS-фингерпринт на все адреса, Google связывает запросы по JA3. Проверяйте, что фингерпринт варьируется или хотя бы соответствует заявленному браузеру.

Заголовки и cookies: где чаще всего палятся

User-Agent — это первое, что все меняют, и последнее, что реально влияет. Google смотрит на консистентность: UA говорит Chrome 120 на Windows, а `Accept-Language` пустой, `Sec-CH-UA` отсутствует, порядок заголовков не тот. Это палево.

Минимальный набор для правдоподобного запроса:

```bash

curl -s "https://www.google.com/search?q=ipv6+proxy&num=20&hl=en" \

-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" \

-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8" \

-H "Accept-Language: en-US,en;q=0.9" \

-H "Sec-CH-UA: \"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Google Chrome\";v=\"120\"" \

-H "Sec-CH-UA-Mobile: ?0" \

-H "Sec-CH-UA-Platform: \"Windows\"" \

-H "Sec-Fetch-Dest: document" \

-H "Sec-Fetch-Mode: navigate" \

-H "Sec-Fetch-Site: none" \

-H "Sec-Fetch-User: ?1" \

-H "Upgrade-Insecure-Requests: 1" \

--compressed

```

Порядок заголовков в curl не гарантируется, но большинство HTTP-клиентов (requests, httpx) позволяют задать его явно. В Python `httpx` с `http2=True` даёт более правдоподобный TLS-отпечаток, чем `requests`.

Cookies — отдельная история. Свежая сессия без `NID`, `CONSENT`, `1P_JAR` выглядит как бот. Либо прогревайте сессию (заходите на google.com, соглашаетесь с cookies, потом ищете), либо используйте `CONSENT=YES+` в первом запросе. Второе работает не всегда — Google ужесточил проверку в 2023-м.

Парсинг выдачи: что реально нужно вытащить

Структура HTML Google меняется. Классы обфусцированы (`g`, `yuRUbf`, `LC20lb`), но стабильны месяцами. Ловить надо не классы, а семантику: ссылки внутри `#rso`, заголовки в `h3`, сниппеты в `div[data-sncf]`.

```python

from bs4 import BeautifulSoup

import httpx

def parse_google(html: str) -> list[dict]:

soup = BeautifulSoup(html, "lxml")

out = []

for block in soup.select("#rso > div"):

a = block.select_one("a[href^='http']")

h3 = block.select_one("h3")

if not a or not h3:

continue

out.append({

"title": h3.get_text(strip=True),

"url": a["href"],

"snippet": (block.select_one("div[data-sncf]") or block).get_text(" ", strip=True)[:300],

})

return out

with httpx.Client(http2=True, proxy="http://[2001:db8::1]:8080") as c:

r = c.get("https://www.google.com/search", params={"q": "ipv6 proxy", "num": 20})

if "/sorry/" in str(r.url):

raise RuntimeError("captcha")

results = parse_google(r.text)

print(len(results), results[0]["url"] if results else None)

```

Проверка на капчу — по финальному URL, а не по статусу. Google отдаёт 200 и на страницу `/sorry/`. Ещё маркер: наличие `form#captcha-form` или `div#recaptcha`.

Кейс: 429 при 50 rps с одного /64

Сервер на nginx 1.24, upstream — пул из 200 IPv6-адресов внутри одного /64. Скрипт на Python с `asyncio` шлёт 50 запросов в секунду. Через 12 минут — стена 429 на все адреса, `Retry-After` нет. Причина: все 200 адресов в одном /64, Google сложил их в один бакет репутации и сжёг префикс. Решение: переехали на /48, разбили на 16 /64 по 50 адресов, ротация между /64 с рандомным интервалом 1.5-4 секунды. 429 пропали, throughput упал до 30 rps, но стабильно. Цена — больше адресного пространства и сложнее управление пулом.

Кейс: тихая деградация на residential-прокси

Прокси-пул из residential IPv4, 500 адресов. Выдача приходит, статус 200. Парсер собирает 10 результатов вместо 20, пагинация отсутствует. Причина: Google урезает выдачу для «подозрительных» сессий без явной капчи. Диагностика — сравнение с эталоном: запрос с чистого браузера даёт 20 результатов и блок «Похожие», с прокси — 10 и пусто. Решение: добавили прогрев сессии (3 запроса к google.com без параметров, пауза 10 секунд, потом поиск), плюс `CONSENT` cookie. Восстановилось до 18-20 результатов. Вывод: проверять не только код ответа, но и количество блоков `#rso > div`.

Кейс: JA3-фингерпринт спалил пул

Прокси-провайдер отдавал один и тот же TLS-фингерпринт (JA3) на все IPv6-адреса. Google связал 5000 запросов с разных IP в одну сессию по отпечатку и выдал капчу на весь пул за час. Причина: JA3 считался по TLS ClientHello, а он был идентичен — Python `requests` с дефолтным OpenSSL. Решение: перешли на `httpx` с `http2=True` и `curl_cffi` с `impersonate="chrome120"`. Фингерпринт стал соответствовать заявленному UA. Капча ушла, но появилась новая проблема — `curl_cffi` медленнее в 2.5 раза на запрос. Компромисс: `curl_cffi` для поиска, `httpx` для остального.

Таблица: сравнение подходов

| Подход | Пул адресов | Риск капчи | Throughput | Сложность |

|---|---|---|---|---|

| Прямой IPv6 с VPS /64 | 2^64 в одном /64 | Высокий через 1-2 часа | 10-20 rps | Низкая |

| Прокси-пул /48, ротация по /64 | 65536 /64 | Средний, держится неделями | 30-50 rps | Средняя |

| Residential IPv4 | 500-5000 IP | Средний, зависит от прогрева | 5-15 rps | Высокая (цена) |

| Datacenter IPv4 /24 | 256 IP | Высокий, выжжены | 20-40 rps | Низкая |

Цифры — из личной практики на запросах `num=20`, `hl=en`, без пагинации. Ваш пробег будет отличаться от нагрузки, гео и времени суток.

Пагинация и `start`: где ломается логика

Google отдаёт по 10 результатов на страницу по умолчанию, `num=20` работает не всегда (иногда игнорируется). Пагинация через `&start=10`, `&start=20`. Лимит — примерно 100 результатов, дальше Google режет. Каждая страница — отдельный запрос, отдельный адрес, отдельная пауза. Если гнать пагинацию с одного адреса подряд, капча прилетает на третьей странице.

Проверяйте, что `start` реально сработал: в HTML должен быть блок с результатами, отличными от предыдущей страницы. Иногда Google возвращает ту же выдачу — это маркер деградации.

Мониторинг: что логировать

Логируйте на каждый запрос: IP, статус, финальный URL, количество блоков `#rso > div`, наличие `captcha-form`, время ответа. Агрегируйте по /64-префиксу: если один префикс даёт капчу чаще 5% — выводите из ротации на час. Это спасает пул от каскадного сжигания.

Метрика, которая реально предсказывает капчу: доля запросов без `NID` cookie. Если она растёт — сессии не прогреваются, жди беды. Вторая — медианное время ответа: при деградации Google начинает отвечать медленнее (300-500 мс вместо 150-200), это ранний сигнал.

Что не работает

Смена User-Agent без смены TLS-фингерпринта — палево. Ротация внутри одного /64 — палево. Запросы каждые 100 мс с одного адреса — палево. Прокси-пул без прогрева cookies — палево. Всё это проверяется на раз, и Google проверяет.

Что работает: несколько /64, рандомные интервалы, консистентные заголовки, прогретые сессии, мониторинг по префиксу. Скучно, но стабильно. Чудес нет — есть инженерия.

✔️Купить прокси