Mixed Content: When HTTPS Gets Undermined

You spent the time to set up a proper SSL certificate. Your site loads over HTTPS. The padlock shows up in the address bar. Everything looks good. But then someone tells you there is a problem. Your site has mixed content. And that padlock might not mean what you think it means.

Mixed content happens when a secure page loads resources over an insecure connection. The main page comes in through HTTPS, but some of the images, scripts, stylesheets, or other files come through plain HTTP. This creates a security hole that attackers can use. And browsers will let your visitors know something is wrong.

What Actually Happens with Mixed Content

Imagine you are in a building with good security at the front door. But someone left a window open in the back. An attacker could get in through that window and cause trouble. Mixed content is that open window. The main connection is encrypted, but the insecure resources are not. Someone on the same network can see those requests, modify them, or inject malicious code.

The risk level depends on the type of resource. Passive content like images and audio files have lower risk. An attacker could replace an image with something inappropriate, but they cannot directly take over the page. Active content like scripts and stylesheets have high risk. If an attacker can modify a script, they can run any code they want on your page. They could steal cookies, capture keystrokes, or redirect users to a fake login page.

Browsers treat these differently. Modern browsers block active mixed content by default. They do not load insecure scripts or stylesheets on HTTPS pages. This breaks parts of your site. Passive mixed content gets loaded, but the browser shows a warning. The padlock icon changes from secure to a warning symbol or disappears completely.

How Mixed Content Creeps In

Mixed content usually happens during the switch from HTTP to HTTPS. You set up the certificate and change your main page to use HTTPS, but you forget to update all the resources. Maybe you hardcoded image URLs with http:// years ago. Maybe you are using a third-party widget that still loads over HTTP. Maybe some content in your database still points to old HTTP addresses.

I have seen sites where the homepage looked fine, but when you clicked through to a product page, the browser console was full of mixed content warnings. The site owners had no idea. They thought everything was secure because the main page showed the padlock. But visitors saw warnings on other pages, and that made them question whether the site could be trusted.

Another common scenario is when developers use relative URLs like /images/photo.jpg. Those work fine because they inherit the protocol from the parent page. But sometimes people use absolute URLs with http:// and forget to update them. Or they copy code from other sources that includes http:// references.

Why Browsers Care So Much

When you see that padlock icon, you assume the page is secure. That is what the browser wants you to think. But if the page loads insecure scripts, the page is not actually secure. An attacker could take over the whole thing. The padlock would be lying.

Browser makers realized this was a problem. They started changing how mixed content gets handled. Chrome, Firefox, Safari, and Edge all now block active mixed content. They show clear warnings in the address bar. Some browsers even block passive mixed content now or plan to do so in the future.

This is not just about warnings. When browsers block insecure scripts, your site stops working. Forms might not submit. Menus might not open. Analytics might not load. The user experience gets broken because of mixed content. Fixing it is not optional if you want your site to work correctly.

Finding Mixed Content on Your Site

The first step to fixing mixed content is finding it. Your browser's developer tools are the best place to start. Open the console tab. Reload your page. Look for messages about mixed content or blocked resources. Chrome shows them in yellow or red. Firefox does the same. These messages tell you exactly which URLs are causing problems.

You can also use online tools that scan your site for mixed content. Some of them crawl your whole site and give you a report. This is helpful because mixed content might only appear on certain pages. A page deep in your site could have a problem that your homepage does not.

Another approach is to use the Content Security Policy upgrade-insecure-requests directive. This tells the browser to automatically rewrite HTTP URLs to HTTPS. It is not a perfect solution, but it can help you find problems. The browser will try to load the HTTPS version of each resource. If that works, great. If it fails, you know that resource needs attention.

Fixing the Problem

Once you know what resources are causing trouble, you have a few ways to fix them. The best approach is to update the URLs to use HTTPS. If the resource is on your own server, you already have HTTPS set up. Just change http:// to https:// in your code. If the resource is hosted elsewhere, check if the provider offers HTTPS access. Most do these days.

For images, you can often just change the protocol and it works. For scripts and stylesheets, the same applies. Many content delivery networks and third-party services have supported HTTPS for years. You just need to update the URLs.

