Bali, Indonesia
Insights

How to Find Mixed Content Resources Blocking the Browser Padlock

October 16, 2026
0:00
You just finished installing a valid SSL certificate on your web server, configured redirection from HTTP to HTTPS, and loaded your site, only to find that the browser address bar still shows an info icon, an unlocked padlock, or a warning that your connection is not fully secure. In the hosting support desk, this is one of the most common post-migration questions we encounter. The certificate itself is working and your web server handshake is valid, but the browser has detected that some secondary assets on the page are still loading over plain, unencrypted HTTP. When an HTTPS webpage pulls in subresources—such as images, scripts, stylesheets, audio, or fonts—over an unencrypted HTTP link, browsers categorize this condition as mixed content. Because unencrypted network traffic can be intercepted, read, or tampered with on public networks, modern browsers flag the entire page as partially insecure or outright block the unencrypted files from executing. To restore the clean padlock icon across all pages, you need a systematic way to locate where these unencrypted URLs originate and replace them at the source.
Before digging into browser diagnostic tools, it helps to know how browsers classify mixed resources, because the severity and visual symptoms differ between asset types. Browsers divide mixed content into two primary buckets: passive mixed display content and active mixed scripting content. Passive content refers to resources that cannot directly alter the Document Object Model (DOM) or read sensitive session data on the page. Images, video files, and audio elements fall into this category. If an attacker tampers with an unencrypted image during transit, they might display a misleading or inappropriate picture, but they cannot steal authentication cookies or inject executable code. For this reason, older browsers historically allowed passive mixed content to load while simply downgrading the address bar from a solid green padlock to a neutral icon or a padlock with a yellow warning triangle. Active mixed content, on the other hand, consists of resources that can directly manipulate the page, execute JavaScript, or intercept user inputs. This includes external JavaScript files (<script src="http://...">), CSS stylesheets (<link rel="stylesheet" href="http://...">), Web Fonts, <iframe> embeds, and XMLHttpRequest or Fetch calls. If an attacker on the local network tampers with an unencrypted stylesheet or script, they can rewrite forms, capture keystrokes, or redirect visitors to malicious destinations. Because of this high risk, all modern browsers automatically block active mixed content by default. The browser will not even attempt to download the file; it simply logs an error in the developer console and leaves your site with missing layouts, broken buttons, or failed AJAX requests. Many modern browsers have also begun auto-upgrading passive mixed content (such as images) to HTTPS in the background. If the remote image host supports HTTPS, the browser silently rewrites the URL and fetches it safely. However, if that remote server does not have an SSL certificate configured, the image request fails completely, leaving a broken image placeholder on your layout. Relying on browser-level fallback behavior is never a reliable long-term strategy; locating and fixing the hardcoded links at the source remains essential.
When a site exhibits mixed content warnings, work through these diagnostic steps in order. This sequence moves from immediate browser diagnostics to file-level and database audits.
  1. Inspect the Browser Developer Tools Console first.
    Opening your browser developer tools (F12 or Ctrl+Shift+I on Linux and Windows, Cmd+Option+I on macOS) and navigating to the Console tab is the fastest diagnostic step because browsers explicitly print an error or warning for every single mixed content request. Modern engines like Chromium and Gecko output a distinct message stating that a resource was loaded over an insecure connection along with the exact URL of the offending asset. This gives you the target filename and its full path immediately without guesswork.
  2. Filter the Network tab by protocol to catch dynamically triggered assets.
    Switch to the Network tab in developer tools, ensure the "Preserve log" checkbox is enabled, and reload the page with a hard refresh (Ctrl+F5 or Cmd+Shift+R). Right-click the column headers in the request list, enable the Scheme or Protocol column, and look for any row showing http instead of https or h2. This helps identify secondary requests initiated dynamically by tracking scripts, fonts loaded through @import, or AJAX polling that might not trigger an obvious red error in the main console view.
  3. Audit external CSS stylesheets for hardcoded font and background URLs.
    If the console flags a font or a background pattern that does not appear in your HTML source code, the reference is almost certainly buried inside a compiled CSS file. Web designers often hardcode absolute HTTP paths inside @font-face blocks or background-image: url('http://...') rules. When your HTML loads over HTTPS, the browser fetches the stylesheet, reads the CSS declaration, and triggers an unencrypted sub-request for the image or font file.
  4. Check for hardcoded schema links inside theme templates and static HTML.
    Scan your template files—such as header, footer, and sidebar partials—for explicit http:// links inside <link>, <script>, or <img> tags. Developers often hardcode logos, favicon paths, or third-party tracking snippets during local development using plain HTTP, forgetting that production templates will execute under HTTPS.
  5. Inspect CMS database tables for absolute image and media URLs.
    Content management systems such as WordPress store full, absolute URLs in database tables like wp_posts and wp_postmeta when authors insert images or embedded media into articles. If your site existed on HTTP before you added an SSL certificate, every legacy blog post contains hardcoded http://yourdomain.com/wp-content/uploads/... links inside the database text fields.
  6. Audit third-party widgets, badges, and analytics scripts.
    External trust seals, visitor counters, weather widgets, and ad banners provided by third parties frequently supply legacy embed codes written with explicit http:// prefixes. If the third-party provider does not support HTTPS on their asset server, you must either remove the widget entirely, host the asset locally on your own secure server, or replace the provider with a secure alternative.
  7. Verify CDN and reverse proxy custom origin settings.
    If you route your traffic through a content delivery network or a reverse proxy like Cloudflare, check how the proxy communicates with your origin server. If your CMS generates canonical URLs based on the incoming web server port and your proxy forwards traffic to the origin on port 80 over plain HTTP, the CMS may continue generating absolute internal links using http:// even though the visitor connected to the proxy via HTTPS.
