One HTTP asset on an HTTPS page, and the padlock is gone
An encrypted page that pulls in one script over HTTP has not slightly weakened its encryption. It has handed an attacker on the network the ability to run code in your page, which is why browsers stopped asking and started blocking.
The short answer
Mixed content is an HTTPS page loading a resource over HTTP, and browsers treat two kinds differently. Active content, scripts, stylesheets and iframes, is blocked outright, so the page visibly breaks. Passive content, images and media, is either upgraded or shown with a warning. The last HTTP references usually hide in inline styles and third-party embeds.
Active and passive, treated completely differently
The distinction the browsers draw is between content that can change the page and content that only appears in it. A script, a stylesheet, an iframe or a request made from JavaScript can execute or restyle; an image, a video or an audio file is displayed.
The consequences differ as sharply as the treatment. A blocked script is a feature that did not run: a payment widget, an analytics call, a menu, a search box, and whatever it was going to render is simply absent. An upgraded image either works, in which case you never find out, or fails and leaves a hole.
Which makes the auto-upgrade behaviour a mixed blessing worth understanding. It has quietly repaired a huge amount of old mixed content, and it means a site can be full of HTTP image references that all happen to work, until one asset host stops serving HTTPS and a set of images disappears with no code change on your side.
Where the last HTTP references hide
A migration usually catches the templates. What it misses is everywhere else a URL can be written, and this list is in rough order of how often it is the culprit.
- Inside your database. Absolute URLs pasted into article bodies, product descriptions and custom fields over the years. This is the big one on any content-managed site, and it is a search and replace across content rather than code.
- In CSS. A
background-imageor an@font-facewith an absolute HTTP URL, in a stylesheet nobody has opened since it was written. Grepping your templates will not find these. - In script that builds URLs. A base URL in a configuration object, a string concatenation, an analytics snippet copied from an old dashboard. These are invisible to a static scan of your markup because the URL does not exist until the page runs.
- In third-party embeds. A map, a video player, a chat widget, a font service. You control the embed and not what it requests, so the fix is updating or replacing the embed.
- In email templates and PDFs. Not mixed content in the browser sense, and the same stale absolute URLs, which stop working when the HTTP host eventually goes away.
The most useful preventive measure is to stop writing absolute URLs to your own assets at all. Protocol-relative URLs are not the answer either, since they are ambiguous outside a document context. A plain path, resolved by the browser against the current page, cannot be wrong.
Every asset reference has to be read
This is a question about the contents of a page rather than about the page itself: every src, every href, every url in a stylesheet, and the protocol on each. The single-page payload reports what the document is, not the list of things it pulls in.
This one needs the full crawl
Finding these means reading every asset reference on the page, scripts, styles, images, iframes and fonts, and checking the protocol on each. A page-level fetch does not enumerate them.
The instant search on this site audits a single page, so rather than show you a verdict it cannot support, this guide sends you to the place the check actually runs.
The immediate version is your browser console, which logs every blocked and upgraded request with the exact URL. It is the fastest diagnosis on this page and the reason the last section uses a script instead: the console only reports the page you are looking at.
Does this affect AI search?
Yes, and by a route that has nothing to do with security assessments. A blocked script is a script that did not run, so any content it was going to insert does not exist. For a client that renders the page, that content is missing; for one that does not render at all, it was missing anyway.
Which makes this a rendering failure wearing a security label, and it compounds with the rendering problem in an unpleasant way. A site whose content is injected by script is already fragile for machine readers. A site whose injecting script is blocked for mixed content is serving an empty shell to everything, including browsers.
The image case is quieter and still costs something. An image that fails after an upgrade attempt is an image with no representation at all, so whatever it was illustrating is unavailable to anything reading the page, and your alt text is describing something nobody can fetch.
Why a blocked asset is rated Critical
Because the blocking is not graceful. A script that a browser refuses to load does not degrade, it does not warn the visitor, and whatever depended on it stops working. When that script renders your navigation or your product list, the page is broken for every visitor and every crawler at once, which is squarely what Critical is for.
The rating also reflects that this is a security finding first. An insecure script on a secure page is an opportunity for anybody between your visitor and your server to run code in your origin, with access to what your page has access to. That is a different category of problem from the rest of an SEO audit and it belongs at the top of any list it appears on.
What keeps it findable rather than mysterious is the browser console, which names every offending URL. This is one of the few Critical findings where the diagnosis takes ten seconds; the work is in the long tail of places listed above, and that is where the afternoon goes.
Finding them without opening a browser
The console shows you one page. For a site, grep the served markup and the stylesheets it references.
URL=https://example.com/guides/carbon-steel
# insecure references in the markup, with the attribute that carries them
curl -s "$URL" \
| grep -oE '(src|href|action|data-src)="http://[^"]*"' \
| sort -u
# and inside every stylesheet the page pulls in
curl -s "$URL" \
| grep -oE 'href="[^"]*\.css[^"]*"' | sed 's/href="//;s/"$//' \
| while read -r css; do
case "$css" in
http*) sheet="$css" ;;
//*) sheet="https:$css" ;;
*) sheet="https://example.com$css" ;;
esac
curl -s "$sheet" | grep -oE 'url\(["'"'"']?http://[^)"'"'"']*' \
| sed "s|^|$css: |"
doneRun the first command across your sitemap and you will find the database problem immediately: if the hits are inside article bodies rather than in the same template position on every page, the URLs were typed by people.
Then let the browser fix the rest for you, and use the report to find them.
A Content-Security-Policy containing upgrade-insecure-requests rewrites every HTTP reference to HTTPS before the request goes out, which turns a long tail of blocked assets into working ones without touching your content. Adding block-all-mixed-content instead makes the failures loud, which is what you want in staging.
The better trick is the reporting directive on a policy in report-only mode: it sends you a report for every violation, from real visitors, on pages nobody thought to test. The policy guide covers how to introduce that without breaking anything.
Questions this check raises
- What is the difference between active and passive mixed content?
- Active content can change the page: scripts, stylesheets, iframes, XHR. Browsers block it entirely, because an intercepted script owns the page. Passive content, images, audio and video, can only be substituted, so browsers upgrade it where possible and warn otherwise.
- Where do mixed content references hide?
- In the places nobody greps: inline style attributes with a background image URL, content stored in a database from before the migration, third-party embed snippets that hardcode http, and redirects that land on a plaintext URL before bouncing back.
- Does upgrade-insecure-requests fix mixed content?
- It papers over it, which is genuinely useful during a migration: the browser rewrites HTTP subresource requests to HTTPS before making them. It is not a fix, because the underlying references are still wrong and any client not honouring the directive still requests plaintext.