dotnet/runtime · error · Error
This browser doesn't support fetch API. Please use a modern…
Error message
This browser doesn't support fetch API. Please use a modern browser. See also https://learn.microsoft.com/aspnet/core/blazor/supported-platforms
What it means
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.
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.
Example fix
// before: legacy browser, no polyfill // after: load polyfill then boot import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'; // (whatwg-fetch) then start dotnet
Defensive patterns
Strategy: validation
Validate before calling
// Feature-detect fetch in the browser before allowing HttpClient usage.
function isFetchSupported(): boolean {
return typeof globalThis.fetch === "function" && typeof globalThis.AbortController === "function";
}
if (!isFetchSupported()) {
// load a polyfill (whatwg-fetch + abortcontroller-polyfill) or show 'unsupported' UI
} Type guard
function supportsFetchApi(): boolean {
return typeof globalThis.fetch === "function" && typeof globalThis.AbortController === "function";
} Try / catch
null
Prevention
- 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.
When it happens
Trigger: 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().
Common situations: 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.
Related errors
- This browser doesn't support fetch API. Please use a modern…
- Please install `node-fetch` and `node-abort-controller` npm…
- Please install `node-fetch` and `node-abort-controller` npm…
- URLSearchParams is supported
- BrowserHttpWriteStream.Rejected
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/abeaa716e747fe43.
Report an issue: GitHub.
Appendix: source
Thrown at src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts:20
// The .NET Foundation licenses this file to you under the MIT license.
import BuildConfiguration from "consts:configuration";
import type { VoidPtr, ControllablePromise } from "./types";
import { wrapAsCancelablePromise } from "./cancelable-promise";
import { ENVIRONMENT_IS_NODE } from "./per-module";
import { assertJsInterop } from "./utils";
import { MemoryViewType, Span } from "./marshaled-types";
import { dotnetLogger, dotnetAssert } from "./cross-module";
function verifyEnvironment() {
if (typeof globalThis.fetch !== "function" || typeof globalThis.AbortController !== "function") {
const message = ENVIRONMENT_IS_NODE
? "Please install `node-fetch` and `node-abort-controller` npm packages to enable HTTP client support."
: "This browser doesn't support fetch API. Please use a modern browser. See also https://learn.microsoft.com/aspnet/core/blazor/supported-platforms";
throw new Error(message);
}
}
function commonAsserts(controller: HttpController) {
if (BuildConfiguration !== "Debug") {
return;
}
assertJsInterop();
dotnetAssert.check(controller, "expected controller");
}
export function httpSupportsStreamingRequest(): boolean {
// Detecting streaming request support works like this:
// If the browser doesn't support a particular body type, it calls toString() on the object and uses the result as the body.
// So, if the browser doesn't support request streams, the request body becomes the string "[object ReadableStream]".
// When a string is used as a body, it conveniently sets the Content-Type header to text/plain;charset=UTF-8.
// So, if that header is set, then we know the browser doesn't support streams in request objects, and we can exit early.
// 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.View on GitHub (pinned to 60108ba66e)