I got a call last week from a client, pretty frustrated. They’d just rolled out a fresh WordPress site, SSL configured perfectly, but their social media links in the footer? Still showing up as http://. Browser warnings, weird redirects, the whole nine yards. Total mess. Turns out, it was our old friend, WordPress’s URL escaping functions, specifically esc_url() and esc_url_raw().
For years, when you passed a URL string to these functions without a protocol, WordPress would just slap http:// on the front by default. Reasonable fallback behavior back in the day, sure, but in 2024? With HTTPS being the absolute standard? It was an unnecessary headache. Developers were constantly fighting it, manually patching output, or worse, just ignoring it, leading to those mixed content warnings we all dread.
The Old Headache: Forcing HTTPS on Escaped URLs
My first thought, and I’ve seen countless devs do this, is to just run a quick str_replace() after the esc_url() call to switch http:// to https://. Or even worse, trying to preprocess the URL before it hits the escaper. You might think, “Hey, it works!” And yeah, it might *appear* to work in a specific scenario. But man, that’s just a brittle workaround. You’re essentially bypassing the very security and sanitization checks WordPress built into these functions. That’s a recipe for a total nightmare, potentially allowing malformed or even malicious URLs to slip through. Not good. The real fix had to be at the source, with the core functions themselves.
WordPress 6.9 Delivers: A Proper HTTPS Default
Thankfully, with WordPress 6.9, this specific pain point is finally addressed. The core team has updated esc_url() and esc_url_raw() to properly support HTTPS as the default protocol when a scheme isn’t explicitly provided. This builds on a core dev note I saw over on the make.wordpress.org blog, which details the changes. Here’s the kicker: it only kicks in if the first item in your $protocols array is 'https'.
So, instead of hacking around with string replacements, we now have a clean, built-in way to ensure our URL-escaped strings default to HTTPS:
<?php
/*
* Recommended approach for defaulting to 'https' while maintaining
* backward compatibility.
*
* Example: no protocol with $protocols and 'https' first.
*
* Output:
* - WordPress >= 6.9: 'https://profiles.wordpress.org'
* - WordPress < 6.9: 'http://profiles.wordpress.org'
*/
echo esc_url( 'profiles.wordpress.org', array( 'https', 'http' ) );
/*
* If you only allow HTTPS, older WordPress versions will return an empty string.
*
* Output:
* - WordPress >= 6.9: 'https://profiles.wordpress.org'
* - WordPress < 6.9: ''
*/
echo esc_url( 'profiles.wordpress.org', array( 'https' ) );
?>
- By including
'https'first, WordPress 6.9 will prependhttps://to incomplete URLs. This is the behavior we want in an HTTPS-first world. - For older WordPress versions, it will gracefully fall back to prepending
http://(if'http'is also in the array), which maintains backward compatibility. If you only specify'https', older versions will return an empty string becausehttpisn’t in its allowed protocols list, which isn’t ideal for compatibility. Something to be aware of.
So, What’s the Takeaway?
This update is a subtle but significant win for security and developer sanity. It means less fighting against core functionality and more confident URL handling. Always leverage WordPress’s built-in functions; they’re there for a reason. And always stay on top of core updates, because even small changes like this can save you hours of debugging and a lot of client headaches.
Look, this stuff gets complicated fast. If you’re tired of debugging someone else’s mess and just want your site to work, drop my team a line. We’ve probably seen it before.
Leave a Reply