search
Tutorials star Featured

Fix: HTTPS required but site loading HTTP - Mixed Content Error Guide

Complete guide to fix mixed content errors when HTTPS is required but site loads HTTP resources. Learn how to resolve HTTP to HTTPS issues with practical solutions for React, Angular, and Vue applications.

person By Gautam Sharma
calendar_today January 8, 2026
schedule 15 min read
HTTPS Mixed Content HTTP SSL Security Frontend React Angular Vue CORS Deployment

The ‘HTTPS required but site loading HTTP’ error, commonly known as a mixed content error, occurs when a website served over HTTPS attempts to load resources (images, scripts, stylesheets, APIs) over HTTP. This security issue triggers browser warnings and can block insecure content from loading, resulting in broken functionality and poor user experience.

This comprehensive guide explains what causes mixed content errors, why they happen, and provides multiple solutions to fix them in your React, Angular, and Vue projects with clean code examples and directory structure.


What is the Mixed Content Error?

The “HTTPS required but site loading HTTP” issue occurs when:

  • Your website is served over HTTPS (secure connection)
  • Resources like images, scripts, or APIs are loaded over HTTP (insecure connection)
  • Browsers block mixed content for security reasons
  • Users see security warnings or broken elements
  • API calls fail due to CORS policies in secure contexts

Common Error Manifestations:

  • “Mixed Content: The page was loaded over HTTPS, but requested an insecure resource”
  • Blocked scripts, stylesheets, or images
  • Failed API calls with CORS errors
  • Security warnings in browser console
  • Broken functionality due to blocked resources

Understanding the Problem

Mixed content issues typically occur due to:

  • Hardcoded HTTP URLs in code
  • Insecure API endpoints
  • External resources loaded over HTTP
  • Environment configuration differences
  • CDN or asset hosting issues
  • Third-party script problems
  • Proxy configuration errors

Types of Mixed Content:

  • Active Mixed Content: Scripts, AJAX requests, plugins (blocked by browsers)
  • Passive Mixed Content: Images, videos, audio (may be blocked depending on browser settings)

Solution 1: Identify Mixed Content Issues

The first step is to identify which resources are being loaded over HTTP.

❌ Without Proper Identification:

// ❌ Don't ignore mixed content warnings
// Site loads but with broken elements
// No visible errors in code

✅ With Proper Identification:

Check Browser Console:

# Open browser developer tools
# Check Console tab for mixed content errors
# Look for "Mixed Content" warnings
# Check Network tab for blocked requests

Example Console Errors:

Mixed Content: The page was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://api.example.com/data'.
Mixed Content: The page was loaded over HTTPS, but requested an insecure script 'http://cdn.example.com/script.js'.
Mixed Content: The page was loaded over HTTPS, but requested an insecure image 'http://images.example.com/photo.jpg'.

Solution 2: React - Fix Mixed Content Issues

React API Call Issues

❌ With HTTP API Calls:

// src/services/api.js - ❌ Loading HTTP resources
import axios from 'axios';

const API_BASE_URL = 'http://api.myapp.com'; // ❌ HTTP instead of HTTPS

export const fetchData = async () => {
  const response = await axios.get(`${API_BASE_URL}/data`);
  return response.data;
};

✅ With HTTPS API Calls:

API Service:
// src/services/api.js
import axios from 'axios';

const API_BASE_URL = 'https://api.myapp.com'; // ✅ Use HTTPS

export const fetchData = async () => {
  try {
    const response = await axios.get(`${API_BASE_URL}/data`);
    return response.data;
  } catch (error) {
    console.error('API call failed:', error);
    throw error;
  }
};

// ✅ For environment-specific URLs
const API_BASE_URL = process.env.REACT_APP_API_URL || 'https://api.myapp.com';

React Asset Loading Issues

❌ With HTTP Assets:

// src/components/ImageComponent.js - ❌ Loading HTTP images
import React from 'react';

const ImageComponent = () => {
  return (
    <div>
      {/* ❌ HTTP image - will be blocked */}
      <img src="http://example.com/image.jpg" alt="Example" />
      {/* ❌ HTTP stylesheet link */}
      <link rel="stylesheet" href="http://cdn.example.com/style.css" />
    </div>
  );
};

✅ With HTTPS Assets:

// src/components/ImageComponent.js
import React from 'react';