Once you have identified where the insecure links live, the resolution process depends on whether the resource belongs to your own domain or an external service. For internal media references stored in a database, perform a serialized-safe search and replace. Never run a raw SQL UPDATE statement on a CMS database without checking whether the platform stores configuration data as serialized PHP strings; running a basic string replacement inside serialized arrays will corrupt string length counters and break your layout or widget settings. Instead, use a specialized tool such as the WP-CLI command-line utility for WordPress, or an administrative search-and-replace plugin designed to handle serialization safely. When updating code in theme templates or custom CSS, switch to root-relative paths or explicit HTTPS URLs. In the past, developers commonly used protocol-relative URLs (such as //example.com/image.png), which instructed the browser to match whichever protocol the parent page was using. However, modern security standards recommend using explicit https:// prefixes everywhere, even for internal staging environments, to ensure assets are always encrypted regardless of how the page was requested.
If you have thousands of legacy pages and cannot immediately audit every piece of archived user content, you can instruct modern browsers to automatically upgrade insecure resource requests before fetching them. This is accomplished using the Content-Security-Policy (CSP) response header. By adding the upgrade-insecure-requests directive to your web server configuration or application headers, you tell compliant browsers that every HTTP subresource requested by the page must be treated as if it were written as HTTPS. The browser rewrites http:// to https:// in memory prior to firing the network request. In Nginx, you can add this directive inside your virtual host server block:
NGINX
# Instruct compliant browsers to automatically upgrade insecure subresources to HTTPS
add_header Content-Security-Policy "upgrade-insecure-requests;" always;
This header provides an effective safety net while you clean up older database entries and templates. Keep in mind that upgrade-insecure-requests is not an absolute cure for every problem: if an external third-party domain hosting one of your scripts or images does not have an active SSL certificate on port 443, the upgraded request will fail with an SSL handshake error, and the resource will still not render. The header merely prevents the browser from downgrading your security status by refusing to send unencrypted requests over the wire.
After you have updated your database records, rewritten template links, or deployed the CSP header, you must verify the result thoroughly. The most frequent stumbling block during this phase is aggressive caching. Always clear your local browser cache before re-testing. Browsers aggressively cache 301 redirects, stylesheets, and image lookup failures. If you reload a page normally, you may see persistent mixed content errors simply because the browser is reading a cached copy of a stylesheet that still holds an old http:// background image path. Next, clear server-side object caches (such as Redis or Memcached) and page cache plugins. If your web application caches rendered HTML output to disk or memory, visitors will continue to receive the old HTML containing insecure links until that cache expires or is manually purged. Finally, purge your CDN edge cache if you utilize external proxy distribution. Once both edge and local caches are empty, re-open Developer Tools, visit key landing pages—including the homepage, checkout screens, and older blog archives—and confirm that the console remains free of yellow warnings. With every subresource loading through a valid TLS handshake, the browser will display the standard clean padlock icon across all sessions.