Mixed content: how to find insecure requests and fix them before the browser blocks them
Mixed content is an insecure request made by a page loaded over HTTPS. Browsers upgrade images, video and audio on their own and block every other insecure request, so one http:// URL can quietly stop a script or a download. Here is the audit command and the fix table.

Mixed content is what a browser calls an insecure request made by a page that was loaded over HTTPS. Browsers handle it in two ways: they upgrade images, video and audio from HTTP to HTTPS on their own, and they block every other insecure request, including scripts, stylesheets, frames, fetches and downloads. The fix is to serve each subresource over HTTPS, and the fastest interim net is one Content-Security-Policy directive.
Read this first
You need to edit one page and view its source. That is the whole prerequisite, and there is no build step. Two chapters sit next to this one. If your question is whether a security header is stopping Google's renderer rather than the browser, content security policy and SEO covers the header itself, and this chapter only borrows one directive from it. If the page's real problem is that a crawler gets an empty shell instead of content, can AI crawl JavaScript is the step before this one. The measured side, how often http:// URLs actually appear, is in mixed content on 27 homepages.
What mixed content is, and why the browser splits it in two
A secure context is a page loaded over HTTPS. MDN defines the guarantee: "When a web page is loaded from a secure origin, over a secure channel such as HTTPS, the connection with the web server is encrypted, and is therefore protected from eavesdropping and modification by manipulator in the middle (MITM) attacks" (MDN, read 2026-09-27). One http:// request inside that page breaks the guarantee for that one resource, and anything sitting on the network path can change it in transit.
Modern browsers draw a single line through all of it. In MDN's wording, "a web page is divided into two categories: 'upgradable content' and 'blockable content'. Browsers should automatically upgrade requests for upgradable content from HTTP to HTTPS, and block requests for the blockable content." In the current text, image, video and audio requests are "auto-upgrading", while browsers "block insecure requests for all other resource types" — scripts, stylesheets, frames, fetch and XHR, fonts.
One insecure request is enough. A page is only as secure as the least secure thing it loads.
There is a third case worth naming: mixed downloads. MDN calls these resources "initiated from a secure context, but fetched over an insecure connection", and states browsers "should also block mixed downloads by default." A file your page offers can be stopped for the same reason a script is.
What a visitor sees depends on which side the failure lands on. A blockable request is refused in the developer console and the resource never arrives. An upgradable request fails quietly when the HTTPS copy does not exist. We cannot read from the HTML which of the two a particular visitor hit; that is a console fact, not a markup fact. The rest of this chapter is about the markup.
Do it in this order
Four steps. Each has a completion mark you can check before moving to the next.
- List every subresource the page loads. Images, scripts, stylesheets, fonts, frames, video. Done when the list matches what the Network panel shows on a hard refresh.
- Flag the http:// ones. Run the audit below. Done when it returns zero lines, or you can name each remaining line and say why it is there.
- Fix the blockable resources first. A script or a stylesheet cannot be auto-upgraded, so it needs a real https:// URL. Done when the console shows no refusal for that resource.
- Add the interim net. If you cannot edit every URL today, add
upgrade-insecure-requests. Done when the header is present and the blockable resources load.
The deliverable: one audit command and a fix table
The audit reads the HTML the server sent and prints every URL that still starts with http://. It does not run JavaScript, so it sees what a crawler sees on the first pass.
curl -sL https://example.com \
| grep -oE 'http://[^" ]+' \
| sort | uniq -c | sort -rn
A companion check asks whether the safety net is already in place:
curl -sIL https://example.com | grep -i content-security-policy
Run against Google's own SEO Starter Guide, the page that tells you to write good HTML, the first command returns nothing on 2026-09-27: no http:// URL in the delivered HTML. The header check is more interesting. That page does send a Content-Security-Policy, and it is not the kind that upgrades anything; its script-src even allows the scheme http:. The same two commands against querywin.com and byerisk.com return zero http:// URLs on both, and no Content-Security-Policy header on either. That is a clean audit and a reminder at once: neither of our pages has the net.
One more number from the guide, because it trips people up. Eleven subresource references on it are scheme-relative — they start with // instead of a scheme. On an HTTPS page those load over HTTPS and are not mixed content; the line only matters if the page is ever served over HTTP. We count them separately for exactly that reason.
| Symptom | Cause | Fix |
|---|---|---|
| Image or video missing | http:// media URL | Change it to https://, or let the browser upgrade it when the HTTPS copy exists |
| Script or stylesheet refused | http:// blockable resource | A real https:// URL is required; auto-upgrade does not cover scripts |
| Many legacy URLs | Old CMS or templates | Send upgrade-insecure-requests while you rewrite them |
| Download blocked | Insecure download | Serve the file over HTTPS |
The interim net is one response header. Where you set it depends on your host.
Content-Security-Policy: upgrade-insecure-requests
MDN says the directive "instructs the user agent to treat a site's insecure URLs (those served over HTTP) as though they have been replaced with secure URLs (those served over HTTPS)." It rewrites the URLs before the request is made, "first-party as well as third-party requests", and it is "intended for websites with large numbers of insecure legacy URLs that need to be rewritten." Two limits are built in, and both matter. If the HTTPS version of a resource does not exist, "the request will fail without any fallback to HTTP." And it does not cover top-level navigation: MDN states it "will not ensure that users visiting your site via links on third-party sites will be upgraded to HTTPS for the top-level navigation," so it is not a replacement for HSTS.
What goes wrong
Three failures account for most of the bad fixes.
- Switching on the upgrade before the HTTPS copy exists. Every rewritten request has no fallback, so a missing file becomes a missing file that used to work. Fix the URLs first, or accept that the net will break whatever it cannot upgrade.
- Trusting the grep. The audit reads delivered HTML. A widget that injects an http:// image or an analytics script after load is invisible to it, and the console is where you will see it. The command is a floor, not a certificate.
- Reading scheme-relative URLs as insecure.
//cdn.example.com/x.jsis HTTPS on an HTTPS page. Rewriting it by hand is harmless, but counting it as mixed content sends you chasing a problem you do not have.
Common questions
What is mixed content?
Content on an HTTPS page that was requested over HTTP. The page is secure and the request is not. Browsers block the dangerous kinds and upgrade the safe kinds.
Does mixed content affect SEO?
It is not a ranking factor, and we will not claim a ranking effect. It changes what loads: a blocked script or stylesheet changes the page that a rendering crawler and a visitor both see. Google's own documentation treats HTTPS as a very lightweight signal, so the reason to fix this is a working page, not a rank jump.
Does upgrade-insecure-requests fix all of it?
No. It covers subresources rather than navigations, and it only works when the HTTPS version exists. Treat it as a net, not a fix.
How did you check this?
We ran the audit command once per page on 2026-09-27 against Google's SEO Starter Guide and two of our own homepages, reading only the HTML the server returned. We did not load the pages in a browser to confirm what was blocked, so the markup and the header are all we report; the survey of 27 homepages covers the wider panel.
Mixed content is a delivery bug with a small, checkable fix, and it tends to surface only after a vendor or a template changes underneath you. The larger half of the same problem — whether a crawler gets your finished page at all — is the part QueryWin works on.
Part of the QueryWin handbook · Level 2