const ImageComponent = () => {
  return (
    <div>
      {/* ✅ HTTPS image */}
      <img src="https://example.com/image.jpg" alt="Example" />
      {/* ✅ Or use relative paths */}
      <img src="/images/example.jpg" alt="Example" />
      {/* ✅ Or import directly */}
      <img src={require('../assets/image.jpg')} alt="Example" />
    </div>
  );
};

React Environment Configuration

.env.production:

REACT_APP_API_URL=https://api.myapp.com
REACT_APP_IMAGE_CDN=https://cdn.myapp.com
REACT_APP_ASSETS_URL=https://assets.myapp.com

package.json:

{
  "name": "my-react-app",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "axios": "^1.4.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test"
  }
}

Solution 3: Angular - Fix Mixed Content Issues

Angular HTTP Client Configuration

❌ With HTTP Requests:

// src/app/services/data.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  // ❌ HTTP instead of HTTPS
  private apiUrl = 'http://api.myapp.com';

  constructor(private http: HttpClient) { }

  getData() {
    return this.http.get(this.apiUrl);
  }
}

✅ With HTTPS Requests:

Service with HTTPS:
// src/app/services/data.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  private apiUrl = environment.apiUrl; // ✅ Use environment-specific HTTPS URL

  constructor(private http: HttpClient) { }

  getData(): Observable<any> {
    return this.http.get(this.apiUrl);
  }

  postData(data: any): Observable<any> {
    return this.http.post(this.apiUrl, data, {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
        'X-Requested-With': 'XMLHttpRequest'
      })
    });
  }
}
Environment Configuration:
// src/environments/environment.prod.ts
export const environment = {
  production: true,
  apiUrl: 'https://api.myapp.com' // ✅ HTTPS URL for production
};

Angular Asset Configuration

❌ With HTTP Assets:

<!-- src/index.html - ❌ Loading HTTP resources -->
<head>
  <!-- ❌ HTTP stylesheet -->
  <link rel="stylesheet" href="http://cdn.example.com/bootstrap.css">
  <!-- ❌ HTTP script -->
  <script src="http://cdn.example.com/analytics.js"></script>
</head>

✅ With HTTPS Assets:

<!-- src/index.html -->
<head>
  <meta charset="utf-8">
  <title>My App</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  
  <!-- ✅ HTTPS resources only -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css">
  <script src="https://www.googletagmanager.com/gtag/js?id=GA_TRACKING_ID" async></script>
</head>

Solution 4: Vue - Fix Mixed Content Issues

Vue API Call Issues

❌ With HTTP API Calls:

// src/api/index.js - ❌ Loading HTTP resources
import axios from 'axios';

const API_BASE_URL = 'http://api.myapp.com'; // ❌ HTTP instead of HTTPS

const api = axios.create({
  baseURL: API_BASE_URL,
});

export default api;

✅ With HTTPS API Calls:

API Configuration:
// src/api/index.js
import axios from 'axios';
import { API_CONFIG } from '@/config/api';

const api = axios.create({
  baseURL: API_CONFIG.baseURL, // ✅ Use HTTPS URL
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
    'X-Requested-With': 'XMLHttpRequest'
  }
});

// ✅ Request interceptor to ensure HTTPS
api.interceptors.request.use(
  config => {
    // Ensure all requests use HTTPS
    if (config.url && config.url.startsWith('http://')) {
      config.url = config.url.replace('http://', 'https://');
    }
    return config;
  },
  error => Promise.reject(error)
);

export default api;
Configuration File:
// src/config/api.js
export const API_CONFIG = {
  baseURL: process.env.VUE_APP_API_URL || 'https://api.myapp.com', // ✅ HTTPS default
  timeout: 10000
};

Vue Asset Loading

❌ With HTTP Assets:

<!-- src/components/AssetLoader.vue - ❌ Loading HTTP resources -->
<template>
  <div>
    <!-- ❌ HTTP image -->
    <img src="http://example.com/image.jpg" alt="Example">
    <!-- ❌ HTTP script in component -->
    <iframe src="http://external-site.com/widget"></iframe>
  </div>
</template>

✅ With HTTPS Assets:

<!-- src/components/AssetLoader.vue -->
<template>
  <div>
    <!-- ✅ HTTPS image -->
    <img src="https://example.com/image.jpg" alt="Example">
    <!-- ✅ Or use relative paths -->
    <img src="@/assets/image.jpg" alt="Example">
    <!-- ✅ Or use public folder -->
    <img src="/images/example.jpg" alt="Example">
    <!-- ✅ HTTPS iframe -->
    <iframe src="https://external-site.com/widget"></iframe>
  </div>
