All fix guides
CriticalSecurity & HTTPS

How to Fix Mixed Content Errors on HTTPS

Mixed content means your page loads over HTTPS but pulls in some resources (images, scripts, stylesheets, iframes) over plain HTTP. Browsers block or auto-upgrade those insecure requests, which strips the padlock, can break layout and functionality, and undermines the trust signal search and AI engines rely on. Fix it by finding every http:// reference, switching it to https://, correcting the source (usually stored content or theme settings, not just one page), and adding upgrade-insecure-requests as a backstop.

What this means

Mixed content happens when a page is delivered over a secure HTTPS connection but that page then requests one or more sub-resources over insecure HTTP. The main document is encrypted, but the browser has to reach back out over an unencrypted channel to fetch an image, script, stylesheet, font, iframe, video, or fetch/XHR endpoint whose URL still starts with http://.

Your audit flagged two related codes:

  • mixed_content — an insecure resource of any type on the page (the general case).
  • mixed_content_image — the common, specific case of an <img> or CSS background-image loading over HTTP.

Browsers treat two severity tiers differently:

  • Active (blockable) mixed content — scripts, stylesheets, iframes, fonts, fetch/XHR, and web workers. These can rewrite the whole page, so browsers refuse to load them. The result is broken layout, missing functionality, or a page that renders as unstyled HTML.
  • Passive (upgradable) mixed content — images, audio, and video loaded via <img>, <audio>, and <video>. Since Chrome 80/81, browsers auto-upgrade these HTTP requests to HTTPS. If the resource also exists on HTTPS it loads; if it does not, the request fails and the asset disappears.

Either way, the browser drops the fully-secure padlock and shows a "Not secure" indicator, and the audit records the page as not genuinely HTTPS.

Why it matters

Mixed content defeats the point of HTTPS. An attacker on the same network (public Wi-Fi, a compromised router, a hostile ISP) can intercept or tamper with any resource that travels over HTTP, even when the main page is encrypted. A hijacked script can steal form data, inject ads, or redirect the user, so the browser is right to treat it as a real vulnerability rather than a cosmetic warning.

For Google, HTTPS is a lightweight ranking signal, and its guidance treats a secure site as one where every resource loads securely. A page with mixed content is not fully HTTPS in the browser's eyes, so it undercuts the security you were trying to earn by installing the certificate. The visible "Not secure" badge and any broken styling or functionality also hurt conversions and bounce rate.

For AI answer engines (ChatGPT browsing, Perplexity, Google AI Overviews) the practical damage is content availability. When active mixed content is blocked, the parts of the page that depended on those scripts or stylesheets may never render, so a crawler reading the rendered DOM sees a broken or incomplete page. When passive image content fails the auto-upgrade, images vanish, weakening the visual and product context those engines might cite. A clean, fully-HTTPS page is also a baseline trust cue.

