Introduction

Mixed content occurs when a secure HTTPS page loads insecure HTTP resources like scripts, images, or stylesheets. Modern browsers block mixed active content (scripts, frames, CSS) and may warn about mixed passive content (images, media). When your site runs through Cloudflare with HTTPS, but your origin still references HTTP URLs for assets, visitors see broken functionality or security warnings. Fixing mixed content requires updating all resource references to HTTPS.

Symptoms

  • Browser console shows "Mixed Content" warnings or errors
  • Page elements (scripts, styles, images) fail to load
  • Browser shows shield icon or security warning
  • JavaScript functionality broken due to blocked scripts
  • CSS styling missing or broken
  • API calls failing with network errors
  • Console error: "Blocked loading mixed active content"

Common Causes

  • Hardcoded HTTP URLs in HTML source
  • HTTP URLs in CSS background-image properties
  • HTTP URLs in JavaScript fetch/ajax calls
  • HTTP URLs in iframe or embed sources
  • Protocol-relative URLs (//domain.com) resolving to HTTP
  • CMS configuration storing HTTP URLs in database
  • Third-party widgets or plugins using HTTP resources
  • Origin server serving mixed content before Cloudflare HTTPS

Step-by-Step Fix

  1. 1.Identify mixed content resources:

Open browser DevTools (F12) > Console tab

Look for warnings like: `` Mixed Content: The page at 'https://yourdomain.com/' was loaded over HTTPS, but requested an insecure script 'http://yourdomain.com/script.js'. This request has been blocked.

  1. 1.Check Network tab for blocked resources:

DevTools > Network tab > Filter by "blocked"

Note which resources are blocked and their HTTP URLs.

  1. 1.Test page with detailed mixed content report:

```bash # Check page content for HTTP references curl -s https://yourdomain.com/ | grep -o 'http://[^"]*'

# Find HTTP references in HTML curl -s https://yourdomain.com/ | grep -E 'src="http:|href="http:|url\(http:' ```

  1. 1.Enable Cloudflare Automatic HTTPS Rewriting:

Navigate to: SSL/TLS > Edge Certificates

``` # Automatic HTTPS Rewriting: Automatically replaces HTTP links # with HTTPS links for resources that can be served securely

# Toggle ON to enable automatic rewriting # This fixes many mixed content issues automatically ```

  1. 1.Enable Always Use HTTPS:

Navigate to: SSL/TLS > Edge Certificates

``` # Always Use HTTPS: Redirects all HTTP requests to HTTPS # Ensures visitors always use secure connection

# Toggle ON ```

  1. 1.Fix hardcoded HTTP URLs in HTML:

```html <!-- Change HTTP to HTTPS for all resource references -->

<!-- Before: --> <script src="http://yourdomain.com/script.js"></script> <link rel="stylesheet" href="http://yourdomain.com/style.css"> <img src="http://yourdomain.com/image.png">

<!-- After: --> <script src="https://yourdomain.com/script.js"></script> <link rel="stylesheet" href="https://yourdomain.com/style.css"> <img src="https://yourdomain.com/image.png"> ```

  1. 1.Use relative URLs instead of absolute HTTP:

```html <!-- Better: Use relative URLs --> <script src="/script.js"></script> <link rel="stylesheet" href="/style.css"> <img src="/image.png">

<!-- Or protocol-relative (forces same protocol as page) --> <script src="//yourdomain.com/script.js"></script> <!-- Note: Protocol-relative now defaults to HTTPS on HTTPS pages --> ```

  1. 1.Fix HTTP URLs in CSS:

```css /* Before: HTTP URLs */ body { background-image: url('http://yourdomain.com/bg.png'); }

/* After: HTTPS or relative */ body { background-image: url('https://yourdomain.com/bg.png'); }

/* Or relative */ body { background-image: url('/bg.png'); } ```

  1. 1.Fix HTTP URLs in JavaScript:

```javascript // Before: HTTP API calls fetch('http://api.yourdomain.com/data') .then(response => response.json());

// After: HTTPS fetch('https://api.yourdomain.com/data') .then(response => response.json());

// Or relative fetch('/api/data') .then(response => response.json());

// For external resources, use HTTPS fetch('https://external-api.com/data') ```

  1. 1.Update CMS configuration:

For WordPress: ```bash # Update site URLs in database or wp-config.php # Settings > General > Site URL: https://yourdomain.com # Settings > General > Home URL: https://yourdomain.com

# Or in wp-config.php: define('WP_SITEURL', 'https://yourdomain.com'); define('WP_HOME', 'https://yourdomain.com');

# Run database update script for existing content # Search and replace HTTP URLs in posts/pages ```

  1. 1.Fix third-party widget HTTP resources:

```html <!-- Check third-party embeds for HTTP -->

<!-- Before: HTTP iframe --> <iframe src="http://widget.example.com/embed"></iframe>

<!-- After: HTTPS (check if third-party supports HTTPS) --> <iframe src="https://widget.example.com/embed"></iframe>

<!-- If third-party doesn't support HTTPS, find alternative --> ```

  1. 1.Use Content-Security-Policy header:

```nginx # nginx: Add CSP header to upgrade insecure requests add_header Content-Security-Policy "upgrade-insecure-requests" always;

# This tells browser to automatically upgrade HTTP requests to HTTPS ```

  1. 1.Verify fix by testing page:

```bash # Check for remaining HTTP references curl -s https://yourdomain.com/ | grep -E 'http://' | head -20

# If no results, all URLs are HTTPS

# Check browser console for mixed content warnings # DevTools > Console > No warnings should appear ```

Verification

After applying fixes:

  1. 1.Browser Console shows no mixed content warnings
  2. 2.All resources load successfully in Network tab
  3. 3.No "blocked" resources in DevTools
  4. 4.Page functionality works correctly (scripts execute, styles apply)
  5. 5.Security badge shows secure connection (no shield icon)
  6. 6.curl -s https://yourdomain.com/ | grep "http://" returns no HTTP URLs