{"record":{"id":"a517bcc814535e11","repo":"dgtlmoon/changedetection.io","slug":"browserstepsinunsupportedfetcher","errorCode":null,"errorMessage":"BrowserStepsInUnsupportedFetcher","messagePattern":"BrowserStepsInUnsupportedFetcher","errorType":"exception","errorClass":"BrowserStepsInUnsupportedFetcher","httpStatus":null,"severity":"error","filePath":"changedetectionio/content_fetchers/requests.py","lineNumber":43,"sourceCode":"            url,\n            timeout,\n            request_headers,\n            request_body,\n            request_method,\n            ignore_status_codes=False,\n            current_include_filters=None,\n            is_binary=False,\n            empty_pages_are_a_change=False,\n            watch_uuid=None,\n            ):\n        \"\"\"Synchronous version of run - the original requests implementation\"\"\"\n\n        import chardet\n        import requests\n        from requests.exceptions import ProxyError, ConnectionError, RequestException\n\n        if self.browser_steps:\n            raise BrowserStepsInUnsupportedFetcher(url=url)\n\n        proxies = {}\n\n        # Allows override the proxy on a per-request basis\n        # https://requests.readthedocs.io/en/latest/user/advanced/#socks\n        # Should also work with `socks5://user:pass@host:port` type syntax.\n\n        if self.proxy_override:\n            proxies = {'http': self.proxy_override, 'https': self.proxy_override, 'ftp': self.proxy_override}\n        else:\n            if self.system_http_proxy:\n                proxies['http'] = self.system_http_proxy\n            if self.system_https_proxy:\n                proxies['https'] = self.system_https_proxy\n\n        session = requests.Session()\n\n        # Configure retry adapter for low-level network errors only","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/dgtlmoon/changedetection.io/blob/5d9c7c6da76340597243e8163c4f2439237fa0e8/changedetectionio/content_fetchers/requests.py#L25-L61","documentation":"The plain requests-based fetcher cannot execute browser steps, so if a watch has browser_steps configured it immediately raises BrowserStepsInUnsupportedFetcher.","triggerScenarios":"Watch has browser steps defined but its fetcher is 'requests' (plain HTTP) — either explicitly chosen or falling back from a missing browser service.","commonSituations":"User records steps then switches fetcher to requests for speed; default fetcher used on a watch created via API with steps payload.","solutions":["Switch the watch's fetcher to Playwright (or puppeteer)","Or delete the browser steps if they are not needed"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"def fetcher_supports_steps(fetcher_name: str, has_steps: bool) -> bool:\n    return not has_steps or fetcher_name in ('playwright', 'puppeteer')","typeGuard":null,"tryCatchPattern":"try:\n    fetcher.run()\nexcept BrowserStepsInUnsupportedFetcher:\n    watch['fetcher'] = 'playwright'\n    retry_check()","preventionTips":["When adding browser steps, ensure the watch fetcher is playwright","Validate watch configs on save: steps + requests fetcher = misconfiguration"],"tags":["browser-steps","fetcher","unsupported-operation"],"backgroundTag":"unsupported-feature-combination","analyzedSha":"5d9c7c6da76340597243e8163c4f2439237fa0e8","analyzedAt":"2026-08-27T19:41:16.067Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}