When you can't edit the size in an image URL: signed variants on itch.io and Flickr
In my last two posts I rewrote size tokens in image URLs: change feed_thumbnail to feed_fullsize, drop .600x338, and the CDN hands you the bigger file. That trick has a limit. Some CDNs sign each size, so the URL for the
In my last two posts I rewrote size tokens in image URLs: change feed_thumbnail to feed_fullsize, drop .600x338, and the CDN hands you the bigger file. That trick has a limit. Some CDNs sign each size, so the URL for the large copy contains a value you can't compute from the small one. Edit the size and keep the old signature, and the server refuses.
I measured two sites that work this way and one that doesn't, on 10 November 2026. Each file was fetched with curl (Flickr through Chrome, since it rate limits plain curl from my IP) and the pixel size was read from the image itself with Pillow or createImageBitmap.
itch.io: a signature per size
A screenshot on an itch.io game page looks like this:
https://img.itch.zone/aW1hZ2UvNDM0NTU0LzcwMTEwMTIuanBn/347x500/ca0rKj.jpg
The first segment is base64 for image/434554/7011012.jpg, the stored file. The second is the size box. The last one, ca0rKj, is a signature over both. The page uses three variants of that screenshot, each with its own signature:
| URL tail | Where it appears | Result |
|---|---|---|
347x500/ca0rKj.jpg |
src |
347×195, 30,571 bytes |
794x1000/ei%2BnwE.jpg |
srcset 2x |
794×446, 86,736 bytes |
original/3t28LO.jpg |
<a href> around the image |
1920×1080, 263,991 bytes |
Now the obvious edit, swapping the size and keeping the signature:
| URL tail | Result |
|---|---|
original/ca0rKj.jpg |
404, body not found (bad signature)
|
794x1000/ca0rKj.jpg |
404, same body |
1000x1000/ca0rKj.jpg |
404, same body |
original/3t28LO.jpg on another screenshot's path |
404 |
The last row matters: the signature covers the image path too, so you can't reuse one valid original signature across screenshots. Without the server's secret there is no URL to construct.
The page already has the answer, though. Here is the markup, trimmed:
<a data-image_lightbox="true"
href="https://img.itch.zone/aW1hZ2Uv.../original/3t28LO.jpg">
<img src="https://img.itch.zone/aW1hZ2Uv.../347x500/ca0rKj.jpg"
srcset=".../347x500/ca0rKj.jpg 1x, .../794x1000/ei%2BnwE.jpg 2x"
class="screenshot">
</a>
The lightbox link points at the 1920×1080 upload, already signed.
Flickr: a different secret per size
Flickr URLs put a hex secret before the size letter. On one Explore photo:
| URL tail | Result |
|---|---|
55638737042_37e1244f5b.jpg |
499×333 |
55638737042_37e1244f5b_w.jpg |
400×267 |
55638737042_37e1244f5b_b.jpg |
1024×683 |
55638737042_37e1244f5b_h.jpg |
410 |
55638737042_37e1244f5b_k.jpg |
410 |
55638737042_37e1244f5b_o.jpg |
410 |
So the small sizes share one secret and the large ones don't. The photo page's HTML lists the large sizes with their own secrets:
| URL tail | Result |
|---|---|
55638737042_e02d4a895b_h.jpg |
1600×1067 |
55638737042_91033b130b_k.jpg |
2048×1365 |
55638737042_93ce021d94_o.jpg |
8256×5504, 24,303,853 bytes |
Three sizes, three secrets, none derivable from 37e1244f5b. On Explore and album grids only the small URLs are in the DOM, so anything that works from the grid has to stop at _b or go fetch every photo page.
Gumtree: a named variant, no signature
For contrast, Gumtree's image CDN names its variants and checks nothing else. One ad photo:
| URL tail | Result |
|---|---|
/86 (what the ad page loads) |
768×507, 46,852 bytes |
/public |
1163×768, 96,698 bytes |
/1 |
400×264 |
/79 |
320×211 |
/original |
404 |
Here a rewrite rule is fine, because the variant name is the whole key. I can't tell whether /public is the uploaded file or just the largest variant, only that it's the largest one I found.
What the extension does about it
When the size is signed, guessing a URL is pointless, so the image downloader I build does two cheaper things. First, when an <img> is wrapped in a link whose href looks like an image file, it keeps that link as the full-size candidate:
const IMG_LINK_RE = /\.(jpe?g|png|gif|webp|avif|bmp|svg|tiff?|jfif)(?:$|[?#])/i;
const a = el.closest('a[href]');
const href = a && a.getAttribute('href');
const linkFull = href && IMG_LINK_RE.test(href) ? href : null;
On itch.io that picks up original/3t28LO.jpg for every screenshot, with no site-specific code. Second, it parses srcset per the HTML spec and takes the largest candidate, so even without the link it would get the 794 px copy instead of the 347 px one.
The link still goes through the same URL rules as everything else, because some gallery links are themselves resized copies, and the unmodified link stays as a fallback if the rewritten one fails. For Flickr the rule only rewrites small suffixes to _b; a test pins that boundary so nobody "improves" it into a 410 later.
The general lesson I took from this: before writing a rewrite rule, fetch the variant with the old signature and see whether the server checks it. If it does, look in the page for a link or a srcset the site already signed for you.
I wrote up the itch.io steps, with and without an extension, here: how to download itch.io screenshots in full size. The extension that does the link and srcset handling above is PixLasso, a Chrome extension for saving images from a page.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.