Wsrv.nl (images.weserv.nl) Resizing Proxy & CDN

Wsrv.nl (formerly known as images.weserv.nl) is a free image resizing proxy and CDN: hand it any public image URL plus a few query parameters, and it returns a resized, converted, and optimized version served from Cloudflare’s global edge cache.

No account, no API key, no build step, the entire API is the URL.

https://wsrv.nl/?url=example.com/photo.jpg&w=600&output=webp

I run every content image on this site through it, and I’ve deployed it on client projects serving millions of pageviews. This article covers how it works, the features I actually reach for, and the full parameter reference.

How It Works

Wsrv.nl is an origin-pull proxy. The first time a URL is requested it fetches the source image, transforms it according to your query parameters, and caches the result on Cloudflare’s CDN. Every subsequent request for that exact URL is served straight from the edge, so your origin server is hit once per variant rather than once per visitor. Cached images are kept and re-validated automatically, and you can control browser caching yourself with the maxage parameter.

The service has been running continuously since 2007, it predates most commercial image CDNs, and now serves billions of images per month for millions of websites. Uptime has been remarkably good for a free service (they publish a public status page at status.wsrv.nl); the one notable rough patch was a Cloudflare terms-of-service change in late 2022 that rate-limited the old images.weserv.nl hostname, which is why the canonical domain is now wsrv.nl, I wrote up the fix in Images.weserv.nl Slow Loading at the time.

Full documentation lives at wsrv.nl/docs.

Useful Features

Resize

Pass w, h, or both. With only one dimension the aspect ratio is preserved automatically, this is the workhorse for responsive images:

# 600px wide, height follows the aspect ratio
https://wsrv.nl/?url=example.com/photo.jpg&w=600

# 400px tall, width follows
https://wsrv.nl/?url=example.com/photo.jpg&h=400

# Both: fits inside a 600x400 box, ratio preserved
https://wsrv.nl/?url=example.com/photo.jpg&w=600&h=400

Convert to WebP

output=webp converts any source format on the fly, typically 25-35% smaller than the equivalent JPEG with no visible difference. This one parameter is the fastest Core Web Vitals win available:

https://wsrv.nl/?url=example.com/photo.jpg&output=webp&q=80

Smart Cropping: Entropy & Attention

When cropping to a fixed shape, a=entropy centers the crop on the busiest region of the image and a=attention on the area most likely to draw the eye (faces, high-contrast zones). Far better than blind center-cropping for cards and thumbnails:

https://wsrv.nl/?url=example.com/photo.jpg&w=400&h=400&fit=cover&a=attention

Tint / Colorize

filt=greyscale plus tint re-colors an image to a single hue. I use this on puck.news to pull editorial photography into their brand palette without touching Photoshop, every image on a listing page tinted consistently, from one URL parameter:

https://wsrv.nl/?url=example.com/photo.jpg&filt=greyscale&tint=79589f

DPR for Retina/High-Res Screens

dpr=2 doubles the output density for the same layout size, so a 300px-wide image ships 600 physical pixels for high-DPI phones and laptops. Pair it with a lower q, dense pixels hide compression artifacts:

https://wsrv.nl/?url=example.com/photo.jpg&w=300&dpr=2&q=70

PDF Preview Images

Point it at a PDF and it renders a page as an image, an on-the-fly document thumbnail with no ImageMagick server setup. page selects which page (zero-based):

https://wsrv.nl/?url=example.com/whitepaper.pdf&w=400&page=0&output=jpg

Sharpen

sharp runs an unsharp mask after resizing. Downscaled headshots and product photos often come out slightly soft; a mild sharpen restores the crispness:

https://wsrv.nl/?url=example.com/headshot.jpg&w=240&h=240&fit=cover&sharp=2

fit=cover fills the exact target dimensions and crops the overflow, the right behavior for blog listing cards where every featured image must be the same shape regardless of what editors upload:

https://wsrv.nl/?url=example.com/featured.jpg&w=720&h=405&fit=cover&a=entropy&output=webp

Quality

q sets the lossy compression level (1-100, default 80). For content photography 70-80 is visually transparent; go lower for large hero backgrounds where fine detail doesn’t matter:

https://wsrv.nl/?url=example.com/hero.jpg&w=1600&q=60&output=webp

Under the Hood: libvips

The image processing engine behind wsrv.nl is libvips, a demand-driven, horizontally-threaded image library that’s dramatically faster and lighter on memory than ImageMagick, it streams images through the pipeline instead of decompressing the whole file into RAM. It’s the same engine behind sharp (Node.js) and many commercial image services.

