Mixed content on an HTTPS site: detect and clean unencrypted links

An HTTPS page loading an HTTP resource is flagged as insecure, hurting UX and SEO. A guide to find and fix.

Mixed content is when a page served over HTTPS requests a resource (CSS, JS, image, font, video) over HTTP. Browsers mark the page as 'not secure', automatically block mixed active content (scripts, iframes, fetch), and significantly degrade the experience.

Why this matters

The impact splits into three areas. Security - an attacker who can intercept HTTP traffic can swap the resource before it reaches the visitor. If it is JavaScript they can inject cookie-stealing code; if it is an image they can replace it with another. Browsers automatically block active mixed content (script, iframe, fetch), which means a site with mixed JS simply will not work. User experience - the padlock turns into a yellow or 'Not Fully Secure' indicator with a warning. In some Chrome modes the visitor sees a 'This site is not secure' page before the content. SEO - Google treats this as a security failure and lowers quality scores. The problem is especially common after migrating to SSL: the new domain starts at https but old links in content (images in posts, menu links, hardcoded URLs in the theme) still point to http.

How to detect

The audit crawls main pages and looks for src, href, action attributes that start with http://. Manually: open the site in Chrome > F12 > Console. Warnings like 'Mixed Content: The page at https://... was loaded over HTTPS, but requested an insecure...' point to the problem. From the command line:

curl -s https://example.com | grep -E 'src="http://|href="http://'
'Why No Padlock?' (whynopadlock.com) scans automatically.

How to fix

  1. Settings > General: confirm WordPress Address and Site Address are both https.
  2. Install the Better Search Replace plugin (free).
  3. Set search='http://yoursite.com', replace='https://yoursite.com'. Tick all tables. Run as dry run first to see how many replacements will happen.
  4. If the count looks reasonable (thousands, not millions), uncheck dry run and run for real.
  5. Next, run a generic search for http:// (no domain) - this finds links to other sites that are still HTTP. If any appear, fix manually but carefully, because not every external site is available over HTTPS.
  6. Quick alternative: add to .htaccess
    <IfModule mod_headers.c>
        Header always set Content-Security-Policy "upgrade-insecure-requests;"
    </IfModule>
    which tells browsers to upgrade every http request to its https equivalent. A plaster, but effective for most cases.
  7. Browse several pages. F12 > Console - mixed-content warnings should be gone.
  8. Once clean, remove the Better Search Replace plugin - it should not stay active.

Common mistakes

Do not include the guid column in search-replace - it serves as a unique identifier in RSS feeds, and changing it breaks feeds and creates duplicate posts in subscribers' readers. Do not run a plain MySQL UPDATE for the same purpose - it does not handle serialized data, and serialized options will break. Do not assume the problem is only in the database - some mixed content lives in theme or plugin files with hardcoded http://. Search there too. Do not rely on upgrade-insecure-requests as the only fix - it does not affect links a user clicks, only resources the browser fetches automatically.

Verifying the fix

Open the site in a Chrome private window > F12 > Console. Reload 5-10 different pages. There should be no mixed-content warnings. Check whynopadlock.com - 'no insecure resources'. The address bar should show a clean green padlock with no warning icon.

Tip: If after a successful search-replace mixed content remains, the likely cause is a theme with hardcoded URLs in HTML or PHP. Search the theme files:
grep -rn 'http://yoursite' wp-content/themes/your-theme/
and replace by hand.