Mixed content means a page loaded over HTTPS is pulling in some files (images, scripts, stylesheets, fonts, iframes) over plain HTTP. On a WordPress site it almost always happens after a move to HTTPS, because old http:// URLs are still saved in the database. The fix is a careful search and replace, plus a quick look at your theme and any hardcoded embeds.
Last updated: October 28, 2026.
Disclosure: some links in this post are affiliate links, marked as sponsored. If you sign up through them I may earn a commission at no extra cost to you. I only recommend hosts I have used.
What mixed content looks like
Depending on what is loading over HTTP, you might see:
- No padlock, or a “Not secure” label, even though the address starts with https
- Images that don’t appear
- A broken layout, because a stylesheet was blocked
- Sliders, forms, or embeds that stop working, because a script or iframe was blocked
Modern browsers handle the two kinds of mixed content differently. Images, audio, and video are upgraded to HTTPS automatically, and blocked if the HTTPS version doesn’t exist. Scripts, stylesheets, and iframes loaded over HTTP are blocked outright, and that is what breaks pages.
Step 1: Find every insecure URL
Open the page in Chrome, press F12, and click the Console tab. Each problem shows up as a line like this:
Mixed Content: The page at 'https://example.com/' was loaded over HTTPS,
but requested an insecure resource 'http://example.com/wp-content/uploads/photo.jpg'.
That tells you exactly which file is the problem. Check a few different page types (home page, a post, a page, your contact form), because a widget or a single post can be the only offender.
To find every stored copy at once, search the database with WP-CLI:
wp db search 'http://example.com' --all-tables
Step 2: Set both site URLs to https
In Settings > General, make sure WordPress Address and Site Address both start with https:// and match the www or non-www version your site actually uses. If changing these locks you out with a redirect loop, see How to Fix ERR_TOO_MANY_REDIRECTS in WordPress.
Step 3: Search and replace old URLs in the database
This fixes most mixed content in one pass. Back up first. Then do a dry run, which reports what would change without changing anything:
wp db export before-https.sql
wp search-replace 'http://example.com' 'https://example.com' --all-tables --skip-columns=guid --dry-run
# looks right? run it for real
wp search-replace 'http://example.com' 'https://example.com' --all-tables --skip-columns=guid
A few notes from doing this on a lot of sites:
- Run it again for
http://www.example.comif your site ever used www. - WP-CLI’s search-replace handles serialized data correctly. A raw SQL
UPDATE ... REPLACE()query does not, and can break widgets and theme settings. - Skip the
guidcolumn. WordPress uses it as a permanent ID, not a link, and the official advice is to leave it alone. - No WP-CLI? The Better Search Replace plugin does the same job from wp-admin, including a dry run.
Try it on a staging copy first if your host gives you one. Here is how staging works on Pressable.
Step 4: Check the theme, widgets, and custom CSS
If the console still shows warnings after the search and replace, the URL is probably not in the database. Places to look:
- Theme files: search your theme for
http://. Background images instyle.cssare a common one. - Page builders that cache CSS to files. Elementor, for example, has a Regenerate CSS option under Elementor > Tools. Run it after the replace.
- Hardcoded script or font tags added by a plugin or in a header/footer code snippet
- Third-party embeds. If an old widget or iframe only works over HTTP, swap it for an HTTPS version or remove it.
Step 5 (stopgap): Tell browsers to upgrade requests
The upgrade-insecure-requests directive tells the browser to request every http:// resource on the page over HTTPS instead. You can send it as a header from your server or CDN:
Content-Security-Policy: upgrade-insecure-requests
SSL plugins like Really Simple SSL can add it for you too. It only works if the file actually exists on HTTPS, and it hides the problem rather than fixing it, so I treat it as a stopgap while the database cleanup gets done.
Step 6: Purge caches and test again
Page caches, CDNs, and minify plugins can keep serving the old HTML with the old URLs. Purge everything, then reload the page in a private window and check the console again. A clean console and a padlock means you are done.
Where http:// URLs hide, and how to fix each
| Where it lives | Example | Fix |
|---|---|---|
| Post and page content | Images inserted before the HTTPS switch | wp search-replace or Better Search Replace |
| Widgets and theme settings | Logo URL, footer HTML | search-replace (handles serialized data) |
| Theme files | Background image in style.css | Edit the file, use https or a relative path |
| Page builder CSS files | Cached CSS with old URLs | Regenerate CSS in the builder’s tools |
| Third-party embeds | Old widget or iframe on http | Use the HTTPS embed code or remove it |
Free SSL on every domain
Pressable issues free SSL certificates for every domain on your site, and includes staging sites, so you can test a database search and replace before you run it on the live site.
FAQ
What is mixed content in WordPress?
Mixed content is when a page served over HTTPS loads some files, such as images, scripts, or stylesheets, over plain HTTP. It usually comes from old http:// URLs left in the database after a switch to HTTPS.
How do I find mixed content on my site?
Open the page in Chrome, press F12, and check the Console tab. Each insecure file is listed with its full URL. WP-CLI’s wp db search command finds every stored copy in the database.
Do I need the Really Simple SSL plugin to fix mixed content?
No. A one-time search and replace of http:// URLs in the database fixes most cases without a plugin. An SSL plugin can help as a stopgap while you clean up.
Why does my site still say Not secure after fixing mixed content?
Check for cached pages, a form that submits to an http:// address, hardcoded URLs in theme files, or an expired SSL certificate.
Should I replace http with https in the guid column?
No. WordPress uses the guid as a permanent identifier, not a link, so skip it with –skip-columns=guid.
Related posts
- How to Fix ERR_TOO_MANY_REDIRECTS in WordPress
- How to Point Your Domain to WP Engine (DNS Records and SSL)
- How to Add a Domain to Pressable and Set the Primary Domain
- Pressable Staging Sites: How to Create One and Push It Live
- How to Speed Up WordPress: Fixes That Start With Your Host
- WordPress Security Best Practices