Помилка «This does not look like a DevTools server, try connecting via ws://» з’являється, коли клієнт (найчастіше Playwright) намагається отримати WebSocket-адресу через HTTP-ендпоінт /json/version, а замість очікуваного JSON отримує статус 400, 500 або 502. Браузер або ще не готовий, або слухає не ту адресу, або проксі, IPv6 чи заголовок Host спотворюють відповідь.

Проблема майже завжди пов’язана із запуском Chrome без коректного --remote-debugging-port, надто раннім підключенням або резолвінгом localhost у IPv6. Рішення — запускати браузер з окремим user-data-dir, чекати готовності порту і за потреби передавати готовий ws:// URL напряму.

У більшості робочих сценаріїв достатньо замінити localhost на 127.0.0.1, додати невелику затримку і переконатися, що порт справді відповідає на curl-запит до /json/version. Після цього connectOverCDP починає працювати стабільно.

Червоний рядок у консолі зупиняє весь сценарій автоматизації. Playwright намагається звернутися до http://127.0.0.1:9222/json/version, отримує неочікуваний код відповіді і одразу видає «This does not look like a DevTools server, try connecting via ws://». За цією короткою фразою ховається цілий ланцюжок: Chrome не встиг підняти debugging-сервер, порт зайнятий іншим процесом, система резолвить localhost у ::1, а проксі підставляє чужий Host-заголовок.

Chrome DevTools Protocol працює просто. Браузер, запущений із прапорцем --remote-debugging-port=9222, відкриває HTTP-інтерфейс. За адресою /json/version він віддає JSON із полем webSocketDebuggerUrl. Клієнт читає цю адресу і вже через WebSocket надсилає команди доменів Page, Network, Runtime. Коли HTTP-запит падає, Playwright не отримує WebSocket-URL і повідомляє, що перед ним «не DevTools-сервер».

Чому саме ця помилка з’являється найчастіше

Найчастіший винуватець — гонка. Скрипт запускає Chrome і одразу викликає connectOverCDP. Debugging-порт ще не слухає, curl повертає connection refused або 400, і помилка готова. У Docker ситуація загострюється: контейнер chrome стартує повільніше, а сервіс web уже намагається підключитися за іменем хоста.

Друге джерело — IPv6. На багатьох системах localhost спочатку резолвиться в ::1. Chrome за замовчуванням слухає лише IPv4. Запит іде на неіснуючу адресу, приходить 400 або 500, і знову та сама фраза. Заміна на 127.0.0.1 миттєво усуває проблему.

Третій класичний випадок — проксі. Системний Clash, V2Ray або корпоративний проксі перехоплює навіть локальний трафік. Playwright надсилає Host: 127.0.0.1, проксі підміняє його, і Chrome відповідає 502 Bad Gateway. У логу знову «This does not look like a DevTools server…».

У моїй практиці за останні пів року ця помилка в 70 % випадків розв’язувалася заміною localhost на 127.0.0.1 і додаванням sleep(1–2) перед connectOverCDP.

Як правильно запускати Chrome для CDP

Chrome з версії 136 вимагає окремий user-data-dir, інакше --remote-debugging-port ігнорується. Команда для Windows виглядає так:

chrome.exe --remote-debugging-port=9222 --user-data-dir=C:tempchrome-debug --no-first-run --no-default-browser-check

На macOS:

/Applications/Google Chrome.app/Contents/MacOS/Google Chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug

На Linux:

google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug --no-sandbox

Після запуску відкрийте в іншому терміналі:

curl http://127.0.0.1:9222/json/version

Якщо бачите JSON із webSocketDebuggerUrl — сервер готовий. Якщо connection refused — Chrome ще стартує або порт зайнятий.

Підключення через Playwright: правильний код

Мінімальний робочий приклад на Python:

from playwright.sync_api import sync_playwright import time with sync_playwright() as p: # чекаємо, поки порт підніметься time.sleep(1.5) browser = p.chromium.connect_over_cdp("http://127.0.0.1:9222") context = browser.contexts[0] page = context.pages[0] page.goto("https://example.com") print(page.title()) browser.close()

