Эта ошибка возникает, когда 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, эта строчка в логах перестанет появляться. А пока она всё ещё мелькает — теперь вы точно знаете, куда смотреть в первую очередь.

От Борис Маркович

Борис Маркович — головний редактор та засновник технологічного напряму на zhovta.ua. Має понад 18 років досвіду в IT-журналістиці та аналітиці. Спеціалізується на штучному інтелекті, українському стартап-екосистемі, кібербезпеці та цифровій трансформації бізнесу. Закінчив Київський політехнічний інститут за спеціальністю «комп’ютерні науки». Автор сотень глибоких матеріалів, спікер конференцій IT Arena та iForum. Його тексти відзначаються точністю, зрозумілістю та практичною користю. Борис вірить, що технології мають робити життя українців кращим і доступнішим.

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

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