Mixed Content
What This Means
Mixed content occurs when an HTTPS webpage loads resources (images, scripts, stylesheets, iframes) over an insecure HTTP connection. This compromises the security of the entire page, triggers browser warnings, and can cause resources to be blocked entirely.
Types of Mixed Content
Active Mixed Content (Blocked):
- JavaScript files loaded over HTTP
- CSS stylesheets loaded over HTTP
- Fonts loaded over HTTP
- Iframes loaded over HTTP
- Result: Browsers block these resources entirely
Passive Mixed Content (Warning):
- Images loaded over HTTP
- Audio files loaded over HTTP
- Video files loaded over HTTP
- Result: Browsers load but show warnings
Impact on Your Business
Security Compromise:
- Entire page marked as "Not Secure"
- Users warned of security risk
- Man-in-the-middle attack vulnerability
- Compromised encryption benefits
Broken Functionality:
- Blocked scripts break features
- Missing CSS breaks layout
- Blocked fonts cause display issues
- Iframes don't load
User Trust:
- Security warnings damage credibility
- Users abandon insecure pages
- Conversion rates plummet
- Professional image damaged
SEO Impact:
- Search engines prefer secure sites
- User experience signals hurt rankings
- Trust signals diminished
- May impact search visibility
How to Diagnose
Method 1: Chrome DevTools Console
- Open your website in Chrome (HTTPS version)
- Press
F12to open DevTools - Navigate to "Console" tab
- Look for mixed content warnings:
Mixed Content: The page at 'https://example.com/' was loaded over HTTPS, but requested an insecure image 'http://example.com/image.jpg'. This content should also be served over HTTPS.
What to Look For:
- Yellow warning icon (passive mixed content)
- Red error icon (active mixed content blocked)
- Resource URLs starting with
http:// - Number and type of mixed content issues
Method 2: Chrome Security Panel
- Open your website
- Press
F12to open DevTools - Navigate to "Security" tab
- Review "Overview" section
- Check "Mixed content" section for details
What to Look For:
- "This page has mixed content" warning
- List of insecure resources
- Type of mixed content (active/passive)
- Resource URLs
Method 3: Why No Padlock Tool
- Visit Why No Padlock
- Enter your website URL
- Click "Test"
- Review list of insecure resources
What to Look For:
- All HTTP resources listed
- Resource types (images, scripts, CSS)
- Source URLs
- Quick fix suggestions
Method 4: View Page Source
- Visit your page (HTTPS version)
- Right-click → "View Page Source" (
Ctrl+U) - Search for
http://(nothttps://) - Review each result
What to Look For:
<!-- Mixed content examples -->
<img src="http://example.com/image.jpg">
<script src="http://example.com/script.js"></script>
<link href="http://example.com/style.css" rel="stylesheet">
<iframe src="http://example.com/embed"></iframe>
Method 5: Browser Network Tab
- Open Chrome DevTools (
F12) - Navigate to "Network" tab
- Reload page
- Filter by "All" or "Other"
- Look for resources with:
- HTTP protocol
- "blocked:mixed-content" status
What to Look For:
- Requests with
http://protocol - Blocked or failed requests
- Status showing mixed content block
- Resource types affected
General Fixes
Fix 1: Update Resource URLs to HTTPS
Convert HTTP URLs to HTTPS:
Images:
<!-- Before --> <img src="http://example.com/image.jpg" alt="Product"> <!-- After --> <img src="https://example.com/image.jpg" alt="Product">Scripts:
<!-- Before --> <script src="http://example.com/script.js"></script> <!-- After --> <script src="https://example.com/script.js"></script>Stylesheets:
<!-- Before --> <link href="http://example.com/style.css" rel="stylesheet"> <!-- After --> <link href="https://example.com/style.css" rel="stylesheet">Iframes:
<!-- Before --> <iframe src="http://example.com/embed"></iframe> <!-- After --> <iframe src="https://example.com/embed"></iframe>
Fix 2: Use Protocol-Relative URLs
Let browser choose protocol:
Remove protocol prefix:
<!-- Before --> <img src="http://cdn.example.com/image.jpg"> <!-- After - protocol-relative --> <img src="//cdn.example.com/image.jpg">Works for both HTTP and HTTPS pages:
- On HTTPS page: Loads as
https://cdn.example.com/image.jpg - On HTTP page: Loads as
http://cdn.example.com/image.jpg
- On HTTPS page: Loads as
Apply to all external resources:
<script src="//ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <link href="//fonts.googleapis.com/css?family=Roboto" rel="stylesheet"> <img src="//cdn.example.com/logo.png" alt="Logo">Note: Modern best practice is to use HTTPS explicitly
Fix 3: Use Relative URLs for Internal Resources
Best practice for same-domain resources:
Use root-relative URLs:
<!-- Before - absolute with protocol --> <img src="http://example.com/images/product.jpg"> <!-- After - root-relative --> <img src="/images/product.jpg">Benefits:
- Works on both HTTP and HTTPS
- No protocol specification needed
- Easier to maintain
- Works in dev and production
Examples:
<link href="/css/style.css" rel="stylesheet"> <script src="/js/script.js"></script> <img src="/images/logo.png" alt="Logo">
Fix 4: Fix CSS Background Images
Update URLs in stylesheets:
Check CSS files for HTTP URLs:
/* Before */ .hero { background-image: url('http://example.com/hero.jpg'); } /* After */ .hero { background-image: url('https://example.com/hero.jpg'); } /* Best - relative URL */ .hero { background-image: url('/images/hero.jpg'); }Check inline styles:
<!-- Before --> <div style="background-image: url('http://example.com/bg.jpg')"></div> <!-- After --> <div style="background-image: url('/images/bg.jpg')"></div>
Fix 5: Fix Third-Party Resources
Ensure external resources use HTTPS:
Google Fonts:
<!-- Before --> <link href="http://fonts.googleapis.com/css?family=Roboto" rel="stylesheet"> <!-- After --> <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">CDN Resources:
<!-- Before --> <script src="http://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <!-- After --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>Social Media Embeds:
<!-- Ensure embed codes use HTTPS --> <iframe src="https://www.youtube.com/embed/VIDEO_ID"></iframe> <iframe src="https://www.facebook.com/plugins/page.php"></iframe>Check if third-party supports HTTPS:
- Try HTTPS version in browser
- If not available, find alternative provider
- Or self-host the resource
Fix 6: Use Content Security Policy Upgrade
Automatically upgrade HTTP to HTTPS:
Add CSP header:
# Nginx add_header Content-Security-Policy "upgrade-insecure-requests";# Apache .htaccess Header always set Content-Security-Policy "upgrade-insecure-requests"Or use meta tag:
<head> <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> </head>How it works:
- Browser automatically upgrades HTTP requests to HTTPS
- Applies to all resources on page
- Fallback: Block if HTTPS version unavailable
Note: This is a temporary fix - better to fix URLs directly
Fix 7: Fix Dynamic Content and JavaScript
Update JavaScript-generated URLs:
Check JavaScript files:
// Before var img = document.createElement('img'); img.src = 'http://example.com/image.jpg'; // After img.src = 'https://example.com/image.jpg'; // Best - use relative URL img.src = '/images/image.jpg';Fix AJAX requests:
// Before fetch('http://api.example.com/data') // After fetch('https://api.example.com/data') // Or relative fetch('/api/data')Update API endpoints:
// Use HTTPS for all API calls const API_URL = 'https://api.example.com';Check third-party scripts:
- Analytics code
- Ad scripts
- Chat widgets
- Ensure all use HTTPS
Platform-Specific Guides
Detailed implementation instructions for your specific platform:
Verification
After fixing mixed content:
Clear browser cache:
- Hard refresh:
Ctrl+Shift+R(Windows) orCmd+Shift+R(Mac) - Or clear cache in browser settings
- Hard refresh:
Check Chrome Console:
- Open DevTools Console
- Reload page
- Verify no mixed content warnings
- Should see green padlock in address bar
Test with Why No Padlock:
- Run test again
- Should show "All Clear"
- No insecure resources listed
Check Security Panel:
- DevTools → Security tab
- Should show "Secure connection"
- No mixed content warnings
Test all pages:
- Homepage
- Product/category pages
- Blog posts
- Contact forms
- Checkout (if applicable)
Test in multiple browsers:
- Chrome
- Firefox
- Safari
- Edge
Common Mistakes
- Hardcoded HTTP URLs - Use relative or HTTPS
- HTTP in CSS - Check background-image URLs
- Third-party embeds - Ensure HTTPS versions
- Cached resources - Clear cache after fixing
- JavaScript-generated URLs - Update API endpoints
- Content in database - Search and replace old URLs
- Ignoring passive mixed content - Fix images too
- Not testing all pages - Some pages may still have issues
- Using HTTP for performance - HTTPS is now faster
- Forgetting mobile version - Test responsive/mobile site
Troubleshooting Checklist
- All images use HTTPS or relative URLs
- All scripts use HTTPS
- All stylesheets use HTTPS
- All iframes use HTTPS
- CSS background images use HTTPS
- Font files use HTTPS
- Third-party resources use HTTPS
- JavaScript-generated URLs use HTTPS
- API endpoints use HTTPS
- Database content updated (if hardcoded URLs)
- Browser cache cleared
- No console warnings
- Padlock appears in address bar
- Tested all major pages
- Tested in multiple browsers
Quick Fixes by Resource Type
Images:
<!-- Find and replace in all files -->
<img src="http:// → <img src="https://
<img src="http:// → <img src="//
<img src="http://yoursite.com/ → <img src="/
Scripts:
<script src="http:// → <script src="https://
Stylesheets:
<link href="http:// → <link href="https://
CSS:
url('http:// → url('https://
url("http:// → url("https://