As I accidentally found, transparent blank image comes with response header indicating possible cause of the problem.
https://external-ams3-1.xx.fbcdn.net/safe_image.php?d=...&url=...
)x-error-detail
response header with explanationFor example, in my case it was Invalid image extension for URL: https://[mydomain]/[myfilename].jpg
The real issue in my case was related to prerender.io.
As it turns out, if image is requested via prerender, it's converted to HTML. Something like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head>
<body style="margin: 0px;"><img style="-webkit-user-select: none; cursor: -webkit-zoom-in; " src="https://[yourdomain].com/[yourfilename].jpg" width="1078" height="718"></body>
</html>
It's either bug in prerender itself, or it's supposed to be configured in your proxy to not use prerender for *.jpg
requests (even if they are requested by Facebook bot).
It's really hard to notice this, as prerender is used only on certain user-agent headers.