</template>

Solution 5: Server-Side Redirects and Headers

Apache Configuration (.htaccess)

❌ Without HTTPS Enforcement:

# .htaccess - ❌ No HTTPS enforcement
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.html [QSA,L]

✅ With HTTPS Enforcement:

# .htaccess - ✅ Force HTTPS
RewriteEngine On

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

# Prevent mixed content
<IfModule mod_headers.c>
    Header always set Content-Security-Policy "upgrade-insecure-requests;"
</IfModule>

# Rest of your routing rules
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.html [QSA,L]

Nginx Configuration

❌ Without HTTPS Enforcement:

server {
    listen 80;
    server_name example.com;
    root /var/www/html;
    index index.html;
    
    location / {
        try_files $uri $uri/ /index.html;
    }
}

✅ With HTTPS Enforcement:

server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;
    root /var/www/html;
    index index.html;
    
    # SSL configuration
    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/private.key;
    
    # Security headers to prevent mixed content
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header Content-Security-Policy "upgrade-insecure-requests;" always;
    
    location / {
        try_files $uri $uri/ /index.html;
    }
}

Solution 6: Content Security Policy (CSP)

Implement CSP Headers

❌ Without CSP:

// No security headers - vulnerable to mixed content
app.use(cors());
app.use(express.static('public'));

✅ With CSP:

Express.js Example:
// server.js
const express = require('express');
const helmet = require('helmet');
const app = express();

// ✅ Security middleware
app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "'unsafe-inline'", 'https://cdnjs.cloudflare.com'],
      styleSrc: ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
      imgSrc: ["'self'", 'data:', 'https:'],
      connectSrc: ["'self'", 'https://api.myapp.com'],
      fontSrc: ["'self'", 'https://fonts.gstatic.com'],
      objectSrc: ["'none'"],
      upgradeInsecureRequests: [] // ✅ Automatically upgrade HTTP requests to HTTPS
    }
  }
}));

app.use(express.static('public'));
Meta Tag Approach:
<!-- In your index.html head section -->
<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; upgrade-insecure-requests;">

Solution 7: Protocol-Relative URLs and Environment Handling

Use Protocol-Relative URLs

❌ With Hardcoded Protocols:

// ❌ Hardcoded HTTP
const imageUrl = 'http://cdn.example.com/image.jpg';
const apiUrl = 'http://api.example.com/data';

✅ With Protocol-Relative URLs:

JavaScript Approach:
// ✅ Protocol-relative URLs
const imageUrl = '//cdn.example.com/image.jpg'; // Uses same protocol as page
const apiUrl = '//api.example.com/data';

// ✅ Or dynamically determine protocol
const getBaseUrl = () => {
  return `${window.location.protocol}//${window.location.host}`;
};

const apiUrl = `${getBaseUrl()}/api/data`;
Environment-Based Approach:
// ✅ Environment-aware configuration
const CONFIG = {
  development: {
    api: 'https://dev-api.myapp.com',
    cdn: 'https://dev-cdn.myapp.com'
  },
  production: {
    api: 'https://api.myapp.com',
    cdn: 'https://cdn.myapp.com'
  }
};

const ENV = process.env.NODE_ENV || 'development';
const CURRENT_CONFIG = CONFIG[ENV];

Working Code Examples

Complete React Solution:

// src/utils/secureResourceLoader.js
import { useState, useEffect } from 'react';

export const useSecureResource = (url) => {
  const [resource, setResource] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const loadResource = async () => {
      try {
        setLoading(true);
        
        // ✅ Ensure HTTPS for all requests
        const secureUrl = ensureHttpsUrl(url);
        
        const response = await fetch(secureUrl);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const data = await response.json();
        setResource(data);
      } catch (err) {
        setError(err.message);
        console.error('Secure resource loading failed:', err);
      } finally {
        setLoading(false);
      }
    };

    if (url) {
      loadResource();
    }
  }, [url]);

  return { resource, loading, error };
};

// ✅ Helper function to ensure HTTPS
export const ensureHttpsUrl = (url) => {
  if (!url) return url;
  
  if (url.startsWith('http://')) {
    return url.replace('http://', 'https://');
  }
  
  if (url.startsWith('//')) {
    return `https:${url}`;
  }
  
  return url;
};

