dgtlmoon/changedetection.io · error · Non200ErrorCodeReceived
Non200ErrorCodeReceived
Error message
Non200ErrorCodeReceived
What it means
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.
Source
Thrown at changedetectionio/content_fetchers/puppeteer.py:460
try:
self.status_code = response.status
except Exception as e:
# https://github.com/dgtlmoon/changedetection.io/discussions/2122#discussioncomment-8241962
logger.critical(f"Response from the browser/Playwright did not have a status_code! Response follows.")
logger.critical(response)
raise PageUnloadable(url=url, status_code=None, message=str(e))
if fetch_favicon:
try:
self.favicon_blob = await self.page.evaluate(FAVICON_FETCHER_JS)
except Exception as e:
logger.error(f"Error fetching FavIcon info {str(e)}, continuing.")
if self.status_code != 200 and not ignore_status_codes:
screenshot = await capture_full_page(page=self.page, screenshot_format=self.screenshot_format, watch_uuid=watch_uuid, lock_viewport_elements=self.lock_viewport_elements)
raise Non200ErrorCodeReceived(url=url, status_code=self.status_code, screenshot=screenshot)
content = await self.page.content
if not empty_pages_are_a_change and len(content.strip()) == 0:
logger.error("Content Fetcher > Content was empty (empty_pages_are_a_change is False), closing browsers")
raise EmptyReply(url=url, status_code=response.status)
# Run Browser Steps here
# @todo not yet supported, we switch to playwright in this case
# if self.browser_steps:
# self.iterate_browser_steps()
# So we can find an element on the page where its selector was entered manually (maybe not xPath etc)
# Setup the xPath/VisualSelector scraper
if current_include_filters:
js = json.dumps(current_include_filters)
await self.page.evaluate(f"var include_filters={js}")View on GitHub (pinned to 5d9c7c6da7)
Solutions
- Inspect attached screenshot and status_code
- Fix URL/auth/headers, or add proxy
- Enable 'Ignore status codes' in watch settings if appropriate
Defensive patterns
Strategy: try-catch
Try / catch
try:
fetcher.fetch_page()
except Non200ErrorCodeReceived as e:
record(e.status_code, screenshot=e.screenshot)
if e.status_code in (429, 502, 503): backoff_and_retry() Prevention
- Set ignore-status-codes for watches where body matters more than code
- Keep auth cookies/headers current
- Alert on repeated 401/403
When it happens
Trigger: puppeteer fetch of a URL returning 403/404/5xx while 'ignore status codes' is disabled.
Common situations: Bot blocking (403), expired URL (404), upstream errors (502/503), missing auth.
Related errors
- EmptyReply
- Error while trying to connect the browser, Code {e.status_co
- Error connecting to the browser, check your browser connecti
- Error connecting to the browser - Exception '{str(e)}'
- 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/6d2faa4b18ee99b1.
Report an issue: GitHub.