"Mixed content: the page was loaded over HTTPS, but requested an insecure resource": how to fix it
Mixed content means your page arrives over https:// but loads a script, stylesheet, image, iframe or API call over plain http://. Browsers block the risky kinds outright and upgrade or flag the rest, so parts of your app break or the address bar warns visitors.
Find each http:// address in your HTML, CSS and code, change it to https:// (or a relative path for your own files), and redeploy.
What browsers do with it
MDN splits mixed content in two:
- Upgradable: images, audio, video and
<source>. "Browsers should automatically upgrade requests for upgradable content from HTTP to HTTPS." If the host is an IP address rather than a domain name, the request is blocked instead. - Blockable: "all mixed content that is not upgradable", including
<script src>, stylesheets,<iframe>,fetch()andXMLHttpRequest, web fonts andsrcsetimages. Browsers block these, which is why a singlehttp://script can stop an app working.
The developer console "shows warnings when mixed content is upgraded or blocked", which is where the "was loaded over HTTPS, but requested an insecure..." messages come from.
Find the http:// addresses
- Open your site, then developer tools: the Console lists each blocked or upgraded address.
- Search your project for
http://(excepthttp://www.w3.org/...namespace strings in SVG and XML, which aren't requests). - Common culprits in AI-built apps: an API base URL in an environment variable (
VITE_API_URL=http://...), an image URL pasted from an old site, a font or widget embed copied from an old snippet, and a CMS or database that storeshttp://image links.
Fix it
- Your own files: use relative paths (
/logo.png) orhttps://addresses on your domain. - Third-party files: change
http://tohttps://. If the provider has no HTTPS version, host the file yourself or replace the provider. - API calls: point the base URL at an
https://endpoint, then rebuild and redeploy so the new value reaches the app. - A safety net: MDN's option is a Content Security Policy that upgrades every request, including blockable content:
Content-Security-Policy: upgrade-insecure-requests
Add it as a response header in your host's config. Upgrading only works when the other server answers on HTTPS. Test this on a preview deployment before relying on it.
What Pewterkit Check looks for
When your homepage is served over https, a free check reads its HTML for http:// addresses in scripts, images, iframes, media, stylesheets, icons, preloads and the manifest, and shows the first one it finds. It doesn't read your CSS files, srcset attributes or addresses your code requests while it runs, so check the browser console too.
FAQ
What does "requested an insecure script" mean?
Your https page tried to load JavaScript from an http:// address. Scripts are blockable mixed content, so the browser refused it, and whatever that script does won't run.
Why do images still show but scripts break?
Images are upgradable: browsers try them over HTTPS automatically. Scripts, stylesheets, iframes and API calls are blocked instead.
Does upgrade-insecure-requests fix everything?
It upgrades every request to HTTPS, including blockable ones. A file whose server has no HTTPS version still fails, so fix the address at the source too.
How do I find mixed content on every page?
The browser console shows it page by page. MDN also mentions crawler tools such as HTTPSChecker and the command-line tool mcdetect for whole sites.
Sources
- MDN: Mixed content — read 27 Oct 2026: upgradable and blockable content, console warnings, fixes, upgrade-insecure-requests, tools
How this page was made: drafted with AI from the sources listed, reviewed by Pewterkit. Docs checked Oct 27, 2026. Spotted something out of date? Tell us.
Related guides
- 404 on refresh: fix deep links in a single-page app on Vercel, Netlify and Cloudflare
- Stripe secret key exposed in your frontend code: rotate it, then move it to the server
- OpenAI API key in your React or Vite frontend: rotate it and move calls to a backend
- Supabase service_role key in your frontend bundle: replace it and switch the old key off