// ✅ Usage in component
const SecureComponent = ({ apiUrl }) => {
  const { resource, loading, error } = useSecureResource(apiUrl);

  if (loading) return <div>Loading securely...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div>
      <h2>Secure Resource Loaded</h2>
      <pre>{JSON.stringify(resource, null, 2)}</pre>
    </div>
  );
};

Complete Angular Solution:

// src/app/interceptors/secure-request.interceptor.ts
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';

@Injectable()
export class SecureRequestInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    // ✅ Ensure all outgoing requests use HTTPS
    let secureUrl = req.url;
    
    if (req.url.startsWith('http://')) {
      secureUrl = req.url.replace('http://', 'https://');
    }
    
    const secureReq = req.clone({
      url: secureUrl,
      setHeaders: {
        'X-Requested-With': 'XMLHttpRequest'
      }
    });
    
    return next.handle(secureReq);
  }
}

// src/app/app.module.ts
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';

@NgModule({
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: SecureRequestInterceptor,
      multi: true
    }
  ]
})
export class AppModule { }

Complete Vue Solution:

// src/plugins/secure-api.js
import axios from 'axios';

// ✅ Create secure API instance
const secureApi = axios.create({
  baseURL: process.env.VUE_APP_API_URL || 'https://api.myapp.com',
  timeout: 10000
});

// ✅ Request interceptor to enforce HTTPS
secureApi.interceptors.request.use(
  config => {
    // Ensure all URLs use HTTPS
    if (config.url && typeof config.url === 'string') {
      if (config.url.startsWith('http://')) {
        config.url = config.url.replace('http://', 'https://');
      } else if (config.url.startsWith('//')) {
        config.url = `https:${config.url}`;
      }
    }
    
    return config;
  },
  error => Promise.reject(error)
);

// ✅ Response interceptor for error handling
secureApi.interceptors.response.use(
  response => response,
  error => {
    if (error.response?.status === 403 && error.response?.data?.message?.includes('mixed content')) {
      console.error('Mixed content error detected:', error);
    }
    return Promise.reject(error);
  }
);

export default secureApi;

Best Practices for HTTPS Security

1. Always Use HTTPS URLs

// ✅ Always use HTTPS for external resources
const API_URL = 'https://api.myapp.com';
const CDN_URL = 'https://cdn.myapp.com';

2. Implement Content Security Policy

<!-- ✅ Add CSP header to prevent mixed content -->
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests;">

3. Test HTTPS in Development

# ✅ Use HTTPS in development when possible
npm start --https
# Or configure your dev server to use HTTPS

4. Audit Your Dependencies

# ✅ Regularly audit for insecure dependencies
npm audit
# Check for packages that may load insecure resources

Debugging Steps

Step 1: Check Browser Console

# Open browser dev tools
# Check Console tab for mixed content errors
# Look for "Mixed Content" warnings
# Check Network tab for blocked requests

Step 2: Use Online Tools

# Use online mixed content scanners
# https://www.jitbit.com/sslchecker/
# https://www.whynopadlock.com/

Step 3: Test with Security Headers

# Add security headers temporarily to identify issues
# Content-Security-Policy: upgrade-insecure-requests;

Step 4: Verify All Resources

# Check all:
# - API endpoints
# - Image sources
# - Script tags
# - Stylesheet links
# - iFrame sources
# - Third-party embeds

Common Mistakes to Avoid

1. Hardcoding HTTP URLs

// ❌ Don't hardcode HTTP URLs
const API_URL = 'http://api.myapp.com'

// ✅ Use HTTPS or environment variables
const API_URL = process.env.API_URL || 'https://api.myapp.com'

2. Forgetting Third-Party Resources

<!-- ❌ Don't forget third-party resources -->
<script src="http://cdn.example.com/library.js"></script>

<!-- ✅ Ensure third-party resources use HTTPS -->
<script src="https://cdn.example.com/library.js"></script>

3. Ignoring WebSockets

// ❌ WebSocket connections also need to be secure
const ws = new WebSocket('ws://api.example.com'); // ❌ Insecure

// ✅ Use secure WebSocket connections
const ws = new WebSocket('wss://api.example.com'); // ✅ Secure

4. Missing Asset Updates

// ❌ Don't miss updating asset URLs
const imageUrls = [
  'http://images.example.com/img1.jpg', // ❌
  'http://images.example.com/img2.jpg'  // ❌
];

// ✅ Update all asset URLs
const imageUrls = [
  'https://images.example.com/img1.jpg', // ✅
  'https://images.example.com/img2.jpg'  // ✅
];

