---
title: "Mixed content on HTTPS pages - Serpwise"
description: "Insecure HTTP resources on HTTPS pages get blocked by browsers, break rendering, and signal a security misconfiguration to crawlers. How to find and fix them."
url: "https://serpwise.ai/learn/mixed-content-on-https/"
source: "https://serpwise.ai/learn/mixed-content-on-https/"
---
[← Back to Learn](/learn/)

Security & HTTPS Critical

# Mixed content on HTTPS pages

Insecure HTTP resources on HTTPS pages get blocked by browsers, break rendering, and signal a security misconfiguration to crawlers. How to find and fix them.

A page served over HTTPS that loads any subresource - image, script, stylesheet, iframe, font, XHR - over plain HTTP is “mixed content.” All current browsers block active mixed content (scripts, iframes, XHR) outright. Passive mixed content (images, audio, video) used to be allowed with a warning; modern Chrome and Firefox upgrade or block these too. The page still loads; it just loads broken.

## Why it matters

Three concrete failure modes:

1. **Scripts and stylesheets don’t execute.** Layout collapses, interactivity dies, hydration fails. To a crawler, the page often looks like an empty shell.
2. **Render-blocking failures cascade into Core Web Vitals collapse.** LCP misses because the hero image was blocked. CLS spikes because the stylesheet that sized the layout never loaded.
3. **Visitors receive a broken or inconsistent page.** Browser consoles and security tooling expose the failures, while missing scripts, styles, or media can prevent the page from working as intended.

This is not a soft signal. Browsers actively break the page.

## How to detect it

Open DevTools → Console. Mixed content warnings appear as red errors:

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

At scale, two production-grade approaches:

1. **CSP `report-only`.** Set a Content Security Policy in report-only mode and collect violations:

```
Content-Security-Policy-Report-Only: default-src https:; report-uri /csp-reports
```

2. **Crawl with a headless browser** that records all subresource requests, then filter for `http://` schemes.

## The fix

Two paths. Do them in order.

### Step 1 - Fix the source

Find the HTTP URLs in your codebase and switch them to protocol-relative or absolute HTTPS:

```
<!-- Wrong -->
<img src="http://cdn.example.com/hero.jpg" />
<script src="http://analytics.example.com/tag.js"></script>

<!-- Right -->
<img src="https://cdn.example.com/hero.jpg" />
<script src="https://analytics.example.com/tag.js"></script>
```

Protocol-relative URLs (`//cdn.example.com/hero.jpg`) work but are considered legacy - write absolute HTTPS.

### Step 2 - Upgrade legacy URLs at the response layer

Some mixed content is unfixable at the source - old database content with hardcoded `http://` image URLs, user-generated content, third-party widgets. Use `upgrade-insecure-requests` to tell the browser to retry every HTTP subresource as HTTPS:

```
Content-Security-Policy: upgrade-insecure-requests
```

Or as a meta tag in `<head>`:

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

This only works if the origin actually serves HTTPS. If `http://cdn.example.com/hero.jpg` upgrades to `https://cdn.example.com/hero.jpg` and the CDN doesn’t have a valid cert there, the resource fails entirely. Test before shipping.

### WordPress

```
-- Find legacy http:// references in content
SELECT ID, post_title FROM wp_posts
WHERE post_content LIKE '%http://example.com%';
```

The Better Search Replace plugin handles this safely (it serializes PHP arrays correctly - a plain `UPDATE` query will corrupt them).

### Nginx

Add the upgrade header globally:

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

### Apache

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

## Common pitfalls

- **`http://` in `srcset`.** Easy to miss in audits that only check `src`.
- **`http://` in inline CSS `url(...)`.** Same deal - most scanners check tags, not stylesheets.
- **Iframes from ad networks.** Modern ad tags emit HTTPS but legacy creatives sometimes don’t. Lock the ad network into HTTPS-only delivery.
- **Hardcoded `http://` in JSON-LD `image` properties.** Search engines fetch these. Broken image URLs in schema = lost rich result eligibility.
- **`upgrade-insecure-requests` as the only fix.** It’s a patch, not a cure - it doesn’t fix the underlying data, and a future CSP change can re-expose the bug.

From diagnosis to deployment

## Find the issue. Ship the fix.

Use Learn to understand the problem, then run Serpwise against your own site to see what can be approved and deployed.

[Run free audit](/audit/) [Book a demo](/demo/)