Mixed Content: What It Is and How to Fix It
Why loading HTTP resources on an HTTPS page weakens your security, and how to eliminate it for good
What is Mixed Content?#
Mixed content occurs when a page loaded over HTTPS also requests resources (scripts, stylesheets, images, iframes) over plain HTTP. The HTTPS connection encrypts the page itself, but the HTTP sub-resources travel unencrypted. An attacker on the same network can intercept or modify those HTTP resources in transit, undermining the security of the entire page.
There are two categories. Active mixed content includes scripts, stylesheets, iframes, and other resources that can change the behavior or appearance of the page. Because a modified script can steal credentials, read cookies, or redirect the user, browsers have blocked active mixed content by default since around 2015. Passive mixed content (also called display mixed content) includes images, audio, and video. These cannot execute code, but they can still be swapped by an attacker to show misleading content or track which pages a user visits.
Even if a single image loads over HTTP on an otherwise secure page, the browser removes the padlock icon from the address bar. Users lose the visual confirmation that the connection is secure, which erodes trust.
How Browsers Handle Mixed Content in 2026#
Browser handling has become stricter over time. Active mixed content (scripts, stylesheets, iframes) has been blocked by all major browsers since around 2015. If your HTTPS page tries to load a script over HTTP, the browser silently blocks it and logs an error in the Console.
Passive mixed content (images, audio, video) was historically allowed with a warning, but modern browsers now auto-upgrade these requests to HTTPS. Chrome, Firefox, and Safari all attempt to load the resource over HTTPS first. If the HTTPS version is not available, the resource is blocked entirely. This means that even passive mixed content that "worked" a few years ago may now fail if the resource server does not support HTTPS.
Active Mixed Content
Scripts, stylesheets, iframes, fetch/XHR, Web Workers
- Blocked by all browsers since 2015
- Can steal data, hijack sessions, modify page content
- Errors appear in DevTools Console
Passive Mixed Content
Images, audio, video, favicons
- Auto-upgraded to HTTPS by modern browsers
- Blocked if HTTPS version is unavailable
- Removes padlock icon from address bar
Finding Mixed Content on Your Site#
Mixed content can hide in places you do not expect: database-stored content, CMS templates, third-party widgets, or hardcoded URLs in stylesheets. A systematic approach ensures you find all of it.
Browser DevTools Console
Open Developer Tools (F12), navigate through your site, and watch the Console tab. Mixed content warnings appear as yellow or red messages with the text "Mixed Content" followed by the blocked URL. Check every page, not just the homepage, since different pages may load different resources.
Network Tab Filtering
In the DevTools Network tab, look for requests with a "scheme" column showing "http" while the page itself loaded over "https". In Chrome, you can also use the "mixed-content:displayed" and "mixed-content:blocked" filters in the search bar to isolate these requests.
Automated Scanning
Run a scan on SiteSecurityScore to check for mixed content alongside your other security headers. Automated tools crawl multiple pages and catch issues that manual browsing might miss, including resources loaded by JavaScript after the initial page render.
Source Code Search
Search your codebase for hardcoded http:// URLs in HTML templates, CSS files, and JavaScript. For CMS-based sites, also check the database for stored content that references HTTP URLs (common in WordPress post content, widget settings, and theme options).
Fixing Mixed Content#
The core fix is straightforward: change every HTTP URL to HTTPS. In practice, this involves several sources and a few edge cases worth noting.
Update Hardcoded URLs
Search your HTML, CSS, and JavaScript files for http:// and replace with https://. Verify that each external resource actually supports HTTPS before changing it. Most CDNs and major services do, but some legacy or self-hosted resources may not.
CMS Database Migration
Content management systems store URLs in the database. WordPress, for example, stores absolute URLs in post content, widget settings, and options. A search-and-replace in the database (using a tool like WP-CLI or a migration plugin) is necessary to convert these from HTTP to HTTPS.
# WordPress: search-replace using WP-CLI wp search-replace 'http://example.com' 'https://example.com' --all-tables
Server-Side Redirects
Ensure your server redirects all HTTP traffic to HTTPS. This prevents users from accidentally accessing the site over HTTP. Use a 301 (permanent) redirect so browsers and search engines update their cached URLs.
Apache
# Force HTTPS redirect
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]Nginx
# Redirect HTTP to HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}Avoid protocol-relative URLs
Protocol-relative URLs like //cdn.example.com/script.js inherit the protocol of the current page. While this seems like a convenient fix, it means the resource loads over HTTP when the page is accessed over HTTP (for example, during local development or if the redirect fails). Always use explicit https:// URLs instead.
Using HTTP Headers to Prevent Mixed Content#
Two security mechanisms can automatically upgrade HTTP requests to HTTPS, serving as a safety net for any URLs you missed during the manual fix. These do not replace fixing the source URLs, but they catch edge cases and prevent regression.
Upgrade-Insecure-Requests Header
The Upgrade-Insecure-Requests response header (not to be confused with the identically named client hint) tells the browser to treat all HTTP URLs on the page as if they were HTTPS. The browser rewrites each request from http:// to https:// before sending it.
# Apache
Header always set Content-Security-Policy "upgrade-insecure-requests"
# Nginx
add_header Content-Security-Policy "upgrade-insecure-requests" always;
# Node.js / Express
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy', 'upgrade-insecure-requests');
next();
});CSP upgrade-insecure-requests Directive
If you already have a Content-Security-Policy header, you can add upgrade-insecure-requests as a directive within it. This has the same effect as the standalone header. The directive is useful when you want all your security policies in a single CSP header.
Content-Security-Policy: upgrade-insecure-requests; default-src 'self'; script-src 'self' https://cdn.example.com
Safety net, not a solution
upgrade-insecure-requests only works when the resource server supports HTTPS. If the server at http://old-cdn.example.com does not have an HTTPS certificate, the upgraded request will fail. Always fix the source URLs first and use the header as a fallback for any you might have missed.
Testing and Preventing Regression#
After fixing existing mixed content, put safeguards in place to prevent it from coming back. New content, third-party updates, and CMS changes can reintroduce HTTP URLs at any time.
Manual DevTools Verification
After deploying fixes, open DevTools on every major page of your site and verify the Console shows no mixed content warnings. Check the padlock icon in the address bar. A full padlock without warnings confirms the page is fully secure.
CSP Reporting for Ongoing Monitoring
Set up a Content-Security-Policy with a report-uri or report-to directive. CSP violations triggered by mixed content will be sent to your reporting endpoint, alerting you when new HTTP resources appear on any page.
# Report mixed content violations without blocking Content-Security-Policy-Report-Only: default-src https:; report-uri /csp-report
HSTS as a Permanent Fix
Once all mixed content is resolved, deploy HTTP Strict Transport Security (HSTS). This header tells browsers to only connect over HTTPS, which prevents HTTP requests from being made in the first place. Combined with upgrade-insecure-requests, HSTS ensures comprehensive protection.
Regular Automated Scans
Schedule periodic scans with SiteSecurityScore to catch any mixed content that appears after CMS updates, new content, or third-party widget changes. Automated scans ensure issues are found before they affect users.
Continue reading
Check Your Site for Mixed Content
Scan your website to detect mixed content, missing HTTPS redirects, and related security header issues in one report.