Performance Considerations

1. HTTP to HTTPS Redirects

// ✅ Minimize redirects by using HTTPS from the start
// Configure your app to use HTTPS URLs directly

2. Certificate Pinning

// ✅ For mobile apps, consider certificate pinning
// For web apps, ensure valid certificates

3. Preconnect for HTTPS Resources

<!-- ✅ Use preconnect for important HTTPS resources -->
<link rel="preconnect" href="https://api.myapp.com">
<link rel="preconnect" href="https://cdn.myapp.com">

Security Considerations

1. HSTS Headers

// ✅ Implement HSTS to force HTTPS
app.use((req, res, next) => {
  res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
  next();
});

2. Secure Cookies

// ✅ Ensure cookies are secure in HTTPS environments
app.use(session({
  cookie: {
    secure: true, // Only send over HTTPS
    httpOnly: true,
    maxAge: 24 * 60 * 60 * 1000
  }
}));

3. Validate Certificates

// ✅ Validate SSL certificates in API calls
const httpsAgent = new https.Agent({
  rejectUnauthorized: true
});

Testing HTTPS Security

1. Automated Testing

// ✅ Test for mixed content in your test suite
describe('HTTPS Security', () => {
  it('should not load any HTTP resources', () => {
    // Test that no HTTP resources are loaded
    expect(document.querySelectorAll('[src^="http://"]').length).toBe(0);
    expect(document.querySelectorAll('[href^="http://"]').length).toBe(0);
  });
});

2. Security Scanning

# ✅ Use security scanning tools
# OWASP ZAP
# Burp Suite
# SSL Labs test

3. Browser DevTools Audit

# ✅ Use Chrome DevTools Security panel
# Run Lighthouse audits
# Check for security issues

Alternative Solutions

1. Upgrade Insecure Requests Directive

<!-- ✅ Use CSP directive to automatically upgrade requests -->
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests;">

2. Service Worker Interception

// ✅ Use service worker to intercept and upgrade requests
self.addEventListener('fetch', event => {
  if (event.request.url.startsWith('http://')) {
    const httpsUrl = event.request.url.replace('http://', 'https://');
    event.respondWith(fetch(httpsUrl));
  }
});

3. Proxy Configuration

// ✅ Configure proxy to handle protocol upgrades
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'https://api.myapp.com',
        secure: true,
        changeOrigin: true
      }
    }
  }
};

Migration Checklist

  • Identify all HTTP URLs in your codebase
  • Update API endpoints to use HTTPS
  • Change all asset URLs to HTTPS
  • Update third-party resource URLs
  • Configure Content Security Policy
  • Test all functionality after changes
  • Verify SSL certificate validity
  • Update documentation for team members

Conclusion

The ‘HTTPS required but site loading HTTP’ issue, also known as mixed content error, is a critical security concern that affects websites served over HTTPS. By following the solutions provided in this guide—whether through proper URL management, Content Security Policy implementation, environment configuration, or framework-specific approaches—you can ensure your React, Angular, and Vue applications maintain security and functionality.

The key is to systematically identify all HTTP resources, update them to HTTPS, implement proper security headers, and regularly audit your application for mixed content issues. With proper configuration and ongoing maintenance, your applications will provide a secure and seamless experience for users while maintaining compliance with modern web security standards.

Remember to always use HTTPS URLs, implement Content Security Policy headers, test thoroughly after making changes, and stay vigilant about third-party resources that might introduce mixed content issues. By following these best practices, you’ll create robust and secure web applications that users can trust.

Gautam Sharma

About Gautam Sharma

Full-stack developer and tech blogger sharing coding tutorials and best practices

Related Articles

Tutorials

Fix: Build succeeded but site shows blank page in React Angular Vue

Complete guide to fix blank page issues after successful builds in React, Angular, and Vue applications. Learn how to debug and resolve blank page errors with practical solutions.

January 8, 2026
Tutorials

How to Fix: 403 Forbidden Error - Complete Tutorial

Complete guide to fix 403 Forbidden errors. Learn how to resolve permission issues with practical solutions, authorization management, and best practices for secure API communication.

January 8, 2026
Tutorials

Fix: 401 Unauthorized Error - Complete Guide to Authentication Issues

Complete guide to fix 401 Unauthorized errors. Learn how to resolve authentication issues with practical solutions, token management, and best practices for secure API communication.

January 8, 2026