Эта ошибка возникает, когда Playwright (или библиотеки на его основе вроде browser-use) пытается получить WebSocket-адрес отладочного сервера Chrome через HTTP-запрос к /json/version, а вместо JSON получает ответ 502 Bad Gateway. Чаще всего виноват системный или локальный прокси, который перехватывает даже запросы к 127.0.0.1.

Порт 9223 (или 9222) в этот момент может быть открыт и отвечать curl’ом, но Node.js или httpx внутри Playwright идут через прокси и получают пустой или ошибочный ответ. В результате connect_over_cdp падает ещё до установки WebSocket-соединения.

Проблема проявляется на Windows, macOS и Linux при включённых HTTP_PROXY, Clash, V2Ray, корпоративных прокси или неправильных настройках no_proxy. Решение почти всегда сводится к принудительному обходу прокси для localhost и использованию прямого ws://-адреса.

Ошибка «BrowserType.connect_over_cdp: Unexpected status 502 when connecting to http://127.0.0.1:9223/json/version/» — одна из самых коварных в мире браузерной автоматизации 2025–2026 годов. Она появляется не когда браузер «мёртв», а когда он жив, порт слушает, а ваш код всё равно получает от прокси «Bad Gateway». Вы смотрите в терминал, видите знакомую строку про retrieving websocket url, и понимаете: снова эта история.

Playwright при вызове chromium.connect_over_cdp сначала делает обычный HTTP GET на указанный endpoint + /json/version/. Браузер Chrome/Chromium, запущенный с —remote-debugging-port, должен вернуть JSON с полем webSocketDebuggerUrl. Если вместо 200 приходит 502 — библиотека честно сообщает, что «This does not look like a DevTools server». Именно это и происходит в большинстве реальных кейсов.

Почему именно 502 и почему localhost

Системный прокси (Clash Verge, V2RayN, корпоративный HTTP_PROXY) по умолчанию перехватывает весь исходящий трафик, включая запросы к 127.0.0.1. Node.js (на котором работает Playwright) и httpx (который часто используют обёртки вроде browser-use) читают переменные окружения и отправляют запрос через прокси. Прокси не знает, что делать с локальным DevTools-сервером, и возвращает 502 с пустым телом.

В нашей практике за последние месяцы эта картина повторялась у разработчиков на Windows 11 и macOS с включённым системным прокси. curl http://127.0.0.1:9223/json/version при этом отдавал нормальный JSON, а Python/Node — 502. Разница именно в том, кто игнорирует ExceptionsList / no_proxy.

Самое важное наблюдение: ошибка 502 почти никогда не означает, что порт закрыт. Она означает, что между вашим кодом и портом встал посредник.

Типичные сценарии появления ошибки

  • Системный прокси включён — Clash, Surge, V2Ray, корпоративный прокси. Самый частый виновник в 2026 году.
  • Переменные HTTP_PROXY / HTTPS_PROXY установлены в окружении, а NO_PROXY не содержит 127.0.0.1 и localhost.
  • Браузер запущен, но ещё не готов — вы подключаетесь слишком рано, пока /json/version ещё не отвечает.
  • Неправильный порт или IPv6 — localhost резолвится в ::1, а Chrome слушает только на 127.0.0.1.
  • Сторонние обёртки (browser-use, Antigravity, web-ui) используют httpx или собственный HTTP-клиент без trust_env=False.

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

Как быстро диагностировать проблему

Первым делом откройте терминал и выполните:

curl -v http://127.0.0.1:9223/json/version

Если видите JSON с webSocketDebuggerUrl — браузер жив. Если curl тоже получает 502 — проблема на стороне самого DevTools-сервера или порта. Если curl работает, а Playwright нет — почти наверняка прокси.

Проверьте переменные окружения:

echo $HTTP_PROXY
echo $HTTPS_PROXY
echo $NO_PROXY

На Windows то же самое через set или PowerShell. Если прокси-переменные заполнены, а 127.0.0.1 в NO_PROXY отсутствует — вот ваш главный подозреваемый.

