Summary
With the documented ws://localhost renderer URLs, JS rendering fails with CDP connect failed: io error (ECONNREFUSED) on recent builds, while the HTTP discovery step against the same localhost host in the same request succeeds.
Repro
- docker compose:
crw + chromedp/headless-shell (9223) + lightpanda (9221), sharing a network namespace
- config:
[renderer.lightpanda] ws_url = "ws://localhost:9221/", [renderer.chrome] ws_url = "ws://localhost:9223/"
- browsers bound IPv4-only (headless-shell:
127.0.0.1:9223, lightpanda: 0.0.0.0:9221)
- container
/etc/hosts lists both 127.0.0.1 localhost and ::1 localhost; resolver returns ::1 first
- any scrape needing JS escalation (e.g. https://quotes.toscrape.com/js/) → server log:
INFO cdp: Discovering browser WS URL from http://localhost:9223/json/version
INFO cdp: Discovered browser WS URL ws_url=ws://localhost:9223/devtools/browser/<uuid>
WARN cdp_conn: CDP connect failed error=IO error: Connection refused (os error 111)
WARN cdp: JS renderer failed ... renderer="chrome"
WARN renderer: JS rendering failed, falling back to HTTP result
(lightpanda tier fails identically against ::1:9221)
Probes from inside the netns:
http://127.0.0.1:9223/json/version → 200
http://[::1]:9223/json/version → ECONNREFUSED
(same pattern on 9221)
Analysis
The HTTP client (discovery) falls back across address families when the first resolved address refuses; the WebSocket connect path in the cdp/cdp_conn modules does not, so with localhost resolving to ::1 it hard-fails against IPv4-only browser listeners.
Workaround
ws_url = "ws://127.0.0.1:9223/" (explicit loopback literal) in config.
Suggestion
Retry across resolved addresses (v6→v4) in the CDP WS connect path, matching the HTTP path, or document that the loopback literal should be used in renderer config.
Version
crw 0.35.1 (docker, ghcr.io/us/crw, image built 2026-09-11); regression observed after updating to that build (JS rendering worked on prior builds per operator reports, unverified).
Summary
With the documented
ws://localhostrenderer URLs, JS rendering fails withCDP connect failed: io error(ECONNREFUSED) on recent builds, while the HTTP discovery step against the samelocalhosthost in the same request succeeds.Repro
crw+chromedp/headless-shell(9223) + lightpanda (9221), sharing a network namespace[renderer.lightpanda] ws_url = "ws://localhost:9221/",[renderer.chrome] ws_url = "ws://localhost:9223/"127.0.0.1:9223, lightpanda:0.0.0.0:9221)/etc/hostslists both127.0.0.1 localhostand::1 localhost; resolver returns::1first(lightpanda tier fails identically against
::1:9221)Probes from inside the netns:
http://127.0.0.1:9223/json/version→ 200http://[::1]:9223/json/version→ ECONNREFUSED(same pattern on 9221)
Analysis
The HTTP client (discovery) falls back across address families when the first resolved address refuses; the WebSocket connect path in the
cdp/cdp_connmodules does not, so withlocalhostresolving to::1it hard-fails against IPv4-only browser listeners.Workaround
ws_url = "ws://127.0.0.1:9223/"(explicit loopback literal) in config.Suggestion
Retry across resolved addresses (v6→v4) in the CDP WS connect path, matching the HTTP path, or document that the loopback literal should be used in renderer config.
Version
crw 0.35.1 (docker,
ghcr.io/us/crw, image built 2026-09-11); regression observed after updating to that build (JS rendering worked on prior builds per operator reports, unverified).