A single unencrypted image request can kill your green padlock and tank your SEO authority. Mixed content—where HTTPS pages load HTTP resources—is one of the easiest security blunders to make, especially after migrations or when pulling data from third-party CMSes. In this article, we'll walk you through how to find and fix mixed content: patterns, pitfalls and fixes that protect both your users and your search rankings.
Understanding mixed content and why browsers block it
Mixed content occurs when a page served over HTTPS loads a resource (image, script, stylesheet, iframe) over HTTP. Browsers treat this as a security violation because an attacker on the network could intercept and modify that HTTP resource—potentially injecting malicious code or defacing your content.
Modern browsers handle mixed content in two ways:
- Passive mixed content (images, audio, video, fonts) is often still loaded but flagged with a warning. The user sees a broken padlock.
- Active mixed content (scripts, stylesheets, XHRs) is blocked outright. The resource fails to load and the page may break.
From an SEO perspective, Google's crawlers note the padlock status, and mixed content signals poor security practices. Combined with Core Web Vitals and user trust signals, this erodes your domain authority over time.
Browser console lists mixed content warnings
The quickest way to spot mixed content is to open your browser's Developer Tools. Navigate to your HTTPS homepage, open the Console tab, and look for warnings like this:
Mixed Content: The page at 'https://yoursite.com/' was loaded over HTTPS, but requested an insecure image 'http://cdn.example.com/banner.jpg'. This request has been blocked; the content must be served over HTTPS.Real-world scenario: We migrated an e-commerce platform from HTTP to HTTPS last quarter. The homepage looked fine, but the Console showed five warnings. Two came from product images stored in an old CDN still served via HTTP. Another came from a third-party review widget. A fourth was a tracking pixel from a legacy analytics vendor. The fifth was a font file from Google Fonts that hadn't been updated to HTTPS.
Here's how to systematically scan for these:
- Open DevTools on your homepage (F12 or right-click → Inspect).
- Go to the Console tab and set the filter to "mixed content" or "insecure".
- Note every resource that appears.
- Check the Network tab: click the img filter to isolate images, then sort by protocol (look for any HTTP requests).
- Repeat this on key pages: checkout, login, product pages, and user account sections where sensitive data flows.
Don't just spot-check one page. Build a quick crawl script using Puppeteer or Playwright to visit 100+ pages and log any mixed content warnings programmatically. Save the results to a spreadsheet so your team can prioritize fixes.
Update hardcoded HTTP URLs in the CMS
The most common source of mixed content is hardcoded http:// URLs baked into your database or CMS templates. This happens because:
- Legacy content editors entered full URLs instead of paths.
- Content was copied from external sources and pasted with HTTP links.
- A third-party tool or migration script didn't account for HTTPS.
- Image galleries or media libraries use absolute URLs instead of relative paths.
To fix this, start with a comprehensive audit. If you use a relational database, query for any URLs containing http://:
SELECT id, column_name, content
FROM posts
WHERE content LIKE '%http://%'
AND created_at > '2023-01-01';For WordPress or similar CMSes, use a find-and-replace plugin to swap http://yoursite.com with https://yoursite.com. Be careful: test this on staging first, and avoid replacing external links that genuinely use HTTP.
For images and media:
- If you control the CDN or storage, update its base URL to HTTPS and regenerate image URLs.
- If third-party content (ads, embeds, user-generated content) uses HTTP, rewrite it client-side using JavaScript before rendering.
- For static images, use relative paths in your templates:
/images/banner.jpginstead ofhttp://yoursite.com/images/banner.jpg.
Example fix for a Node.js/Express CMS:
// Middleware to rewrite HTTP URLs to HTTPS
app.use((req, res, next) => {
res.locals.rewriteUrl = (url) => {
if (!url) return url;
return url.replace(/^http:\/\//, 'https://');
};
next();
});
// In your template
<img src="<%= rewriteUrl(post.imageUrl) %>" alt="...">For large migrations, coordinate with your infrastructure team. Sometimes the simplest fix is setting up a reverse proxy or CDN rule that redirects HTTP requests to HTTPS at the edge, so you don't have to touch every database record.
Content-Security-Policy: upgrade-insecure-requests
While you're hunting down and fixing hardcoded URLs, you need a safety net. The upgrade-insecure-requests directive in your Content-Security-Policy (CSP) header tells browsers to silently rewrite all http:// resource requests to https:// before fetching them.
This is not a permanent solution—you should still fix the underlying URLs—but it buys you time and prevents users from seeing broken padlocks while your team works through the backlog.
Add this HTTP response header:
Content-Security-Policy: upgrade-insecure-requests;Or in your Express middleware:
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy', 'upgrade-insecure-requests');
next();
});For NestJS:
import { NestFactory } from '@nestjs/core';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy', 'upgrade-insecure-requests');
next();
});
await app.listen(3000);
}
bootstrap();Important caveats:
- Browsers only upgrade if they support CSP (most modern browsers do, but some older clients or API consumers may not).
- Upgraded requests may fail if the HTTP endpoint doesn't exist or doesn't support HTTPS.
- This doesn't fix third-party scripts or iframes that explicitly check for HTTPS or make their own security decisions.
Monitor your logs after deploying this header. Look for failures in the request logs where an http:// URL was attempted and the HTTPS version didn't respond. Fix those URLs in your database or content management system.
Crawl for HTTP resources after migrations
After you deploy your fixes, run a comprehensive crawl to verify everything is truly HTTPS. Rely on automation because manual spot-checks miss edge cases.
Use a headless browser crawler like Puppeteer to visit every page on your site and check the Network activity for any HTTP requests:
const puppeteer = require('puppeteer');
const fs = require('fs');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
const mixedContentIssues = [];
page.on('response', response => {
const request = response.request();
if (request.url().startsWith('http://') && !request.url().includes('localhost')) {
mixedContentIssues.push({
url: response.url(),
initiator: request.url()
});
}
});
const urlsToCheck = ['https://yoursite.com', 'https://yoursite.com/products', 'https://yoursite.com/checkout'];
for (const url of urlsToCheck) {
try {
await page.goto(url, { waitUntil: 'networkidle0' });
} catch (error) {
console.error(`Failed to load ${url}: ${error.message}`);
}
}
fs.writeFileSync('mixed-content-report.json', JSON.stringify(mixedContentIssues, null, 2));
await browser.close();
console.log(`Found ${mixedContentIssues.length} mixed content issues`);
})();Alternatively, use a commercial crawler like Screaming Frog or Semrush with their security audit modules. These tools are faster for large sites and catch issues that automated scripts might miss.
After crawling, categorize findings by severity:
- Critical: JavaScript files, stylesheets, or iframes served over HTTP (these break the page or enable code injection).
- High: Third-party tracking or analytics scripts over HTTP (compromise user privacy and site functionality).
- Medium: Images or fonts over HTTP (visual indicators of insecurity, but don't break core functionality).
- Low: External links on your page that use HTTP (you can't control these, but ensure your own resources are secure).
Create a tracking issue or dashboard so the team can see progress. Aim for zero critical and high-severity issues within two weeks of migration.
Common mistakes
Mistake 1: Assuming the CSP header is a permanent fix. It's not. Upgrade-insecure-requests is a band-aid. Browsers may stop supporting it, and users with older clients won't benefit. Always replace the hardcoded URLs in your source.
Mistake 2: Only checking your homepage. Mixed content hides on deep pages, category archives, user-generated content, and old blog posts. Crawl at least 5–10% of your site, including every template and content type.
Mistake 3: Forgetting about third-party embeds. Review widgets, comment systems, analytics, and ad networks often load over HTTP. Audit your vendor contracts and escalate requests to upgrade to HTTPS. If they refuse, find a replacement.
Mistake 4: Not testing on staging before pushing to production. A find-and-replace that swaps http://yoursite.com to https://yoursite.com might break links to legitimate external resources. Always test the migration on a staging environment first and verify with real users.
Mistake 5: Ignoring HTTP redirects. If you're still serving content over HTTP and relying on redirects to HTTPS, search engines may crawl both versions, leading to duplicate content penalties. Ensure all traffic is HTTPS from the edge (via your web server or load balancer configuration).
Key takeaways
- Open the browser console on every key page and filter for mixed content warnings. A single HTTP image can break the padlock and signal poor security to users and crawlers.
- Query your database and CMS for hardcoded
http://URLs and batch-replace them withhttps://or relative paths. Test on staging first. - Deploy a
Content-Security-Policy: upgrade-insecure-requestsheader as a temporary safety net while your team fixes the underlying URLs. Monitor logs for upgrade failures. - Run automated crawls with Puppeteer or commercial tools to verify zero mixed content across your entire site. Categorize findings by severity and track fixes in a visible dashboard.
- After migration, check third-party vendors and user-generated content. Don't assume your content is secure just because your homepage loads over HTTPS.






Comments
Loading comments…