Cloudinary turns one upload into every crop, format and size you will ever serve, addressed by URL. The kit stores media in your own R2, records it, and enriches it on your own Workers AI binding. On transformation breadth this is not close; on where the originals live, it is not close the other way.
Choose Cloudinary
When the image pipeline is the product's surface.
Transformations composed in a URL, format negotiation, art-directed crops, video packaging and a global CDN in front of all of it. If your app is visual and your team is small, that is an enormous amount of work you are not doing.
Choose Pithy
When the bytes should stay in your own bucket.
The client uploads straight to your R2 — never through your Worker — and the record, the owner, the quota and the enrichment live beside the rest of your data. There is no third party holding your users' uploads and no egress bill for serving them.
On this capability alone
| Feature | Cloudinary | Pithy |
|---|---|---|
Media | ||
| URL-based transformations Cloudinary: crop, format, quality, effects, composed in the path Pithy: not offered; Cloudflare Images is the adjacent product if you want this | Yes | No |
| Direct-to-bucket upload Pithy: a presigned PUT; bytes never proxy through your Worker | Yes | Yes |
| Originals stay in your account Cloudinary: stored on their infrastructure Pithy: your R2, your credentials, your lifecycle rules | No | Yes |
| Per-object owner and quota Cloudinary: folders and tags Pithy: an owner and a quota enforced in your own tables | Partial | Yes |
| Authorized downloads Cloudinary: signed URLs Pithy: a read that streams through your Worker, so it can be authorized per request | Yes | Yes |
| AI enrichment of uploads Cloudinary: tagging, moderation, captioning Pithy: your Workers AI binding, in a Workflow you can read | Yes | Yes |
| Video packaging and streaming Cloudinary: adaptive bitrate, players, the lot Pithy: Cloudflare Stream is the adjacent product; the kit records and stores | Yes | Partial |
| No charges for egress Pithy: R2 does not charge egress, which is most of the argument | No | Yes |
The saffron tick marks where Pithy leads — not that the other column is absent. Every claim about Cloudinary was checked against their own documentation on 2026-08-25; both products change, and this page is a snapshot rather than a maintained contract.
Where Cloudinary wins
One URL becomes every variant you need, cached at the edge. Reimplementing a fraction of that on your own is weeks, and the fraction will be the wrong one.
Transcoding ladders, packaging, players and captions. The kit stores a video and enriches it; it does not stream it.
An upload widget with cropping, progress and retry, on every platform, is a component nobody enjoys writing twice.
Format negotiation and quality heuristics tuned across an enormous corpus. Hand-rolled settings are usually worse and always slower to arrive at.
If you need a transformation pipeline, use one — Cloudinary or Cloudflare Images, both good. What the kit is for is the part underneath: an upload that lands in your bucket, a row that says who owns it and what it counts against, and a download your Worker can refuse. Egress not being billed is the quiet reason that arithmetic changes at scale.