SSL Mixed Content Warning on HTTPS Sites – Fixes That Work
Your HTTPS site loads but shows a padlock warning because some resources are still HTTP. The fix is almost always in the HTML, CSS, or JS. I'll walk you through the three most common causes and their exact fixes.
1. Hardcoded HTTP Links in HTML or Database
This is the culprit in 80% of cases. You moved your site to HTTPS, but somewhere in your HTML – a template, a theme, or an old post – there's a direct http:// URL for an image, script, or stylesheet. Browsers see that and immediately flag it.
Where it hides: Images embedded in blog posts, third-party widgets, CDN URLs you forgot to update, and footer scripts. WordPress users: it's almost always in the wp_posts table or your theme's header.php.
Fix #1: Search-and-Replace in Database
Don't do it manually – you'll miss something. Use a tool like Better Search Replace (WordPress plugin) or wp-cli if you're comfortable on the command line. Run a search for http://yourdomain.com and replace with https://yourdomain.com. But do not blindly replace every HTTP – you'll break external links. Only replace your own domain.
For non-WordPress sites, run a grep on your source files:
grep -rn 'http://yourdomain.com' /var/www/html/
Then fix each file manually or with sed. I've seen sites with 300+ hardcoded HTTP links in a single template – the search-and-replace saves hours.
Pro tip: After the replace, clear your cache (server, CDN, browser) and reload the page. Open Chrome DevTools (F12), go to Console. Any mixed content warnings left? They'll show up there with the exact URL.
2. External Scripts or Fonts Loaded Over HTTP
Your own content is fine, but you're pulling in something from a third-party – Google Fonts, a jQuery CDN, an analytics script – and that resource is served over HTTP. The browser treats it the same as a local HTTP resource. Annoying, but fixable.
Real-world example: I had a client whose site worked fine on HTTPS, but the footer loaded a font from http://fonts.googleapis.com. Chrome flagged it. One line change fixed it.
Fix #2: Change the Protocol to // (Protocol-Relative)
Instead of http://fonts.googleapis.com/css or https://fonts.googleapis.com/css, use //fonts.googleapis.com/css. The browser picks the protocol that matches the page. This works for most modern browsers and all CDNs that support both HTTP and HTTPS.
If the external service doesn't support HTTPS at all (rare in 2024, but I've seen it with old ad networks), you need to either drop that resource or host it locally. Don't waste time trying to force HTTPS on a service that doesn't support it – you'll break the script.
Check your and tags. Updating them to protocol-relative URLs is a two-minute fix. Do it.
3. The Web Server Serves Mixed Content Through Redirects
Less common but nasty. Your page loads over HTTPS, but your server redirects an internal resource (like an image) from HTTPS to HTTP. This triggers mixed content even though your HTML looks clean. The redirect chain is the problem.
Trigger: Happens often when you have a reverse proxy or load balancer (like Nginx or HAProxy) that terminates HTTPS, but the backend server (Apache, IIS) generates URLs with HTTP because it doesn't see the original scheme.
Fix #3: Force HTTPS in Server Config or Application
For Nginx, add this to your server block to set the X-Forwarded-Proto header:
proxy_set_header X-Forwarded-Proto $scheme;
Then in your app (WordPress, Laravel, etc.), tell it to trust that header. For WordPress, add this to wp-config.php:
$_SERVER['HTTPS'] = 'on';
For custom PHP apps, check your URL generation functions. They often use $_SERVER['SERVER_PORT'] or $_SERVER['HTTPS'] – if those aren't set right, you get HTTP URLs in the response.
Also, use the Content-Security-Policy header with upgrade-insecure-requests. This tells the browser to automatically upgrade any HTTP resource to HTTPS. It's a band-aid, not a real fix, but it can hide the warning while you fix the root cause. Add this to your server config:
add_header Content-Security-Policy "upgrade-insecure-requests";
This won't fix resources that only exist over HTTP (the browser will fail to load them), but it silences the warning for everything else.
Quick-Reference Summary
| Cause | How to Check | Fix | Time to Fix |
|---|---|---|---|
| Hardcoded HTTP in HTML/database | Chrome Console, grep files | Search-and-replace in DB or files | 15–60 min |
| External scripts/fonts on HTTP | Check and tags in page source |
Change to protocol-relative URLs or host locally | 5–20 min |
| Server redirects from HTTPS to HTTP | Curl with -I to see redirect chain |
Fix proxy headers, use upgrade-insecure-requests |
30–90 min |
Start with Cause #1. That's where you'll almost always find it. If not, move to Cause #2. Cause #3 is the rare bird but will make you look like a hero when you find it.
Was this solution helpful?