How to fix it

  1. 1

    Find every insecure resource

    Open the page in Chrome, then open DevTools (F12) and check the Console, the Issues tab, and the Security tab. The Console and Issues tab list each mixed-content warning with the exact HTTP URL; the Security tab summarizes which resources are insecure. Also view source and search for http://, src="http, and href="http to catch hardcoded links, inline styles, and content pasted into your CMS. Note whether each offender is a script, stylesheet, or iframe (active, blocked) or an image or media file (passive, auto-upgraded), because the active ones are what actually break the page.

  2. 2

    Rewrite each URL to HTTPS

    For every flagged resource, change http:// to https:// when the host serves the file over HTTPS (nearly all CDNs, font providers, and analytics do). Test the HTTPS version by pasting it in the address bar first. If a host has no HTTPS version at all, find an alternative source, self-host the file on your own HTTPS domain, or remove it. Use explicit https:// for third-party assets; for your own domain, root-relative paths like /images/logo.png inherit the page protocol and never go stale.

  3. 3

    Fix the source, not just the rendered HTML

    Mixed content usually comes from stored data, not your template. Check database content (old post bodies with http://yourdomain.com/... image URLs), theme and page-builder settings (logo, background, favicon fields), hardcoded paths in CSS/JS, and third-party embeds (old widget snippets, tracking pixels). Editing one page will not stop the warning from reappearing sitewide. Back up first, then run a database find-and-replace of http://yourdomain.com to https://yourdomain.com, or use your platform's migration tool.

  4. 4

    Add upgrade-insecure-requests as a backstop

    Set the upgrade-insecure-requests CSP directive so the browser rewrites any leftover http:// sub-resource to https:// before the request is made, which also clears the mixed-content flag. Send it as a response header (Content-Security-Policy: upgrade-insecure-requests) or, if you cannot edit headers, add the meta tag in your <head>. This is a safety net, not a fix: it only helps for resources that actually exist on HTTPS, and a genuinely HTTP-only asset will still fail. Do not use it as an excuse to leave broken references in your source.

  5. 5

    Re-crawl and confirm the padlock is clean

    After deploying, hard-reload (Ctrl+Shift+R) and confirm the Console shows zero mixed-content warnings and the address bar shows a full padlock with no 'Not secure' label. Spot-check reusable components (header, footer, sidebar) and a few content pages, since offenders often hide there. Then re-run your audit so the mixed_content and mixed_content_image flags clear across the whole site, not just the URL you started with.

Example

<!-- Meta tag: place in the <head>, before any resource references -->
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

<!-- BEFORE: insecure references flagged as mixed content -->
<img src="http://cdn.example.com/logo.png" alt="Logo">
<script src="http://example.com/app.js"></script>        <!-- active: BLOCKED -->
<link rel="stylesheet" href="http://example.com/main.css"> <!-- active: BLOCKED -->

<!-- AFTER: explicit HTTPS for third parties, root-relative for your own domain -->
<img src="https://cdn.example.com/logo.png" alt="Logo">
<script src="/assets/app.js"></script>
<link rel="stylesheet" href="/assets/main.css">

Add upgrade-insecure-requests to auto-upgrade any leftover HTTP resources. Prefer the response header; use the meta tag only if you can't edit headers.

Platform-specific steps

WordPress (Yoast / Rank Math)

Set both WordPress Address and Site Address to https:// under Settings > General. Neither Yoast nor Rank Math rewrites mixed content, so run a database search-replace of http://yourdomain.com to https://yourdomain.com with the Better Search Replace plugin or WP-CLI (wp search-replace), covering post content and serialized options. As a catch-all, the Really Simple SSL plugin enables upgrade-insecure-requests and rewrites resource URLs. Then re-save your logo and favicon in the Customizer, since those are stored separately.

Shopify

Shopify serves everything over HTTPS by default, so mixed content almost always comes from custom code: a hardcoded http:// URL in a theme file (Online Store > Themes > Edit code), an app snippet, or an external script or pixel added to theme.liquid. Search the theme files for http:// and switch to https://. Check custom Liquid sections and third-party embeds; if an external service has no HTTPS endpoint, replace it.

Wix

Wix hosts assets over HTTPS automatically, so the usual culprit is an HTML embed (Add > Embed > Embed HTML / Custom Code) that loads an http:// script, iframe, or image. Open each custom embed and rewrite the URLs to https://. If an embedded third-party tool only offers HTTP, ask that provider for an HTTPS version or remove the embed.

Squarespace

Squarespace forces HTTPS, so mixed content comes from Code Blocks, Code Injection (Settings > Advanced > Code Injection), or an image URL pointing at an external HTTP source. Edit each custom code area and change http:// to https://, and re-upload any externally-hosted images to Squarespace so they serve over HTTPS.

Raw HTML / Next.js

Grep your codebase and any CMS or markdown content for http:// in src, href, url(), and fetch calls, then switch to https:// or root-relative paths. In Next.js, use the <Image> component (which enforces configured https domains) and confirm environment variables and API base URLs use https://. Add Content-Security-Policy: upgrade-insecure-requests via next.config.js headers or your reverse proxy as a backstop, and set HSTS separately for the top-level page.

Free tool
Check this with the Security Checker

Frequently asked

Why does my site still show 'Not secure' even though I installed an SSL certificate?

The certificate secures the main HTML document, but if that page references any resource over http:// (an image, script, stylesheet, or iframe) the browser downgrades the padlock. The certificate is fine; the problem is mixed content. Find the insecure resources in the Console or Issues tab and switch them to https://.

What is the difference between active and passive mixed content?

Active (blockable) mixed content is scripts, stylesheets, iframes, and fetch/XHR calls, which can control the page. Browsers block these entirely, breaking layout or functionality. Passive (upgradable) mixed content is images, audio, and video; browsers auto-upgrade these to HTTPS and they only fail if the resource is not available over HTTPS. Active mixed content is the urgent one to fix.

Does upgrade-insecure-requests fix mixed content on its own?

Only for resources that already exist on HTTPS. The browser rewrites http:// to https:// before the request, so no insecure request hits the network. But there is no fallback: if an asset is HTTP-only, the upgraded HTTPS request fails and the resource will not load. It is a strong backstop, not a replacement for correcting the actual URLs, and it does not replace HSTS for the top-level page.

Should I use protocol-relative URLs like //example.com/file.js?

They avoid mixed content by matching the page's protocol, but they are now considered legacy. Since your site should be HTTPS-only, use explicit https:// for third-party resources and root-relative paths (/assets/file.js) for your own domain. Explicit HTTPS is clearer and avoids problems if the asset is ever loaded outside a browser.

I fixed one page but the warning keeps coming back on others. Why?

Mixed content almost always lives in shared components or stored data, not a single page. Old http:// image URLs baked into database content, a logo set with an HTTP URL in theme settings, or a footer widget snippet will reappear on every page that uses them. Back up, then run a sitewide database find-and-replace of your HTTP domain to HTTPS and check your template and theme settings.

Does your site have this issue?

Run a free, AI-powered audit and we’ll flag this and 150+ other checks in about a minute. No signup.

No signup needed. Results in under 60 seconds.

Related fixes