Mixed Content: Browser Blocking HTTP Resources on an HTTPS Page

An HTTPS page loading scripts/images/iframes over plain http:// gets them silently stripped by the browser. Find the offending http:// URLs, upgrade or proxy them — never disable the protection.

What you'll see

Root causes

Hardcoded http:// asset URLs in templates/CMS content

protocol-relative or https:// missing on images, iframes, script/css tags. view-source + grep 'http://' finds them in seconds.

Protocol-relative pitfalls and 301 loops

//example.com works but http://example.com in a redirect chain reintroduces mixed content; some old CDNs 301 https → http (mixed-content redirect blocks).

Fix it

  1. List the offending URLs (console shows each one)
    # DevTools console: each blocked URL is listed. Or: curl -s https://site/ | grep -oE 'http://[^"]*' | sort -u | head
  2. Upgrade the URLs to https:// (or protocol-relative)
    # https://cdn.example.com/app.js  — verify each upgraded URL actually serves TLS first
  3. Serve an Upgrade-Insecure-Requests header as a safety net
    add_header Content-Security-Policy 'upgrade-insecure-requests' always;   # browser rewrites http:// to https:// automatically
  4. If the third-party asset has no HTTPS at all: proxy or drop it
    # proxy_pass through your own TLS origin, or replace the dependency — never allow an insecure iframe/script just to keep it working

Field note

'Passive' mixed content (images) degrades to warnings; 'active' (scripts, iframes, XHR) is blocked outright — that asymmetry explains partially-broken pages. HSTS + upgrade-insecure-requests together make the failure mode impossible to reintroduce silently.

Common questions

Why do only images break while scripts load fine?

Browsers treat images as passive mixed content (allowed with a warning) but block active content (scripts, frames, fetch). Partial breakage is the signature of mixed content.

What does upgrade-insecure-requests actually do?

It tells the browser to rewrite every same-site http:// subresource request to https:// before sending it. It fixes stragglers without a code sweep, but the underlying URLs should still be cleaned up.

Ship it right the first time

Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.

Browse the template store →

One-time. Yours to modify. Instant download from the NinjaOps template store.