{"record":{"id":"abeaa716e747fe43","repo":"dotnet/runtime","slug":"this-browser-doesn-t-support-fetch-api-please-use-abeaa7","errorCode":null,"errorMessage":"This browser doesn't support fetch API. Please use a modern browser. See also https://learn.microsoft.com/aspnet/core/blazor/supported-platforms","messagePattern":"This browser doesn't support fetch API\\. Please use a modern browser\\. See also https://learn\\.microsoft\\.com/aspnet/core/blazor/supported-platforms","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts","lineNumber":20,"sourceCode":"// The .NET Foundation licenses this file to you under the MIT license.\n\nimport BuildConfiguration from \"consts:configuration\";\n\nimport type { VoidPtr, ControllablePromise } from \"./types\";\n\nimport { wrapAsCancelablePromise } from \"./cancelable-promise\";\nimport { ENVIRONMENT_IS_NODE } from \"./per-module\";\nimport { assertJsInterop } from \"./utils\";\nimport { MemoryViewType, Span } from \"./marshaled-types\";\nimport { dotnetLogger, dotnetAssert } from \"./cross-module\";\n\n\nfunction verifyEnvironment() {\n    if (typeof globalThis.fetch !== \"function\" || typeof globalThis.AbortController !== \"function\") {\n        const message = ENVIRONMENT_IS_NODE\n            ? \"Please install `node-fetch` and `node-abort-controller` npm packages to enable HTTP client support.\"\n            : \"This browser doesn't support fetch API. Please use a modern browser. See also https://learn.microsoft.com/aspnet/core/blazor/supported-platforms\";\n        throw new Error(message);\n    }\n}\n\nfunction commonAsserts(controller: HttpController) {\n    if (BuildConfiguration !== \"Debug\") {\n        return;\n    }\n    assertJsInterop();\n    dotnetAssert.check(controller, \"expected controller\");\n}\n\nexport function httpSupportsStreamingRequest(): boolean {\n    // Detecting streaming request support works like this:\n    // If the browser doesn't support a particular body type, it calls toString() on the object and uses the result as the body.\n    // So, if the browser doesn't support request streams, the request body becomes the string \"[object ReadableStream]\".\n    // When a string is used as a body, it conveniently sets the Content-Type header to text/plain;charset=UTF-8.\n    // So, if that header is set, then we know the browser doesn't support streams in request objects, and we can exit early.\n    // Safari does support streams in request objects, but doesn't allow them to be used with fetch, so the duplex option is tested, which Safari doesn't currently support.","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts#L2-L38","documentation":"verifyEnvironment() throws this browser-specific message when globalThis.fetch or globalThis.AbortController are missing in a non-Node environment. It points the developer to the Blazor supported-platforms doc. It means the host browser is too old to provide the Fetch API the .NET HttpClient relies on.","triggerScenarios":"Running the .NET WASM runtime (Blazor WASM or standalone) in a legacy browser (old Safari, IE, embedded WebView) that lacks window.fetch or AbortController. httpCreateController()/httpFetch() trigger verifyEnvironment().","commonSituations":"Users on Internet Explorer or very old Safari/Chrome; embedded WebViews in older desktop apps (old WebView2/Edge legacy); a polyfill that should have been loaded wasn't, so fetch is undefined; strict CSP blocking the fetch polyfill script.","solutions":["Require a modern, supported browser per the Blazor supported-platforms doc (Edge, Chrome, Firefox, Safari recent versions).","If you must support older browsers, load a fetch + AbortController polyfill (e.g. whatwg-fetch, abortcontroller-polyfill) before booting the runtime.","Detect the missing API up front and show a user-facing 'browser not supported' message instead of letting HttpClient throw.","For embedded WebViews, update the WebView runtime (WebView2 Evergreen) so a recent Chromium engine provides fetch."],"exampleFix":"// before: legacy browser, no polyfill\n\n// after: load polyfill then boot\nimport 'abortcontroller-polyfill/dist/polyfill-patch-fetch';\n// (whatwg-fetch) then start dotnet","handlingStrategy":"validation","validationCode":"// Feature-detect fetch in the browser before allowing HttpClient usage.\nfunction isFetchSupported(): boolean {\n  return typeof globalThis.fetch === \"function\" && typeof globalThis.AbortController === \"function\";\n}\n\nif (!isFetchSupported()) {\n  // load a polyfill (whatwg-fetch + abortcontroller-polyfill) or show 'unsupported' UI\n}","typeGuard":"function supportsFetchApi(): boolean {\n  return typeof globalThis.fetch === \"function\" && typeof globalThis.AbortController === \"function\";\n}","tryCatchPattern":"null","preventionTips":["Require a modern browser per the Blazor supported-platforms doc.","Load a fetch/AbortController polyfill for legacy browsers before booting the runtime.","Show a user-facing 'unsupported browser' message when fetch is missing rather than letting HttpClient throw.","Update embedded WebViews (WebView2 Evergreen) to a recent engine."],"tags":["http","browser","fetch","compatibility","polyfill"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}