dgtlmoon/changedetection.io · error · BrowserConnectError
Error connecting to the browser, check your browser connecti
Error message
Error connecting to the browser, check your browser connection address (should be ws:// or wss://
What it means
BrowserConnectError raised when pyppeteer's websocket endpoint URL fails to parse as a valid ws:// or wss:// URI (websockets.exceptions.InvalidURI).
Source
Thrown at changedetectionio/content_fetchers/puppeteer.py:301
extra_wait = min(n, 15)
logger.debug(f"Extra wait set to {extra_wait}s, requested was {n}s.")
from pyppeteer import Pyppeteer
pyppeteer_instance = Pyppeteer()
# Connect directly using the specified browser_ws_endpoint
# @todo timeout
try:
logger.debug(f"[{watch_uuid}] Connecting to browser at {self.browser_connection_url}")
self.browser = await pyppeteer_instance.connect(browserWSEndpoint=self.browser_connection_url,
ignoreHTTPSErrors=True
)
logger.debug(f"[{watch_uuid}] Browser connected successfully")
except websockets.exceptions.InvalidStatusCode as e:
raise BrowserConnectError(msg=f"Error while trying to connect the browser, Code {e.status_code} (check your access, whitelist IP, password etc)")
except websockets.exceptions.InvalidURI:
raise BrowserConnectError(msg=f"Error connecting to the browser, check your browser connection address (should be ws:// or wss://")
except Exception as e:
raise BrowserConnectError(msg=f"Error connecting to the browser - Exception '{str(e)}'")
# more reliable is to just request a new page
try:
logger.debug(f"[{watch_uuid}] Creating new page")
self.page = await self.browser.newPage()
logger.debug(f"[{watch_uuid}] Page created successfully")
except Exception as e:
logger.error(f"[{watch_uuid}] Failed to create new page: {e}")
# Browser is connected but page creation failed - must cleanup browser
try:
await asyncio.wait_for(self.browser.close(), timeout=3.0)
except Exception as cleanup_error:
logger.error(f"[{watch_uuid}] Failed to cleanup browser after page creation failure: {cleanup_error}")
finally:
self.browser = None
raiseView on GitHub (pinned to 5d9c7c6da7)
Solutions
- Set the URL with an explicit scheme: ws://host:port or wss://host:port
- Check the environment/config value actually loaded (no stray quotes/whitespace)
Example fix
# before http://chrome:3000 # after ws://chrome:3000
Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
def valid_ws_url(u: str) -> bool:
p = urlparse(u)
return p.scheme in ('ws', 'wss') and bool(p.hostname) Prevention
- Always configure ws:// or wss:// scheme explicitly
- Normalize browser URLs in config management, not ad-hoc env edits
When it happens
Trigger: browser_connection_url missing the ws:// scheme (e.g. 'localhost:3000' or 'http://host'), malformed URI, or trailing garbage that breaks parsing.
Common situations: Copy-pasting an http:// URL into the puppeteer connection setting; missing scheme entirely after env var misconfiguration.
Related errors
- Error while trying to connect the browser, Code {e.status_co
- Error connecting to the browser - Exception '{str(e)}'
- EmptyReply
- Non200ErrorCodeReceived
- Content Fetcher > xPath scraper failed. Please report this U
AI-assisted analysis of dgtlmoon/changedetection.io@5d9c7c6da7 (2026-08-27).
Data as JSON: /api/errors/0dd162ff9a5fddde.
Report an issue: GitHub.