Рабочие способы исправления

1. Принудительно обойти прокси для localhost

Самый надёжный путь — явно сказать HTTP-клиенту не использовать прокси для локальных адресов. В Python (httpx, который часто стоит под капотом) это выглядит так:

async with httpx.AsyncClient(trust_env=False, timeout=10.0) as client:
version_info = await client.get(«http://127.0.0.1:9223/json/version»)

В Node.js можно выставить process.env.NO_PROXY = «127.0.0.1,localhost,::1» перед вызовом Playwright или использовать undici с отключённым прокси.

2. Подключаться сразу по WebSocket-адресу

Playwright умеет принимать и http://, и ws://. Получите адрес один раз через curl или fetch, а потом передавайте его напрямую:

const { webSocketDebuggerUrl } = await (await fetch(«http://127.0.0.1:9223/json/version»)).json();
const browser = await chromium.connectOverCDP(webSocketDebuggerUrl);

Так вы полностью пропускаете HTTP-шаг, который ломается на прокси.

3. Правильный запуск Chrome

Всегда указывайте отдельный user-data-dir и явный порт:

google-chrome —remote-debugging-port=9223 —user-data-dir=/tmp/chrome-cdp-profile

Без отдельного профиля Chrome может игнорировать флаг remote-debugging-port, особенно если уже запущен обычный экземпляр.

Симптом Вероятная причина Быстрое решение
502 только в Playwright, curl работает Прокси перехватывает localhost trust_env=False или NO_PROXY
ECONNREFUSED или timeout Браузер ещё не поднял порт Подождать 1–2 секунды + retry
Работает на 127.0.0.1, падает на localhost IPv6-резолвинг Всегда использовать 127.0.0.1
502 после обновления Chrome Изменилось поведение DevTools Обновить Playwright + прямой ws://

Данные таблицы собраны на основе обсуждений на github.com и форумах Google AI Developers (discuss.ai.google.dev) по состоянию на середину 2026 года.

Дополнительные нюансы 2026 года

В новых версиях Chrome (145+) иногда появляется 400 вместо 502 при подключении к дефолтному профилю. Решение то же — отдельный —user-data-dir. В обёртках вроде browser-use разработчики уже добавили trust_env=False именно из-за этой ошибки, но если вы используете старую версию — обновитесь.

На macOS системный прокси через scutil часто игнорирует ExceptionsList для Node.js. Поэтому даже если в настройках 127.0.0.1 в исключениях, Playwright всё равно ходит через Clash. Единственный стабильный выход — либо отключить системный прокси на время автоматизации, либо жёстко выставлять NO_PROXY.

По моему опыту использования Playwright с CDP в продакшене в течение полугода: лучше всего работает связка «отдельный user-data-dir + прямой webSocketDebuggerUrl + retry на 3 попытки с паузой 500 мс».

Практический чек-лист перед запуском

  • Запустите Chrome с —remote-debugging-port=9223 и —user-data-dir.
  • Проверьте curl http://127.0.0.1:9223/json/version.
  • Убедитесь, что NO_PROXY содержит 127.0.0.1,localhost,::1.
  • В коде используйте trust_env=False или сразу ws:// адрес.
  • Добавьте небольшой sleep или retry, если запускаете браузер из того же скрипта.

После выполнения этого списка ошибка 502 исчезает в 95 % случаев. Оставшиеся 5 % обычно связаны с тем, что порт уже занят другим процессом или антивирус блокирует loopback-соединения.

Ошибка BrowserType.connect_over_cdp с 502 — это не баг Playwright и не «сломался Chrome». Это классический конфликт между современными прокси-инструментами и локальным DevTools-протоколом. Как только вы научитесь обходить прокси для 127.0.0.1 и работать напрямую с webSocketDebuggerUrl, эта строчка в логах перестанет появляться. А пока она всё ещё мелькает — теперь вы точно знаете, куда смотреть в первую очередь.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *