Guide · SSL & Security

Mixed Content Warnings: How to Find and Fix HTTP Resources on HTTPS

Understand active vs passive mixed content, hunt down http:// references in HTML, CSS, JS and databases, fix them with wp-cli or CSP, and verify the result.

By SiteDownCheck Editorial · Updated October 4, 2026 · 8 min read

You installed a valid certificate, the padlock still looks wrong or images and scripts are missing, and the browser console is full of warnings about insecure resources. That is mixed content: an HTTPS page pulling in something over plain HTTP. This guide shows you how to find every offending reference, fix it at the source, and add a safety net so it does not return.

What mixed content is, and why browsers care

When a page is delivered over HTTPS, the browser expects everything it loads to be protected as well. A single resource fetched over HTTP can be read or altered by anyone on the network path. If that resource is a script, the attacker effectively controls your page. Browsers therefore split mixed content into two categories.

Active mixed content

Resources that can change the page's behavior or read its data:

  • scripts (<script src>)
  • stylesheets (<link rel="stylesheet">)
  • iframes
  • XHR and fetch() calls
  • web fonts, and other resources loaded by those above

Modern browsers block active mixed content outright. The visible symptom is something that simply does not work: a broken menu, a missing map, a form that never submits, a layout without its stylesheet.

Passive (display) mixed content

Resources that display but cannot execute: images, audio and video. Historically browsers loaded these with a warning and removed the secure padlock. Current versions of the major browsers instead try to upgrade these requests to HTTPS automatically and block them if the upgrade fails. The exact behavior has changed across releases and differs a little between browsers, so do not rely on it. An image served over HTTP might display in one browser and disappear in another.

The rule that matters is simple: after your fix, every subresource should be requested over HTTPS directly.

Step 1: Find the offenders

In the browser

Open DevTools (F12), reload the page and look at the Console. Chrome reports messages such as Mixed Content: The page at 'https://example.com/' was loaded over HTTPS, but requested an insecure script 'http://...'. This request has been blocked. The Network panel can filter by scheme; type scheme:http into the filter box in Chromium-based browsers. Check several page types, not just the homepage, because templates differ: product pages, blog posts, checkout, and embedded-video pages.

The Mixed Content Checker scans a URL's HTML for insecure references and lists them, which is faster than clicking through pages one by one.

In your source files

Search the code, templates and static assets for hard-coded absolute HTTP URLs:

grep -rIn --include='*.{html,php,js,css,twig,vue,jsx,tsx}' "http://" ./wp-content/themes/mytheme
grep -rIn "src=[\"']http://" ./public
grep -rIn "url(http://" ./public --include='*.css'

Expect false positives such as XML namespaces (http://www.w3.org/2000/svg), which are identifiers, not requests, and plain-text links that merely appear in content. Focus on src, href of stylesheets, srcset, url(), @import, fetch( and XMLHttpRequest.

In the database

Content management systems store absolute URLs inside posts, options, widgets and page-builder data. Search for them:

SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%http://example.com%' LIMIT 20;
SELECT option_name FROM wp_options WHERE option_value LIKE '%http://example.com%';

Note that post_content is not the only place; check wp_postmeta, widget options and theme settings, which is why a dedicated replace tool beats hand-written SQL.

Step 2: Fix them at the source

Use HTTPS URLs, or relative URLs

For your own assets, the best fix is a root-relative URL such as /images/logo.png, which inherits the page's scheme and host, or an explicit https:// URL. For third-party resources, switch to the HTTPS version of the same URL; most providers have served HTTPS for years. If a provider only supports HTTP, replace it, host a copy yourself (if the license allows) or remove it.

Beware protocol-relative URLs

A URL like //cdn.example.net/lib.js inherits the page's scheme. It was a popular trick when sites mixed HTTP and HTTPS, but it is now considered an anti-pattern. If the page is ever opened from file://, an email client or a preview tool, the browser may try a scheme that does not work. Replace them with explicit https://.

WordPress: search-replace with wp-cli

For WordPress, change the site and home URLs first (Settings > General, or wp option update home https://example.com and wp option update siteurl https://example.com). Then rewrite stored content. Always take a backup and do a dry run:

wp db export before-https.sql

wp search-replace 'http://example.com' 'https://example.com' --all-tables --dry-run --report-changed-only
wp search-replace 'http://example.com' 'https://example.com' --all-tables --skip-columns=guid

wp search-replace handles PHP-serialized data correctly, which is why it is safer than a raw SQL REPLACE(): changing the length of a string inside a serialized array without updating its length marker corrupts the data. The --skip-columns=guid option leaves post GUIDs untouched; they are identifiers, not links. If you used www variants or a CDN hostname, run the replace for each variant.

Then clear caches: page cache plugin, object cache, and CDN. Stale cached HTML is a very common reason the warnings persist after a correct fix. If page-builder plugins keep generated CSS files, regenerate them using the builder's tools.

Other platforms

Most CMSs and frameworks have a base-URL setting that must be changed to HTTPS; set it before hunting for strays. Check also: hard-coded values in environment variables, CDN origin settings, Open Graph tags, canonical links, and JSON-LD blocks. These do not trigger mixed-content blocking (they are not fetched as subresources) but should still use HTTPS for consistency.

Step 3: Third-party resources

Third-party widgets are a typical last holdout: old analytics snippets, chat widgets, ad tags, embedded maps and fonts. For each one:

  1. Open the vendor's current documentation and copy their HTTPS snippet.
  2. Check whether the script itself requests more HTTP resources, which you cannot fix from your side. In that case, contact the vendor or drop the integration.
  3. Remember that blocked active content breaks features silently; verify behavior, not only the console.

The Third-Party Script Checker lists external hosts your page depends on, which helps you spot forgotten ones.

Step 4: Add a safety net with CSP

The upgrade-insecure-requests directive tells the browser to rewrite HTTP subresource requests to HTTPS before sending them. It also upgrades same-site navigations. Send it as a header:

add_header Content-Security-Policy "upgrade-insecure-requests" always;
Header always set Content-Security-Policy "upgrade-insecure-requests"

This is a very effective stopgap for large legacy sites, but note its limits:

  • It only helps if the HTTPS version of the resource actually exists. If the host does not serve HTTPS, the request fails.
  • It does not repair your stored data, and it adds nothing for clients that do not support it (support is broad in current browsers).
  • If you already send a Content-Security-Policy header, add upgrade-insecure-requests as another directive inside it rather than as a second competing header. Multiple CSP headers are all enforced together, which is valid but can surprise you.

A longer-term complement is a report-only policy such as Content-Security-Policy-Report-Only: default-src https: 'unsafe-inline' 'unsafe-eval' data: blob:; report-uri /csp-reports, which flags any new non-HTTPS load without blocking. See the HTTP security headers guide for the full CSP workflow.

Step 5: Redirect and lock in HTTPS

Mixed content often appears together with incomplete HTTP-to-HTTPS migration. Confirm that http:// URLs of your site redirect with a permanent redirect to the HTTPS equivalent (see HTTP redirects 301 vs 302), and consider HSTS once everything is clean. If you enable HSTS before fixing mixed content, nothing improves for subresources on other hosts, so clean up first.

Step 6: Verify

  1. Reload key pages in a fresh private window with DevTools open and an empty cache. No Mixed Content messages should remain.
  2. Run the Mixed Content Checker against several URL types.
  3. Check the certificate and chain with the SSL Checker; a broken chain can be mistaken for a mixed content issue in some clients.
  4. Look at forms, embeds, maps, fonts, video players and checkout flows manually, since blocked scripts often leave no visible error on the page.
  5. Check emailed or shared pages and AMP or mobile variants if you have them.

Make this part of your deployment routine: a single new template with http:// in it can reintroduce the problem.

Next steps

FAQ

Why do I still get mixed content warnings after switching to HTTPS?

Almost always because there are hard-coded http:// URLs in your database, theme files or a cached copy of the page. Search-replace the stored URLs, fix templates, and purge every cache layer including the CDN.

Is passive mixed content really a problem if browsers upgrade it?

Yes. Browser behavior varies by version, and an upgrade fails if the HTTPS version does not exist. Fixing the URL makes your site correct everywhere, not just in browsers that happen to rescue it.

Will upgrade-insecure-requests fix everything?

It fixes many cases quickly, but only when the target host supports HTTPS at the same path. It does not correct database content, and unsupported clients ignore it. Use it as an interim safeguard while fixing the source.

Are protocol-relative URLs acceptable?

They work in a browser on HTTPS, but they are no longer recommended. Explicit https:// is clearer and avoids problems in non-browser contexts.

Does mixed content hurt SEO?

It can hurt indirectly: broken scripts and missing images degrade the experience, and warnings reduce trust. Search engines do not need you to remove every HTTP reference, but a clean HTTPS site is easier to crawl and render correctly.

Does wp-cli search-replace break serialized data?

No. It is designed to unserialize, replace and reserialize correctly, unlike a plain SQL replace. Still, export the database first and run --dry-run to see what would change.

Get notified when this guide updates

Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.

This page is general information written by our editorial team and updated when documentation changes. Servers and providers differ, so test changes safely first. See our editorial policy and disclaimer.