The wsrv.nl server itself is open source too: weserv/images is an nginx module wrapping libvips, published under a BSD 3-Clause license. If a free third-party service in your critical rendering path makes you nervous, you can self-host the exact same stack on your own infrastructure and keep the identical URL API, the free public service and full control are the same software, just a different host.

All Available Query Parameters

Name GET Description
Width w Set the output width in pixels, or as a percentage of the source with a trailing %. info
Height h Set the output height in pixels, or as a percentage of the source with a trailing %. info
Device pixel ratio dpr Multiply the output dimensions for high-DPI screens (e.g. dpr=2 doubles the pixel density at the same layout size). info
Fit fit How the image fills the target box when both dimensions are set: inside, outside, cover (crop overflow), contain (letterbox), or fill (stretch). info
Contain background cbg Background color for the letterbox bars added by fit=contain. info
Without enlargement we Never scale the image beyond its source dimensions, small originals stay small instead of upscaling blurry. info
Alignment position a Where a fit=cover crop anchors: an edge or corner (top, bottom-left, …), a focal point, or the smart modes entropy and attention. info
Rectangle crop crop Cut an exact rectangle from the image as width,height,x,y, applied after any resize. info
Pre-resize crop precrop Apply the rectangle crop to the original image before resizing, instead of after, coordinates refer to source pixels. info
Trim trim Automatically remove near-uniform borders (whitespace) from all four edges; the value sets the color-difference tolerance. info
Trim background tbg The border color trim should look for, instead of detecting it from the top-left pixel. info
Masking mask Clip the image to a predefined shape: circle, ellipse, triangle, pentagon, hexagon, star, heart, and more. info
Mask trim mtrim Crop away the transparent whitespace left around the masked shape. info
Mask background mbg Fill the area outside the mask with a color instead of transparency. info
Flip flip Mirror the image vertically (top becomes bottom). info
Flop flop Mirror the image horizontally (left becomes right). info
Rotation ro Rotate the image by any angle in degrees; multiples of 90 are lossless. info
Rotation background rbg Background color revealed in the corners when rotating by a non-right angle. info
Background bg Flatten transparent areas of the image onto a solid color. info
Blur blur Apply a Gaussian blur; the value (0.3-1000) is the sigma, higher = blurrier. info
Contrast con Increase or decrease contrast, from -100 (flat) to +100 (harsh). info
Filter filt Apply a color filter: greyscale, sepia, duotone, or negate. info
Gamma gam Gamma-correct the image to lighten or darken midtones without clipping highlights or shadows. info
Modulate mod Adjust brightness, saturation, and hue rotation together as comma-separated multipliers. info
Saturation sat Multiply color saturation: 0 is greyscale, 1 unchanged, higher values more vivid. info
Hue rotation hue Rotate every color’s hue around the color wheel by the given number of degrees. info
Sharpen sharp Apply an unsharp mask after resizing, restores crispness lost when downscaling. info
Tint tint Re-color the image’s luminance with the given hex color; combine with filt=greyscale for a clean single-hue result. info
Adaptive filter af Apply an adaptive row filter before PNG compression, which can shrink PNGs with gradients. info
Base64 (data URL) encoding Return the image as a base64 data URL for inlining directly into an <img src=> attribute. info
Cache-Control maxage How long browsers (and the CDN) should cache the result, e.g. maxage=31d or maxage=1y. info
Compression level l PNG zlib compression level from 0-9: higher is smaller but slower to encode (default 6). info
Lossless compression ll Use lossless WebP encoding instead of lossy, pixel-perfect output at larger file sizes. info
Default image default Fallback image URL to redirect to when the source image fails to load, no more broken image icons. info
Filename filename Filename to send in the Content-Disposition header, controlling what a downloaded copy is saved as. info
Interlace / progressive il Encode PNG/GIF as interlaced and JPEG as progressive, so images render in increasing detail while loading. info
Number of pages n How many pages or frames to render from multi-page sources (PDF, animated GIF/WebP, multi-page TIFF). info
Output output Force the output format: jpg, png, webp, gif, tiff, or json (image metadata). info
Page page Which page or frame to load from a multi-page source, zero-based (e.g. page=0 is a PDF’s first page). info
Quality q Lossy compression quality from 1-100 for JPEG, WebP, and TIFF (default 80). info