{"record":{"id":"6d2faa4b18ee99b1","repo":"dgtlmoon/changedetection.io","slug":"non200errorcodereceived-6d2faa","errorCode":null,"errorMessage":"Non200ErrorCodeReceived","messagePattern":"Non200ErrorCodeReceived","errorType":"exception","errorClass":"Non200ErrorCodeReceived","httpStatus":null,"severity":"error","filePath":"changedetectionio/content_fetchers/puppeteer.py","lineNumber":460,"sourceCode":"\n        try:\n            self.status_code = response.status\n        except Exception as e:\n            # https://github.com/dgtlmoon/changedetection.io/discussions/2122#discussioncomment-8241962\n            logger.critical(f\"Response from the browser/Playwright did not have a status_code! Response follows.\")\n            logger.critical(response)\n            raise PageUnloadable(url=url, status_code=None, message=str(e))\n\n        if fetch_favicon:\n            try:\n                self.favicon_blob = await self.page.evaluate(FAVICON_FETCHER_JS)\n            except Exception as e:\n                logger.error(f\"Error fetching FavIcon info {str(e)}, continuing.\")\n\n        if self.status_code != 200 and not ignore_status_codes:\n            screenshot = await capture_full_page(page=self.page, screenshot_format=self.screenshot_format, watch_uuid=watch_uuid, lock_viewport_elements=self.lock_viewport_elements)\n\n            raise Non200ErrorCodeReceived(url=url, status_code=self.status_code, screenshot=screenshot)\n\n        content = await self.page.content\n\n        if not empty_pages_are_a_change and len(content.strip()) == 0:\n            logger.error(\"Content Fetcher > Content was empty (empty_pages_are_a_change is False), closing browsers\")\n            raise EmptyReply(url=url, status_code=response.status)\n\n        # Run Browser Steps here\n        # @todo not yet supported, we switch to playwright in this case\n        #            if self.browser_steps:\n        #                self.iterate_browser_steps()\n\n\n        # So we can find an element on the page where its selector was entered manually (maybe not xPath etc)\n        # Setup the xPath/VisualSelector scraper\n        if current_include_filters:\n            js = json.dumps(current_include_filters)\n            await self.page.evaluate(f\"var include_filters={js}\")","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/dgtlmoon/changedetection.io/blob/5d9c7c6da76340597243e8163c4f2439237fa0e8/changedetectionio/content_fetchers/puppeteer.py#L442-L478","documentation":"Same non-200 guard as the playwright fetcher: puppeteer fetch_page raises Non200ErrorCodeReceived (with full-page screenshot) when status != 200 and ignore_status_codes is off.","triggerScenarios":"puppeteer fetch of a URL returning 403/404/5xx while 'ignore status codes' is disabled.","commonSituations":"Bot blocking (403), expired URL (404), upstream errors (502/503), missing auth.","solutions":["Inspect attached screenshot and status_code","Fix URL/auth/headers, or add proxy","Enable 'Ignore status codes' in watch settings if appropriate"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    fetcher.fetch_page()\nexcept Non200ErrorCodeReceived as e:\n    record(e.status_code, screenshot=e.screenshot)\n    if e.status_code in (429, 502, 503): backoff_and_retry()","preventionTips":["Set ignore-status-codes for watches where body matters more than code","Keep auth cookies/headers current","Alert on repeated 401/403"],"tags":["http-status","puppeteer","fetcher"],"backgroundTag":"http-non-200-response","analyzedSha":"5d9c7c6da76340597243e8163c4f2439237fa0e8","analyzedAt":"2026-08-27T19:41:16.067Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}