Skip to main content

    Mixed Content Errors: What They Are and How to Fix Them

    Mixed content errors occur when an HTTPS page loads HTTP resources. Learn active vs passive types, how browsers handle them, and step-by-step fixes.

    MS
    My-SSL Security Team
    ·
    13 min read
    ·Published June 3, 2026

    You've installed your SSL certificate. Your URL bar shows HTTPS. But the padlock icon is gone — replaced by a warning triangle, or absent entirely. The culprit is almost always mixed content: your HTTPS page is loading one or more resources over HTTP.

    Mixed content doesn't mean your certificate is broken. It means some URLs embedded in your HTML, CSS, or JavaScript still point to http:// — usually because they were written before the site moved to HTTPS and were never updated. (Seeing a full-page certificate warning instead of a missing padlock? That's a different class of problem — our SSL certificate errors guide decodes those by error code.) This guide explains what mixed content is, how browsers respond to it, how to find every affected URL, and how to fix it for good.

    Installed SSL but still missing the padlock?

    Mixed content is the most common reason an HTTPS site lacks a secure padlock after SSL installation. Use My-SSL's free SSL Checker to confirm your certificate is valid and your chain is complete, then follow this guide to identify and eliminate the HTTP resources on your page.

    What is mixed content?

    A web page has mixed content when its main document is delivered over HTTPS but one or more of the sub-resources it requests — images, scripts, stylesheets, fonts, iframes, audio, or video — are fetched over HTTP. The HTTP requests travel in plaintext over the network while the page itself is encrypted. An attacker on the same network could observe or tamper with those resources even though the page's own channel is secure.

    From the browser's perspective, the security of a page is only as strong as its weakest sub-resource. A script loaded over HTTP can be modified in transit to inject arbitrary JavaScript into the page. An image can reveal what the user is viewing. Even a stylesheet can leak layout information through CSS timing. This is why browsers don't just warn about mixed content — they block or auto-upgrade it.

    Common sources of mixed content

    • Hardcoded URLs in templates or CMS content — written as http://example.com/image.jpg before HTTPS migration and never updated
    • Third-party embeds — widgets, social buttons, analytics tags, or ad networks that serve their assets over HTTP
    • CSS background images background-image: url('http://...') in inline styles or stylesheets
    • JavaScript that builds URLs dynamically — code that constructs HTTP URLs at runtime based on a hardcoded scheme
    • Database-stored content — in CMS platforms like WordPress, older posts often contain absolute HTTP URLs stored in the database that templates render as-is
    • Form actions — a form that submits data to an HTTP endpoint even when the page itself is served over HTTPS

    Active vs passive mixed content

    Not all mixed content carries the same risk. Browsers and the W3C Mixed Content specification separate it into two categories based on how much damage a compromised resource can cause.

    Active mixed content

    Resources that can read or modify the DOM, execute code, or intercept user interactions. The highest risk category.

    • <script src="http://...">
    • <link rel="stylesheet" href="http://...">
    • <iframe src="http://...">
    • XMLHttpRequest / fetch() to HTTP URLs
    • <object> and <embed> over HTTP
    Browser action: blocked — the request is not sent

    Passive mixed content

    Resources that are displayed but cannot alter page behavior or execute code. Lower risk, but still observable by a network attacker.

    • <img src="http://...">
    • <video src="http://...">
    • <audio src="http://...">
    • CSS background-image: url('http://...')
    Browser action: auto-upgraded to HTTPS; blocked if HTTPS fails

    The practical implication: active mixed content is a hard failure — the browser will not load the resource at all, which can break page functionality visibly. Passive mixed content was once merely a warning, but modern browsers now auto-upgrade it (see the next section), so the effective result is the same: the resource either loads securely or doesn't load at all.

    How browsers handle mixed content in 2026

    Browser enforcement has tightened considerably over the past several years. Here is the current behavior across the major browsers:

    Content typeChromeFirefoxSafari
    Scripts (script)BlockedBlockedBlocked
    Stylesheets (link)BlockedBlockedBlocked
    IframesBlockedBlockedBlocked
    ImagesAuto-upgradedAuto-upgradedBlocked / warned
    Audio / VideoAuto-upgradedAuto-upgradedBlocked / warned
    XHR / fetchBlockedBlockedBlocked

    Auto-upgrade means the browser silently replaces http:// with https:// before sending the request. If the resource is not available over HTTPS, the browser blocks it — there is no HTTP fallback. Chrome introduced auto-upgrade for audio and video in M80 (January 2020) and for images in M86 (October 2020), as documented in the Chromium autoupgrade docs. Firefox adopted equivalent behavior for passive mixed content.

    What this means for your site: Even "passive" mixed content is no longer merely a warning. If an image exists only at http:// and the server does not respond on port 443, the browser blocks it and the image does not display. Fix the source URL rather than relying on auto-upgrade to save you.

    How to find mixed content

    Before you can fix mixed content, you need to locate every HTTP resource. Several complementary approaches work together to give complete coverage.

    1. Browser DevTools Console

    The quickest method for a single page. Open DevTools (F12 on Windows/Linux, ⌘ Opt I on macOS), click the Console tab, and navigate to the page. Blocked or upgraded mixed content appears as a message starting with Mixed Content:. Each message includes the exact URL of the HTTP resource and which element triggered it.

    [blocked] Mixed Content: The page at 'https://example.com/' was loaded over HTTPS, but requested an insecure resource 'http://example.com/scripts/analytics.js'. This request has been blocked; the content must be served over HTTPS.

    [autoupgraded] Mixed Content: 'http://cdn.example.com/banner.jpg' automatically upgraded to HTTPS.

    2. DevTools Network tab

    In the Network tab, type mixed-content:blocked or mixed-content:displayed in the filter bar. This shows the full request list alongside response codes, sizes, and initiators — useful when the console messages alone don't make the source clear.

    3. Lighthouse Best Practices audit

    Chrome's Lighthouse tool (Audits or Lighthouse panel in DevTools) runs a Best Practices audit that includes a mixed-content check. It lists every HTTP resource URL it finds on the page, making it easy to export and share with your development team. A score of 100 on Best Practices confirms no mixed content issues remain.

    4. Grep your codebase

    If your site's HTML is generated from source templates, a targeted grep catches most hardcoded mixed content before it reaches production:

    # Search templates and source files for http:// src/href/url attributes

    grep -r '(src|href|url)=["'"'"']http://' --include="*.html" --include="*.css" --include="*.js" .

    Fixing mixed content

    There are four main approaches, and you will often use a combination of them. The right fix depends on whether the content is hosted by you or by a third party, and whether you can edit your server config or only your page templates.

    1. Update HTTP URLs to HTTPS

    The most direct fix: change every http:// URL in your markup, CSS, and JavaScript to https://. This works for any resource where the destination server supports HTTPS — which virtually all major CDNs, image hosts, and third-party providers now do.

    <!-- Before -->

    <img src="http://cdn.example.com/logo.png" alt="Logo">

    <!-- After -->

    <img src="https://cdn.example.com/logo.png" alt="Logo">

    2. Use protocol-relative URLs

    A protocol-relative URL omits the scheme entirely and inherits the protocol of the parent page: //cdn.example.com/file.js. When the page loads over HTTPS, the browser fetches the resource over HTTPS. This is useful for resources that genuinely need to work across both HTTP and HTTPS (e.g., a shared staging template). For production-only HTTPS sites, a direct https:// URL is clearer and avoids any ambiguity if the page were ever accidentally served over HTTP.

    3. Use relative URLs for self-hosted assets

    For resources you host yourself, a root-relative path is the cleanest solution: /images/logo.png instead of https://example.com/images/logo.png. Relative URLs inherit both scheme and host from the page and can never introduce mixed content.

    4. Fix WordPress mixed content

    WordPress is the most common source of mixed content complaints because post and page content is stored with absolute URLs in the database. Two reliable approaches:

    If you haven't yet installed an SSL certificate on your WordPress site, see our complete WordPress SSL installation guide — it covers the full process from choosing a certificate through forcing HTTPS and eliminating mixed content.

    Option A: Really Simple SSL plugin

    The Really Simple SSL plugin (available free in the WordPress plugin directory) scans your database for HTTP URLs, replaces them with HTTPS, and adds a upgrade-insecure-requests CSP header as a runtime safety net. It is the fastest path for shared-hosting WordPress installations.

    1. Install and activate Really Simple SSL from the plugin directory
    2. The plugin detects your certificate and prompts to activate HTTPS
    3. Click Activate SSL
    4. The plugin updates site URL settings and adds the CSP header

    Option B: WP-CLI search-replace

    For more control, use WP-CLI's built-in search-replace command to update all HTTP URLs in the database at once. Always take a database backup first.

    # Dry run first — see what would change

    wp search-replace 'http://example.com' 'https://example.com' --dry-run

    # Apply the replacement across all tables

    wp search-replace 'http://example.com' 'https://example.com' --all-tables

    The --all-tables flag covers custom tables created by plugins. Confirm a clean backup exists before running the live command.

    5. Replace or remove third-party HTTP resources

    If a third-party service you embed only supports HTTP, you have three options: find an HTTPS-capable alternative, self-host a copy of the asset, or remove it entirely. There is no safe way to load active mixed content. A blocked active resource can break your page; a blocked image or video simply won't display.

    CSP: upgrade-insecure-requests

    The upgrade-insecure-requests Content Security Policy directive instructs the browser to silently upgrade every HTTP sub-resource request on the page to HTTPS before sending it. Unlike fixing URLs in your HTML, this is a server-level directive that acts as a runtime safety net without requiring changes to existing content. It is defined in the MDN upgrade-insecure-requests documentation and is supported by all modern browsers.

    Sending the header

    Content-Security-Policy: upgrade-insecure-requests

    Or via a <meta> tag

    If you don't control server headers, place this in <head>:

    <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

    Important caveat

    upgrade-insecure-requests is a safety net, not a cure. If a resource does not exist over HTTPS, the browser blocks it rather than falling back to HTTP. Always fix the underlying URLs in your source content and use this directive as an additional layer for anything that might have been missed.

    Server-level configuration

    Adding upgrade-insecure-requests at the web server level applies the CSP directive to every response without editing individual files or templates. Here is how to do it on the three most common servers.

    Nginx

    Add inside your server block. If you already have a CSP header, extend the existing value rather than adding a second add_header directive:

    # /etc/nginx/sites-available/example.com

    server {

    listen 443 ssl;

    server_name example.com;

    # ... ssl_certificate, ssl_certificate_key, etc.

    add_header Content-Security-Policy "upgrade-insecure-requests" always;

    }

    sudo nginx -t && sudo systemctl reload nginx

    For a full Nginx SSL configuration including HSTS and OCSP stapling, see our Nginx SSL installation guide.

    Apache

    Ensure mod_headers is enabled (sudo a2enmod headers), then add to your VirtualHost:

    # /etc/apache2/sites-available/example.conf

    <VirtualHost *:443>

    ServerName example.com

    # ... SSLEngine on, SSLCertificateFile, etc.

    Header always set Content-Security-Policy "upgrade-insecure-requests"

    </VirtualHost>

    sudo apachectl configtest && sudo systemctl reload apache2

    IIS (Windows Server)

    Add the header in your site's web.config:

    <configuration>

    <system.webServer>

    <httpProtocol>

    <customHeaders>

    <add name="Content-Security-Policy" value="upgrade-insecure-requests" />

    </customHeaders>

    </httpProtocol>

    </system.webServer>

    </configuration>

    Consider adding HSTS alongside CSP

    Once your site is free of mixed content, HTTP Strict Transport Security (HSTS) prevents browsers from ever loading your pages over HTTP in the first place — eliminating the risk of a downgrade attack on the initial request. The two headers complement each other well.

    Verifying the fix

    After applying fixes, confirm mixed content is fully resolved before calling the work done.

    1

    Check the padlock

    Open the page in Chrome. A fully secured page shows a padlock icon in the address bar. Click it — the popup should read "Connection is secure" with no warnings about mixed content.

    2

    Clear the DevTools Console

    Reload the page with DevTools open. The Console should be free of any "Mixed Content:" messages. Also check the Network tab filtered by mixed-content:blocked.

    3

    Run a Lighthouse audit

    A Lighthouse Best Practices score of 100 confirms no mixed content issues remain. This also gives you a shareable record of the fix for your team or client.

    4

    Test on mobile

    Mobile browsers — especially iOS Safari — can behave differently from desktop Chrome on passive mixed content. Open the page on a physical device or use Chrome DevTools device emulation to confirm images and media display correctly.

    5

    Check beyond the homepage

    Mixed content often lives in old blog posts or product pages created before the HTTPS migration. Spot-check your most-visited pages and run a full-site crawl to catch anything that was missed.

    Need a valid SSL certificate to start?

    Mixed content only becomes an issue once your site is on HTTPS. If you haven't moved yet, browse our DV SSL certificates — from $3.99/year, issued in minutes.

    Frequently asked questions