Features

The SSL Image Proxy

Published

External Images lets your site display pictures that physically live on someone else’s server, usually an affiliate CDN or a supplier’s image host. Most of the time the browser just loads that external URL directly and everything is fine. The SSL proxy exists for the cases where loading the image straight from its original host causes a problem, and it fixes those cases by fetching the image and re-serving it from your own domain.

The problem it solves

If your site runs over https (as every site should), but an external image URL is only http, the browser treats that as mixed content. Depending on the browser and the theme, the image either fails to load or triggers a “not fully secure” warning, and the padlock in the address bar disappears. Feed-driven and affiliate catalogues are the usual culprits, because the source URLs were often recorded as http years ago.

There is a second, subtler problem. Some social and SEO scrapers (Facebook, X/Twitter, various link-preview bots) are fussy about images that sit on a third-party host, or simply refuse to fetch an http image for an https page. That can leave your shared links without a preview thumbnail even though the product page shows the image perfectly.

The SSL proxy addresses both. Instead of pointing the browser at the awkward external URL, the plugin fetches the image itself and serves it back through your own domain over https. To the browser, and to any scraper, the image now looks like it came from your site: same origin, valid https, no mixed-content warning.

How the automatic trigger works

The important thing to understand is that proxying is a last resort, not the default. The plugin tries the cheapest fix first and only proxies when nothing else will work.

When it renders an external image, and the current page is being served over https, the plugin looks at the image URL. It detects https from the incoming request in three ways so that it works behind Cloudflare and other proxies as well as directly: the request scheme, the server protocol, and the X-Forwarded-Proto header. If the page is https and the image URL is already https, there is nothing to do. If the page is https and the image URL is http, the plugin steps in.

Its first move is not to proxy but to test whether the image’s own host will serve the same file over https. It does a quick HEAD request to the https version of the URL and remembers the answer per domain (so it only tests each host once, not once per image). If that host does support https, the plugin simply rewrites http:// to https:// and serves the original URL. No proxying, no copy, no extra load on your server. Many CDNs pass this test, which is why most http images never actually get proxied.

Only when the remote host does not support https does the plugin fall back to true proxying: it downloads the image once and caches it into wp-content/uploads/external-images/, then serves that local copy from your own domain. Supported image types are png, jpg, jpeg, gif and svg.

Did you know?

The https test is a single HEAD request per domain, not per image. The plugin remembers whether a host supports https and reuses that answer for every image on it, so a whole CDN is checked once. That is why the protocol rewrite is effectively free even across a large catalogue.

There is also a manual switch on the settings page called “Proxy All Images”. With that enabled, external images are copied into your uploads folder and served from your domain regardless of protocol, so that everything appears under your own name. This consumes disk space over time and is really only for people who cannot use a dedicated image subdomain. The settings page recommends using a subdomain of your own (for example images.yourdomain.com) for SEO instead, which is covered in “Guide to third party storage”.

Turning it off

If you never want the plugin to proxy an image, define the constant in your wp-config.php:

define('EI_NEVER_ATTEMPT_PROXY', true);

It defaults to false. When set to true, the proxy step is skipped and the original image URL is returned untouched, so you keep the http-to-https rewrite behaviour but never the download-and-cache behaviour.

Datafeedr comparison sets

Datafeedr comparison sets already use external image URLs, and the plugin recognises them and runs those images through the same SSL handling. So if you use comparison sets on an https site, their images are made secure the same way as any other external image. See “Datafeedr Integration” for how the two plugins fit together.

og:image for social sharing

Because proxied images are served from your own domain, the plugin can also output its own og:image and twitter:image meta tags pointing at a secure, same-origin URL. That is what makes link previews reliable on Facebook and X even when the underlying image lives on an affiliate CDN. There is more on the social tags in the “Frequently Asked Questions”.

Practical notes

  • The proxy trades a little server work for correctness. The first time an uncached image is proxied, your server makes an outbound request to fetch it, which slows that page’s generation. After that the file is on disk in your uploads folder and is served straight from there, and the proxy response is sent with a long cache lifetime.
  • If your external host already serves valid https, you almost certainly do not need the proxy at all. The plugin will detect this and just rewrite the protocol, which costs nothing.
  • Proxying needs outbound HTTP requests to be allowed on your server (the fetch uses WordPress’s own HTTP layer, and the https test uses cURL). On locked-down hosts these can be blocked.
  • The proxy interacts with the rest of the rendering pipeline described in “How External Images Works”, and with the third-party plugins listed in “Compatibility and Integrations”.

Further reading

the image subdomain approach the settings page recommends over Proxy All Images
how the proxy sits alongside Cloudflare, Datafeedr and the themes
the `ssl-proxy.php` endpoint and the `EI_NEVER_ATTEMPT_PROXY` constant in detail

Comments

▲
▼
1/1