What if the resource does not support HTTPS? You have a few options. You can host a copy of the file on your own server. You can find an alternative provider that does support HTTPS. Or you can use a service that acts as a proxy, fetching the HTTP resource and serving it over HTTPS. The last option is not ideal but can work as a temporary fix.

Sometimes the problem is not in your code but in your content. If you have a blog or a content management system, posts and pages might contain images with HTTP URLs in the content. You need to update those in the database. This can be tedious if you have a lot of content, but it has to be done. There are tools and scripts that can help find and replace these URLs.

The Upgrade-Insecure-Requests Shortcut

If updating every single URL feels overwhelming, there is a header that can help. The Content-Security-Policy header with upgrade-insecure-requests tells the browser to automatically change HTTP URLs to HTTPS. The browser tries the HTTPS version. If it works, the resource loads. If it fails, the resource does not load.

This header does not fix the underlying problem, but it can be a good way to handle mixed content without updating every URL individually. It is especially useful when you have user-generated content that might include HTTP links. You can add this header and forget about manually updating everything.

The downside is that if a resource truly does not support HTTPS, it will break. Your site might lose images or functionality. You need to test and make sure everything critical works over HTTPS. The header also does not work in older browsers. For those, you still need to provide the correct URLs.

Here is how you add the header:

Content-Security-Policy: upgrade-insecure-requests

You can add this to your server configuration or set it in your application. It is a one-line change that can clean up a lot of mixed content issues quickly.

Preventing Mixed Content in the Future

Once you have cleaned up your site, you want to keep it clean. The best way is to always use relative URLs or protocol-relative URLs. Instead of http://example.com/image.jpg or https://example.com/image.jpg, use /image.jpg. The browser automatically uses the same protocol as the main page. This works for resources on your own domain.

For external resources, make sure you always use https:// URLs. Most third-party services now provide HTTPS endpoints. If you are adding new code to your site, check the URLs. If someone gives you a script tag with http://, change it to https:// before adding it to your site.

You can also set up automated testing that checks for mixed content. Tools like Lighthouse and various security scanners will flag mixed content as an issue. Run these tests regularly, especially after making changes to your site.

What Visitors See

When you have mixed content, your visitors see something different depending on their browser. In Chrome, the padlock icon changes to a warning triangle or shows "Not secure" in the address bar. In Firefox, there is a shield icon that you can click to see blocked content. Safari shows a warning in the address bar as well.

These warnings matter. People are becoming more aware of online security. When they see a warning, they might leave. They might think your site is compromised or that you do not take security seriously. If you run an e-commerce site or collect any personal information, mixed content can hurt your business directly.

Beyond the warnings, the functionality itself can break. If your site depends on a script that gets blocked, forms might not submit, payments might fail, or the site might look completely wrong. This leads to frustrated visitors who might not come back.

Real-World Examples

I have helped several sites fix mixed content problems. One site had a theme that loaded a font from an HTTP URL. The font file was small, but it triggered mixed content warnings on every page. The fix was simple. Change the URL to HTTPS. The font provider supported it. The warnings disappeared.

Another site had hundreds of blog posts with images linked from an old HTTP-only image hosting service. The images still existed, but the service did not support HTTPS. We had to download all the images, upload them to the site's own server, and update the URLs in the database. It took time, but the site became fully secure.

A third site used a third-party tracking script that the vendor only provided over HTTP. We contacted the vendor. They said they were working on HTTPS support. In the meantime, we used the upgrade-insecure-requests header to let the browser handle it. It worked until the vendor finally added HTTPS support.

Making the Switch to All HTTPS

If you are still running your site on HTTP, now is the time to switch. Mixed content only matters when you have HTTPS pages that load HTTP resources. The real solution is to move everything to HTTPS. Once your whole site is HTTPS, you can worry about mixed content. Before that, you are already insecure.

When you do switch, plan for mixed content. Change your URLs. Test thoroughly. Use the upgrade-insecure-requests header as a safety net. Monitor your site for a few days to make sure nothing breaks. Once everything is clean, your visitors will see that secure padlock, and they will know they can trust your site.