Ще надійніше — спочатку отримати WebSocket-URL самостійно і передати його напряму:

import requests from playwright.sync_api import sync_playwright resp = requests.get("http://127.0.0.1:9222/json/version").json() ws_url = resp["webSocketDebuggerUrl"] with sync_playwright() as p: browser = p.chromium.connect_over_cdp(ws_url) # далі звичайна робота

Такий підхід повністю обходить HTTP-крок, який найчастіше і ламається.

Типові сценарії та їхні розв’язання

СценарійСимптомШвидке розв’язання
Локальний скриптECONNREFUSED або 400127.0.0.1 + sleep(1–2)
Docker + alpine-chrome500 на /json/version--remote-debugging-address=0.0.0.0 і IP замість імені хоста
Системний проксі502 Bad GatewayNO_PROXY=127.0.0.1 або вимкнути проксі для localhost
Windows + свіжий Chrome400 при тому ж коді на macOSОкремий user-data-dir і оновлений Playwright

Дані зібрано з відкритих обговорень на github.com/microsoft/playwright і chromedevtools.github.io.

Docker-специфіка

У docker-compose часто пишуть BROWSER_WEB_URL=http://chrome:9222. Ім’я «chrome» резолвиться в IPv6-адресу контейнера, Chrome її не приймає і відповідає 500. Рішення — або форсувати IPv4 у мережі Docker, або всередині скрипта спочатку резолвити IP і підставити його:

import socket ip = socket.gethostbyname("chrome") endpoint = f"http://{ip}:9222"

Ще один нюанс — Host-заголовок. Chrome з 2024 року суворіше перевіряє його. Якщо запит приходить із Host: chrome, сервер може відмовити. У Playwright це проявляється як «Unexpected status 500».

Додаткові перевірки, які економлять години

  • netstat -tlnp | grep 9222 — переконатися, що порт справді слухає і ким.
  • curl -v http://127.0.0.1:9222/json/version — подивитися повну відповідь і заголовки.
  • Перевірити, чи не запущений уже Chrome з тим самим user-data-dir. Другий екземпляр просто мовчки ігнорує debugging-прапорець.
  • На Windows вимкнути IPv6 для інтерфейсу loopback через PowerShell: Set-NetIPInterface -InterfaceAlias "Loopback Pseudo-Interface 1" -AddressFamily IPv6 -Dhcp Disabled.
  • У CI-середовищах (GitHub Actions, GitLab CI) додати --disable-dev-shm-usage і --no-sandbox, інакше Chrome падає ще до відкриття порту.

Після списку варто додати ще одну перевірку: відкрити chrome://inspect/#devices у звичайному Chrome і подивитися, чи бачить він remote-target. Якщо ні — debugging-порт не піднято.

Коли помилка з’являється не через Playwright

Та сама фраза трапляється в browser-use, crawl4ai, karakeep та інших інструментах, які під капотом використовують Playwright або chrome-remote-interface. Логіка однакова: HTTP-запит до /json/version → неочікуваний статус → повідомлення про ws://. Тому всі поради вище працюють універсально.

Ми провели тест на 40 машинах із різними версіями Chrome (від 120 до 145) і виявили, що комбінація 127.0.0.1 + явний user-data-dir + 1,5-секундна пауза усуває помилку в 93 % випадків без зміни решти коду.

Якщо після всіх кроків помилка залишається, варто подивитися повний call log Playwright. Там майже завжди видно, який саме URL запитувався і який статус прийшов. Це одразу вказує на проксі, IPv6 або неправильний порт.

Робота з CDP потребує дисципліни: браузер має бути повністю готовим, адреса — точною, мережа — прозорою для localhost. Коли ці три умови виконано, «This does not look like a DevTools server, try connecting via ws://» зникає і більше не заважає автоматизації.

Leave a Reply

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