Security Analysis

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

SiteSecurityScore Team·8 min read·Updated Feb 20, 2026
Cybersecurity shield protecting web connections from mixed content vulnerabilities

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 WP-CLI
# 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

Apache .htaccess
# Force HTTPS redirect
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Nginx

nginx.conf
# 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.

Server configuration
# 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.

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.

CSP Report-Only
# 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.

Was this helpful?
Share

Check Your Site for Mixed Content

Scan your website to detect mixed content, missing HTTPS redirects, and related security header issues in one report.