Ця помилка виникає, коли 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 працюєПроксі перехоплює localhosttrust_env=False або NO_PROXY
ECONNREFUSED або timeoutБраузер ще не підняв портЗачекати 1–2 секунди + retry
Працює на 127.0.0.1, падає на localhostIPv6-резолвингЗавжди використовувати 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, цей рядок у логах перестане з’являтися. А поки він усе ще мелькає — тепер ви точно знаєте, куди дивитися насамперед.

Leave a Reply

Your email address will not be published. Required fields are marked *