Mixed content: what the error means and how to fix it

Your site moved to HTTPS, and now something on it is broken: a script doesn't run, an API call fails, an embed is blank. The console says Mixed Content. The page is secure, but it asked for something over plain HTTP, and the browser refused.

Mixed Content: The page at 'https://example.com/' was loaded over HTTPS, but requested an
insecure script 'http://cdn.example.net/widget.js'. This request has been blocked; the
content must be served over HTTPS.
On this page
  1. Why browsers block it
  2. What gets blocked and what gets upgraded
  3. Finding every instance
  4. The fixes
  5. On localhost and in development

Why browsers block it

Anything fetched over HTTP travels unencrypted, so anyone on the same Wi-Fi or network path can read or change it. A script altered on the way in runs with full access to your HTTPS page, including its cookies and whatever the user types. Loading it would make the padlock a lie, so browsers don't.

What gets blocked and what gets upgraded

ResourceWhat Chrome does
Scripts, stylesheets, iframes, fetch/XHR, WebSockets (ws://), fontsBlocked. The console shows the Mixed Content error above.
Images, audio, videoUpgraded to https:// automatically; blocked if the server doesn't answer on HTTPS. Two exceptions are blocked, not upgraded: a URL whose host is an IP address, and images loaded through srcset or <picture>.
Form posting to http://Warning before submitting.
Downloads over http:// from an https:// pageBlocked or warned, depending on file type and version.

In JavaScript, a blocked fetch just rejects, which shows up as TypeError: Failed to fetch. Check the console for the Mixed Content line.

Finding every instance

The fixes

  1. Change the URL to https://. Almost every CDN, API and embed supports it; the http:// address is just old. Use https:// explicitly rather than protocol-relative // URLs.
  2. If the other server has no HTTPS, host a copy of the file yourself, or call the API from your own server and serve the result over HTTPS.
  3. Add a safety net header that makes the browser try HTTPS for every http:// address on your pages:
    Content-Security-Policy: upgrade-insecure-requests
    Anything that isn't available over HTTPS will still fail, but you'll stop missing the ones that are.
  4. Make the whole site HTTPS-only with Strict-Transport-Security: max-age=31536000 once everything works, so browsers never load your own pages over HTTP again.

On localhost and in development

http://localhost and http://127.0.0.1 count as secure, so an http page on localhost calling an http API is fine. The error appears when an https page (a deployed front end, or a dev server with a certificate) calls an http API. Run the API with HTTPS too (mkcert makes local certificates trusted), or put both behind the same dev-server proxy.

To test the upgrade-insecure-requests fix on a live site before changing its server, add the header to that site's responses in your own browser:

HeaderForge (Chrome, free)

Add Content-Security-Policy: upgrade-insecure-requests, or any other response header, to the sites you choose, and see whether the rule fired. Switch it off with one click. No account, no tracking.

Get HeaderForge for Chrome

More on this topic: How to change your user agent in Chrome (and what it really changes) · ModHeader alternative · Requestly alternatives for modifying headers (2026) · 401 vs 403: which status code means what, and how to fix each