Short answer
Open Chrome DevTools (F12), look at the Console and Network tabs, and run the request again: the red message there names the cause. Most often it is CORS: the API doesn’t send an Access-Control-Allow-Origin header for your web app’s address, and the fix is on the server, not in Flutter. Next come an http:// API called from an https:// page (mixed content), a Firebase Storage bucket with no CORS setting, and a server that is down or has a bad certificate. Starting Chrome with --disable-web-security only hides CORS on your own machine; your users still hit it.
What the browser blocked, and the fix
01
The API doesn’t allow your web app’s origin (CORS)
“CORS is a mechanism that browsers use to control how one site accesses the resources of another site.” Flutter, Display images on the web: CORS
The console says blocked by CORS policy: No 'Access-Control-Allow-Origin' header. Phones don’t apply CORS, which is why only the web build fails. Add your web app’s address to the server’s CORS settings and answer OPTIONS preflight requests. While developing, run flutter run -d chrome --web-port 5000 so the localhost address stays the same and can be allowed too.
02
An http:// API called from an https:// page
“Mixed content requests are insecure requests for resources from a secure context” MDN, Mixed content
A web app served over https can’t make requests to a plain http:// API (http://localhost is the exception); the browser blocks them as mixed content. The phone build may still work, so the web build looks like the only one broken. Serve the API over https.
03
Firebase Storage downloads with no CORS rule
“To download data directly in the browser, you must configure your Cloud Storage bucket for cross-origin access (CORS).” Firebase, Download files with Cloud Storage on Web
Reading a file’s bytes from Firebase Storage in the browser needs a CORS rule on the bucket. Write a cors.json that lists your web app’s origins and the GET method, then apply it with gcloud storage buckets update gs://your-bucket --cors-file=cors.json (older guides use gsutil cors set).
[{"origin": ["https://your-app.web.app"], "method": ["GET"], "maxAgeSeconds": 3600}]04
The server is down, the URL is wrong, or the certificate is bad
A request that never gets an answer gives the same error. Open the API URL in a browser tab: if it fails there or shows a certificate warning, fix the server or the address first. A server that crashes with a 500 often sends no CORS headers on that error, so it shows up as a CORS problem too: check the server log. A self-signed certificate that a phone build accepts through a custom HttpClient is still rejected by the browser.
Checked against the vendor’s docs on : Flutter: Display images on the web (CORS); MDN: Mixed content; Firebase: Download files with Cloud Storage on Web (CORS configuration).
Rather hand it over?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- from $450App Fix TicketOne reproducible bug in an existing mobile or web app, diagnosed and fixed.See scope and start
- from $450AI-Built App RescueA Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.See scope and start
Related: “Blocked by CORS policy” · Firebase Functions CORS error · Flutter “Unable to load asset” · Flutter “type 'Null' is not a subtype of type 'String'”