The Problem
When a page is loaded over HTTPS, browsers block any resources (images, scripts, stylesheets, iframes) loaded over HTTP. This is called "mixed content" and is a security risk.
Symptoms
- Console error: "Mixed Content: The page was loaded over HTTPS but requested an insecure resource"
- Images, fonts, or scripts do not load on production
- Page looks broken on HTTPS but works on HTTP
- Works in development (HTTP) but not production (HTTPS)
Real Error Message
Mixed Content: The page at 'https://example.com/' was loaded over HTTPS,
but requested an insecure image 'http://cdn.example.com/image.jpg'.
This request has been blocked; the content must be served over HTTPS.Types of Mixed Content
- Passive (images, audio, video): Browser shows warning, may block
- Active (scripts, styles, iframes): Browser ALWAYS blocks
How to Fix It
Fix 1: Use Protocol-Relative URLs
<!-- Instead of http:// or https:// -->
<img src="//cdn.example.com/image.jpg">
<script src="//cdn.example.com/lib.js"></script>Note: This is considered legacy. Prefer explicit HTTPS.
Fix 2: Use Explicit HTTPS URLs
<img src="https://cdn.example.com/image.jpg">
<link href="https://fonts.googleapis.com/css2?family=Roboto" rel="stylesheet">Fix 3: Upgrade-Insecure-Requests Header
# nginx.conf - automatically upgrade HTTP to HTTPS
add_header Content-Security-Policy "upgrade-insecure-requests" always;<!-- Or via meta tag -->
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">Fix 4: Find and Fix Hardcoded HTTP URLs
```bash # Search your codebase for http:// grep -r "http://" src/ --include="*.html" --include="*.js" --include="*.css"
# Check database content for HTTP URLs SELECT * FROM posts WHERE content LIKE '%http://%'; ```
Fix 5: Handle Dynamic Content URLs
```javascript // If URLs come from a CMS or API, ensure they use HTTPS function ensureHttps(url) { return url.replace(/^http:///i, 'https://'); }
<img src={ensureHttps(user.avatarUrl)} alt="Avatar"> ```
Fix 6: Debug with Browser DevTools
- 1.Open Chrome DevTools Security tab
- 2.Click "View certificate" to verify HTTPS
- 3.Check the Security panel for mixed content warnings
- 4.Use the Console to see all blocked resources