Serveproxy

Documentation

Everything the image proxy does, and how to use it on your site.

URL format

Pass the address of the original image in the url parameter:

https://serveproxy.com/?url=https%3A%2F%2Fexample.com%2Fimages%2Fphoto.jpg

Encode the source URL with encodeURIComponent or your language's equivalent. Unencoded URLs work when they have no query string of their own, but encoding is always safe.

Each distinct source URL is converted and cached separately. photo.jpg and photo.jpg?v=2 are two different images.

Request lifecycle

  1. Check. The request is checked against the rate limit and the source domain against our blocklists.
  2. Fetch. On a cache miss, the image is downloaded from your server over HTTPS (http:// sources are upgraded). Requests to private and internal network addresses are refused.
  3. Detect. The file type is read from the image's bytes, not from its extension or the Content-Type your server sent.
  4. Convert. The image is converted according to the table below.
  5. Cache. The result is served with a 7-day immutable Cache-Control header and cached by Cloudflare's edge network.

The first request for an image usually takes one to three seconds. Every request after that is served from cache.

Output formats

SourceOutputSettings
JPEG, PNG, static GIF, BMP, TIFF, HEICAVIFQuality 65, metadata stripped
WebP (static or animated)WebPPassed through unchanged
Animated GIFAnimated WebPFrame timing and looping kept
SVGSVGSanitized, served with a restrictive Content-Security-Policy
AVIF cases with jxl=trueJPEG XLQuality 75, effort 7, metadata stripped

SVG sanitization removes <script> elements, <foreignObject>, on… event handlers and javascript: links. The drawing itself is left intact.

Multi-frame sources other than GIF (for example animated PNG or multi-page TIFF) are converted from their first frame.

JPEG XL

Optional output format.

Add jxl=true as the first query parameter. It has to come before url=, because everything after url= is treated as part of the source address.

https://serveproxy.com/?jxl=true&url=https%3A%2F%2Fexample.com%2Fphoto.jpg

Limited browser support. JPEG XL renders in Safari on macOS and iOS. Chrome, Edge and Firefox don't display it by default. Use it only inside a <picture> element with an AVIF fallback:

<picture>
  <source type="image/jxl"
          srcset="https://serveproxy.com/?jxl=true&url=https%3A%2F%2Fexample.com%2Fphoto.jpg">
  <img src="https://serveproxy.com/?url=https%3A%2F%2Fexample.com%2Fphoto.jpg"
       alt="Harbour at dusk" loading="lazy">
</picture>

WebP, animated GIF and SVG sources keep their normal output when jxl=true is set.

Limits

LimitValue
Uncached requests per IP5,000 every 10 minutes
Block after exceeding the limit1 hour
Maximum source image size5 MB
Source fetch timeout15 seconds

Requests answered from Cloudflare's cache never reach our servers and don't count toward the limit. Responses from our servers include X-RateLimit-Remaining.

Integration examples

HTML

<img src="https://serveproxy.com/?url=https%3A%2F%2Fexample.com%2Fimage.jpg"
     alt="Description" loading="lazy">

JavaScript

function optimized(originalUrl) {
  return "https://serveproxy.com/?url=" + encodeURIComponent(originalUrl);
}

img.src = optimized("https://example.com/image.jpg");

Responsive images

<img src="https://serveproxy.com/?url=https%3A%2F%2Fexample.com%2Fimage-800.jpg"
     srcset="https://serveproxy.com/?url=https%3A%2F%2Fexample.com%2Fimage-800.jpg 800w,
             https://serveproxy.com/?url=https%3A%2F%2Fexample.com%2Fimage-1600.jpg 1600w"
     sizes="(max-width: 800px) 100vw, 800px"
     alt="Description" loading="lazy">

Serveproxy doesn't resize images, so provide each size from your own server.

WordPress

The free plugin rewrites image URLs on your pages automatically, with no theme changes.

Response headers

Use these to confirm what was served.

HeaderMeaning
Content-TypeThe output format: image/avif, image/webp, image/svg+xml or image/jxl
CF-Cache-StatusHIT when Cloudflare served the image from cache
Cache-Controlpublic, max-age=604800, immutable (7 days)
ETagLets browsers revalidate with If-None-Match and get a 304
X-Serveproxy-Image-HashIdentifier for the source URL. Include it when you contact support
X-Serveproxy-NodeThe server that converted the image

Troubleshooting

ResponseWhat it means and what to do
400The url parameter is missing, isn't a valid address, or points back at Serveproxy itself. Check that it's encoded.
403The source domain is on one of our blocklists.
404 and other 4xxYour server returned this status for the source image. Open the source URL directly to check it.
413The source image is larger than 5 MB. Resize or compress it on your server.
415The source isn't an image we can read. Check that the URL returns the image itself, not an HTML page.
429Your IP made more than 5,000 uncached requests in 10 minutes. Wait for the block to expire (1 hour).
502Your server didn't respond, timed out after 15 seconds, or returned a 5xx error. Retry in a minute.
Image is outdatedCached images are immutable for 7 days. Change the source URL, for example with ?v=2.

Error responses are cached briefly by Cloudflare: 30 seconds for 502, 5 minutes for 404, 1 hour for 400, 403, 413 and 415.

Live status is at serveproxy.status.hesklo.com. For anything else, email [email protected].