DEV Community

Casper Tran
Casper Tran

Posted on

Reading a Cloudinary URL on nike.com: presets, f_auto and the grey underlay

Nike and adidas serve product photos from Cloudinary on their own domains, static.nike.com and assets.adidas.com. Cloudinary puts the whole image recipe in the URL path, one transformation per segment, so you can read a product photo URL like a short program and edit it. I measured what each part does on 11 November 2026 with curl, reading pixel sizes from the files (and from the AVIF ispe box, since my Pillow build has no AVIF decoder).

Reading the chain

This is the main photo on the Air Force 1 '07 product page, as Chrome loads it:

https://static.nike.com/a/images/t_web_pdp_535_v2/f_auto,u_9ddf04c7-2a9a-4d76-add1-d15af8f0263d,c_scale,fl_relative,w_1.0,h_1.0,fl_layer_apply/b7d9211c-26e7-431a-ac24-b0540fb3c00f/AIR+FORCE+1+%2707.png
Enter fullscreen mode Exit fullscreen mode

Segments between /a/images/ and the photo ID run left to right. Inside a segment, commas join parameters that apply together.

  • t_web_pdp_535_v2 is a named transformation, a preset stored on Nike's account. You can't see what it contains, only what it outputs.
  • f_auto lets the server pick the format from the request's Accept header.
  • u_9ddf04c7-… is an underlay: another image placed behind this one. c_scale,fl_relative,w_1.0,h_1.0 scales it to 100% of the photo's size and fl_layer_apply closes the layer.
  • b7d9211c-… is the uploaded photo, and the product name after it is decoration.

The underlay is a real asset you can fetch on its own: /a/images/9ddf04c7-2a9a-4d76-add1-d15af8f0263d.png comes back as a 400×400 JPEG of flat grey, RGB (236, 236, 234). That is the light grey behind every Nike product shot.

What each edit returns

Same photo, same Chrome-style Accept: image/avif,image/webp,*/* header unless noted:

URL after /a/images/ Type Pixels Bytes
t_web_pdp_535_v2/f_auto,u_…/<id> (desktop page) AVIF 1070×1338 23,072
t_web_pdp_936_v2/f_auto,u_…/<id> (mobile carousel) AVIF 1872×2340 76,245
t_default/u_…/<id> (what the raw HTML has) PNG 320×400 147,200
f_auto,u_…/<id> (preset removed) AVIF 2880×3600 117,444
same, Accept: image/webp,*/* WebP 2880×3600 219,000
same, Accept: */* JPEG 2880×3600 315,747
u_…/<id> (no f_auto) PNG, RGB 2880×3600 6,130,065
<id> (bare upload) PNG, RGBA 2880×3600 3,569,409

The stored photo is 2880×3600, and the page asks for 1070×1338. Delete t_web_pdp_535_v2/ and you get every pixel, still on the grey background, at 117 KB as AVIF.

f_auto matters more for bytes than the size step does. Drop it and the server falls back to the upload's own format, PNG, and the grey underlay makes it a 6.1 MB opaque PNG. The bare upload is smaller (3.6 MB) because it keeps the alpha channel: pixel (5, 5) is (255, 255, 255, 0), fully transparent. So the bare URL is the one you want for cutouts, and the underlay URL is the one that looks like the website.

The server answers with vary: Accept,User-Agent, so a cached JPEG for curl and a cached AVIF for Chrome live side by side. If you script this and save with a .png name because the URL ends in .png, you will write AVIF bytes into a .png file.

The server tells you the original size

Cloudinary adds a server-timing header with the output and the original:

$ curl -sI -H "Accept: image/avif" "https://static.nike.com/a/images/f_auto,u_9ddf…/b7d9211c-…/AIR+FORCE+1+%2707.png" | grep server-timing
server-timing: cld-akam;dur=5;start=…;desc=hit,rtt;dur=3,content-info;desc="width=2880,height=3600,bytes=117444,format=\"avif\",owidth=2880,oheight=3600,obytes=3569409,oformat=\"png\",…"
Enter fullscreen mode Exit fullscreen mode

owidth, oheight and obytes describe the upload. On adidas the same header shows up on the resized URL: h_840,f_auto,q_auto,fl_lossy,c_fill,g_auto/…/Samba_OG_Shoes_White_IG1024_01_standard.jpg returns an 840×840 AVIF (13,028 bytes) and reports owidth=2400,oheight=2400,obytes=819017. Strip the whole step and the bare URL returns that 2400×2400 JPEG, 819,017 bytes. A HEAD request is enough to learn whether an edit is worth making.

Don't ask for more than the original

Cloudinary will upscale if you ask. Replacing the preset with w_4000 returned a 4000×5000 AVIF, bigger than anything Nike uploaded. Adding c_limit (w_4000,c_limit) capped it at 2880×3600. When you strip size steps instead of rewriting them, this can't happen, which is why I strip.

The rule in code

PixLasso, the Chrome extension I made for saving every image on a page, does the "preset removed" edit for both brands. It drops leading segments while each one is only size, crop, quality or format parameters, and stops at the first segment that does anything else, such as the u_ underlay or an adidas l_ overlay:

const [, head, rest] = /^(\/(?:a\/)?images\/)(.*)$/.exec(u.pathname);
const parts = rest.split('/');
const STEP = /^(?:t_[a-z0-9_]+|(?:(?:w|h|c|q|f|dpr|ar|g)_[^,/]*|fl_(?:progressive|lossy)(?::[^,/]*)?)(?:,(?:(?:w|h|c|q|f|dpr|ar|g)_[^,/]*|fl_(?:progressive|lossy)(?::[^,/]*)?))*)$/i;
while (parts.length > 2 && STEP.test(parts[0])) parts.shift();
u.pathname = head + parts.join('/');
Enter fullscreen mode Exit fullscreen mode

parts.length > 2 keeps the photo ID and file name even if a malformed URL has nothing else. Run on the two URLs above it gives:

https://static.nike.com/a/images/f_auto,u_9ddf04c7-…,fl_layer_apply/b7d9211c-…/AIR+FORCE+1+%2707.png
https://assets.adidas.com/images/a34f007a106043afb2f3afab00e997ee_9366/Samba_OG_Shoes_White_IG1024_01_standard.jpg
Enter fullscreen mode Exit fullscreen mode

On Nike, f_auto,u_… survives as one segment because the u_ parameter fails the test, so the result keeps the grey background and stays small. That was deliberate: people saving product photos mostly want them to look like the site.

If you only need a few photos, the edit works by hand in the address bar. I wrote the steps up in how to download Nike product images in full size. Cloudinary URLs change when a brand renames its presets, so check the server-timing header again before relying on any number here.

Top comments (1)

Collapse
 
tomerbarm profile image
Tomer Bar-Meir (Tom) •

Useful breakdown of the delivery half. One thing that bit us on the source side of the same pipeline: phone photos that carry an EXIF orientation tag. A transform chain can look right in Chrome and still arrive sideways in another viewer or tool, because not every consumer applies the tag. Baking the rotation into the pixels once, at upload, before any presets or f_auto run, removes a whole class of surprises. Did you see any product shots on nike.com where the underlay or crop hid an orientation problem like that? Disclosure: I'm the founder of BlueVeta.com, we generate product images from a single photo, so I run into this a lot.

⌂ 换网址