Fix: Mixed Content Warnings on HTTPS (Why Your Padlock Disappeared)

·6 min read

You moved your site to HTTPS, the certificate is valid, and yet the padlock in the address bar is missing — or worse, a chart won't render and the console is full of red. The cause is almost always mixed content: your page loads over https:// but pulls in at least one resource over plain http://.

Browsers treat that as a broken promise. You told the user the connection is secure, then reached out over an unencrypted channel anyway. So Chrome, Safari, and Firefox either downgrade your security indicator or block the resource outright.

What "Mixed Content" Actually Means

A mixed-content page is an HTTPS page that requests a sub-resource over HTTP. The resource can be anything the page loads: a script, a stylesheet, an image, a font, an iframe, an <audio>/<video> file, an XHR/fetch call, or even a <form> that posts to an HTTP endpoint.

Browsers split these into two buckets, and the buckets behave very differently:

  • Active mixed content — scripts, stylesheets, iframes, fonts, XHR/fetch, and form submissions. These can alter the whole page, so browsers block them outright. This is why "my JavaScript widget vanished after going HTTPS" happens.
  • Passive mixed content — images, audio, and video. These can't rewrite the page, so browsers usually load them but strip the padlock, showing "Not fully secure" instead.

That distinction explains the two symptoms people report. If a feature is broken, you have active mixed content. If the page works but the padlock is gone, you have passive mixed content.

How to Find Every Instance

Start with your browser's DevTools. Open the Console on the affected page and look for messages like:

Mixed Content: The page at 'https://example.com/' was loaded over HTTPS,
but requested an insecure script 'http://cdn.example.com/widget.js'.
This request has been blocked.

The console catches what the browser executed on this load. But it misses anything that didn't fire — a form action that nobody submitted, an http:// link in a lazy-loaded section, a resource behind a conditional. To catch those, scan the raw HTML instead of relying on runtime behavior.

Paste your page source into the HTTPS Mixed Content Checker — it walks every tag that can load a sub-resource (<script>, <link>, <img>, <iframe>, <source>, <audio>, <video>, <object>, <form action>, inline url() in styles) and flags every http:// reference, sorted by whether the browser will block it or just downgrade the padlock. That way you fix the form action nobody clicked before a customer finds it.

The Fixes, In Order of Preference

1. Change http:// to https://

The boring answer is right 90% of the time. Most CDNs, font hosts, and analytics providers have supported HTTPS for years. Find the offending URL and swap the scheme:

<!-- before -->
<script src="http://cdn.example.com/widget.js"></script>
<!-- after -->
<script src="https://cdn.example.com/widget.js"></script>

Before you commit, actually load the https:// version in a new tab. A surprising number of legacy CDNs serve a valid certificate on HTTPS but a different (or missing) file. Confirm it returns 200 over HTTPS, not a redirect to HTTP.

2. Use protocol-relative URLs only as a stopgap

You'll see old code use //cdn.example.com/widget.js (no scheme), which inherits the page's protocol. It works, but it's a relic from the era when sites still served some pages over HTTP. On an all-HTTPS site it adds nothing over just writing https://, and it hides intent from anyone reading the markup later. Prefer an explicit https://.

3. Self-host the asset

If a third-party resource genuinely has no HTTPS version — rare now, but it happens with abandoned scripts and some regional providers — download it and serve it from your own HTTPS origin. You then control the protocol and remove a dependency on someone else's uptime.

4. Let the browser auto-upgrade (with a safety net)

Add this to your page <head> to tell the browser to retry HTTP sub-resources over HTTPS before loading them:

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

This is a cleanup tool, not a fix. It quietly upgrades requests where an HTTPS version exists, which is great for old image references buried in years of blog posts. It does not help when the resource has no HTTPS version — that request still fails. Treat it as a backstop while you replace the underlying URLs, not a reason to skip the work.

The Sources People Always Miss

The <script> and <img> tags are easy. These are the ones that slip through:

  • Inline CSS background-imagestyle="background:url('http://...')" buried in a hero section.
  • Database content — old blog posts and product descriptions with hardcoded http:// image URLs. A site-wide find-and-replace in your CMS database usually clears these in one pass.
  • Redirect responses — a resource requested over HTTPS that 301-redirects to HTTP. The initial request looks clean; the redirect target is the problem. Check the chain with our Redirect Chain Checker.
  • <form action> — a contact form posting credentials to an http:// endpoint. This is the most dangerous one, because the user is actively sending data over an unencrypted channel.
  • Hardcoded URLs in JavaScriptfetch('http://api.example.com/...') strings the HTML scanner won't catch but the console will, once the call fires.

Why This Matters Beyond the Padlock

A missing padlock costs you conversions — users abandon checkout when the browser stops vouching for the page. But there's an SEO angle too. HTTPS is a confirmed ranking signal, and a page that browsers flag as "Not fully secure" undercuts the trust that move was supposed to buy. (See Does HTTPS Affect SEO? for the full picture.)

Mixed content also interacts with your security headers. If you've set a strict Content Security Policy or HSTS, blocked sub-resources can cascade into more visible breakage. Audit those at the same time with the HTTP Header Checker.

A Two-Minute Workflow

  1. Load the broken page and open DevTools Console — note any "blocked" or "insecure" warnings.
  2. Run the page source through the HTTPS Mixed Content Checker to catch the resources that didn't fire on this load.
  3. Fix active content first (it's breaking features), then passive (it's killing the padlock).
  4. Swap http://https://, verify each HTTPS URL returns 200, and add upgrade-insecure-requests as a backstop.
  5. Reload, confirm the padlock is back, and re-scan to verify zero remaining http:// references.

Get to zero insecure sub-resources and the padlock returns, the blocked widgets load, and the browser goes back to telling your visitors the connection is safe — because now it actually is.

Ready to try it?

Detect insecure http:// resources loaded on an HTTPS page. Flags active content (scripts, styles, iframes, fonts, form actions) that browsers block outright and passive content (images, audio, video) that breaks your secure padlock — so every sub-resource ships over HTTPS.

🔒 HTTPS Mixed Content Checker — Free Online Tool

Get notified about new SEO tools

More free tools coming soon — keyword research, sitemap generator, and more.