{"record":{"id":"12c0d49bf1dd6987","repo":"dgtlmoon/changedetection.io","slug":"error-while-trying-to-connect-the-browser-code-e","errorCode":null,"errorMessage":"Error while trying to connect the browser, Code {e.status_code} (check your access, whitelist IP, password etc)","messagePattern":"Error while trying to connect the browser, Code (.+?) \\(check your access, whitelist IP, password etc\\)","errorType":"exception","errorClass":"BrowserConnectError","httpStatus":null,"severity":"error","filePath":"changedetectionio/content_fetchers/puppeteer.py","lineNumber":299,"sourceCode":"\n        n = int(os.getenv(\"WEBDRIVER_DELAY_BEFORE_CONTENT_READY\", 12)) + self.render_extract_delay\n        extra_wait = min(n, 15)\n\n        logger.debug(f\"Extra wait set to {extra_wait}s, requested was {n}s.\")\n\n        from pyppeteer import Pyppeteer\n        pyppeteer_instance = Pyppeteer()\n\n        # Connect directly using the specified browser_ws_endpoint\n        # @todo timeout\n        try:\n            logger.debug(f\"[{watch_uuid}] Connecting to browser at {self.browser_connection_url}\")\n            self.browser = await pyppeteer_instance.connect(browserWSEndpoint=self.browser_connection_url,\n                                                            ignoreHTTPSErrors=True\n                                                            )\n            logger.debug(f\"[{watch_uuid}] Browser connected successfully\")\n        except websockets.exceptions.InvalidStatusCode as e:\n            raise BrowserConnectError(msg=f\"Error while trying to connect the browser, Code {e.status_code} (check your access, whitelist IP, password etc)\")\n        except websockets.exceptions.InvalidURI:\n            raise BrowserConnectError(msg=f\"Error connecting to the browser, check your browser connection address (should be ws:// or wss://\")\n        except Exception as e:\n            raise BrowserConnectError(msg=f\"Error connecting to the browser - Exception '{str(e)}'\")\n\n        # more reliable is to just request a new page\n        try:\n            logger.debug(f\"[{watch_uuid}] Creating new page\")\n            self.page = await self.browser.newPage()\n            logger.debug(f\"[{watch_uuid}] Page created successfully\")\n        except Exception as e:\n            logger.error(f\"[{watch_uuid}] Failed to create new page: {e}\")\n            # Browser is connected but page creation failed - must cleanup browser\n            try:\n                await asyncio.wait_for(self.browser.close(), timeout=3.0)\n            except Exception as cleanup_error:\n                logger.error(f\"[{watch_uuid}] Failed to cleanup browser after page creation failure: {cleanup_error}\")\n            finally:","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/dgtlmoon/changedetection.io/blob/5d9c7c6da76340597243e8163c4f2439237fa0e8/changedetectionio/content_fetchers/puppeteer.py#L281-L317","documentation":"puppeteer/pyppeteer fetcher got websockets.exceptions.InvalidStatusCode while connecting to the browser WebSocket endpoint; wrapped as BrowserConnectError with the HTTP status hint about access/whitelist/IP/password.","triggerScenarios":"pyppeteer connecting to browser_connection_url and the endpoint answers with an unexpected HTTP status — 401/403 from an auth-protected browser, 404 wrong path/port, or a proxy in between.","commonSituations":"Browserless/cloud browser service requiring a token not in the URL; wrong port; firewall/NAT rejecting the WS handshake; IP not whitelisted on a managed browser service.","solutions":["Verify the websocket URL includes required credentials/token (e.g. ws://host:3000/?token=...)","Confirm host/port and that the browser service is up","Whitelist the changedetection.io host IP with the browser provider","Check for intercepting proxies that answer the WS upgrade with an error status"],"exampleFix":"# before\nbrowser_connection_url = \"ws://browser:3000\"\n# after\nbrowser_connection_url = \"ws://browser:3000/?token=YOUR_TOKEN\"","handlingStrategy":"try-catch","validationCode":"import socket, urllib.parse\nu = urllib.parse.urlparse(browser_url)\nassert u.scheme in ('ws','wss') and u.hostname and u.port\nsocket.create_connection((u.hostname, u.port), timeout=5).close()  # reachability pre-check","typeGuard":null,"tryCatchPattern":"try:\n    fetcher.fetch_page()\nexcept BrowserConnectError as e:\n    if 'Code 40' in str(e): fix_credentials_or_whitelist()\n    else: raise","preventionTips":["Include auth tokens in the websocket URL for managed browser services","Whitelist the changedetection.io host IP with the provider","Pre-check TCP reachability before running checks"],"tags":["websocket","puppeteer","connection","browser-service"],"backgroundTag":"websocket-connection-refused","analyzedSha":"5d9c7c6da76340597243e8163c4f2439237fa0e8","analyzedAt":"2026-08-27T19:41:16.067Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}