The short answer
You can leave Cloudinary without touching a single image URL in your code. A Cloudinary URL has three parts: the host, your cloud name, and a transformation string such as w_400,c_fill,f_auto. If the new server reads the same path and the same transformation string, the only change is the host name. Two products do this today: ImageKit, through its Cloudinary URL Rewriter, and Flatpix, which reads Cloudinary URLs natively and is free to run yourself.
- Export your originals to a bucket you own (S3, R2 or Google Cloud Storage).
- Point a Cloudinary-compatible server at that bucket.
- Compare its output with Cloudinary's on your own URLs.
- Move your custom domain, or replace
res.cloudinary.comwith your new host in one place. - Run both for a few weeks, then cancel.
Why the URLs are the hard part
Cloudinary puts the work into the URL. A product photo on a store might be https://res.cloudinary.com/acme/image/upload/c_fill,w_600,h_600,g_auto,f_auto,q_auto/v1712/products/shoe.jpg. That one string asks for a square crop, a size, a crop position, the best format for the browser and an automatic quality. Those strings are spread through templates, React components, mobile apps, marketing emails, product feeds and other people's websites that link to your images. Search engines have them indexed. Emails already sent cannot be edited.
Most alternatives use their own syntax. imgix writes ?w=600&h=600&fit=crop, Cloudflare writes /cdn-cgi/image/width=600/. Moving to one of them means finding and rewriting every URL, and accepting that the old ones in emails and feeds break. That rewrite, not the new price, is what keeps teams on a bill they would rather not pay.
Two ways to keep the URLs
| Option | How it keeps the URL | Where the originals live | How it charges |
|---|---|---|---|
| ImageKit with the Cloudinary URL Rewriter | Translates Cloudinary transformation strings into its own. You set up a custom domain and keep the path. | ImageKit storage, or your bucket connected as external storage. ImageKit can also read a Cloudinary backup bucket. | Usage: bandwidth and storage tiers. |
| Flatpix (ours) | Reads the Cloudinary URL grammar directly: /{cloud}/image/upload/{transformations}/{public_id}. Same path, new host. | A folder or any S3-compatible bucket you own: S3, R2, MinIO, Google Cloud Storage. | Free and open source (AGPL) to run yourself, or a flat $39, $99 or $249 a month hosted. |
Sources: ImageKit: Migrate from Cloudinary and Flatpix on GitHub, 31 October 2026.
A third way is to write your own translation layer: a small edge function that reads the Cloudinary string and calls another service in its syntax. It works, but you now own a parser for a large URL language, and every parameter you miss is a broken image.
The move, step by step
1. List what you use
Search your code and templates for res.cloudinary.com and for your own Cloudinary domain if you have one. Collect the distinct transformation strings. Most sites use fewer than twenty. The cost calculator scans one public page and lists the cloud names and transformations it finds. Note anything unusual: overlays (l_), named transformations (t_), rounded corners (r_), video, and signed URLs.
2. Export the originals
You need every original file, stored under its public ID. There are two routes:
- Backup to your own bucket. Cloudinary can back up assets to your own Amazon S3, Google Cloud Storage or Azure container. Using your own storage for backup is available on paid plans only, and you can run a one-time backup for assets uploaded before you turned it on.
- The Admin API. List your assets page by page and download each one from its URL. Each asset comes back with its public ID, and long lists come back in pages with a
next_cursor. The Admin API is rate limited: 500 requests an hour on the free plan, 2,000 and up on paid plans. Plan a large export over a few hours.
Save each file at a path equal to its public ID. A public ID of products/shoe becomes products/shoe.jpg in the bucket. Flatpix looks for the file as named, then the bare ID, then common extensions such as .jpg, .png and .webp, so you do not need to know the original format in the URL.
3. Point the new server at the bucket
With Flatpix, the cloud name in the URL picks the origin. If your Cloudinary cloud is acme and your originals are in an R2 bucket called acme-media:
docker run -p 8080:8080 \
-e FLATPIX_CLOUDS=acme=s3://acme-media/originals \
-e FLATPIX_S3_ENDPOINT=https://ACCOUNT.r2.cloudflarestorage.com \
-e FLATPIX_S3_REGION=auto \
-e FLATPIX_S3_ACCESS_KEY=... -e FLATPIX_S3_SECRET_KEY=... \
-e FLATPIX_CACHE=s3://acme-media/derived \
ghcr.io/taktekhq/flatpix
Now http://localhost:8080/acme/image/upload/c_fill,w_600,h_600/products/shoe.jpg serves the same picture as the Cloudinary URL with the same path. Each rendered image is stored in the derived cache and served from there after the first request. Versioned URLs (v1712) are cached for a year.
4. Test with your own URLs
Take the list from step 1 and request every URL from both hosts. Compare sizes first, then look at the pictures side by side. Flatpix answers an unsupported parameter with a 400 error that names it, so a missing feature shows up at once instead of as a quietly wrong image. If you would rather serve something than fail, set FLATPIX_LENIENT=1: unsupported parameters are ignored and listed in an X-Flatpix-Ignored response header, which you can log.
5. Change one host name
If you use a custom domain with Cloudinary, such as images.acme.com, point it at the new server and nothing in your code changes. If your URLs say res.cloudinary.com/acme, change that one prefix in your config or image helper. Most codebases build image URLs in one function. ImageKit's guide recommends the same pattern: set up the new domain alongside the old one, test, then switch.
6. Run both, then cancel
Keep Cloudinary on for a few weeks. Old emails, feeds and other sites still point at res.cloudinary.com, so watch its traffic fall before you cancel. The new server starts with a cold cache, so its first days do more rendering than a normal month.
What carries over
These are the parameters the open-source Flatpix server reads today, from its README. ImageKit publishes its own list in its migration guide.
| Cloudinary parameter | What it does | Flatpix today |
|---|---|---|
w_, h_, dpr_, ar_ | Size, pixel density, aspect ratio | Yes, including decimals such as w_0.5 |
c_ | Crop mode | Yes: scale, fit, limit, mfit, fill, lfill, pad, lpad, crop, thumb |
g_ | Crop position | Compass points, auto and auto:entropy. No face or object gravity |
f_auto, f_webp, f_avif | Output format | Yes. f_auto picks AVIF, then WebP, from the browser's Accept header |
q_auto, q_80 | Quality | Yes, with the auto tiers best, good, eco and low |
b_, e_grayscale, a_ | Background, black and white, rotation | Yes |
| Chained transformations | c_fill,w_800/c_scale,w_400 | Yes, in order |
/image/fetch/ | Transform a remote URL | Yes, for hosts on an allow list you set |
l_, u_, r_, t_, fl_, w_auto | Overlays, rounded corners, named transformations, flags, automatic width | Not in the open-source server yet. Check these in step 1 |
| Signed URLs, video | Signature checks, video delivery | Signatures are read and ignored. No video |
Source: Flatpix README: supported parameters, 31 October 2026. Cloudinary's full list is in its Transformation URL API reference.
How close the pictures are
Flatpix ships a test tool that fetches an original and Cloudinary's rendering from Cloudinary's public demo cloud, renders the same URL itself, and scores the pixels: 1.0 is identical, and a plain re-encode of the same picture scores about 0.995. Across 31 transformations of Cloudinary's sample.jpg, run on 29 October 2026:
- All 31 output sizes matched Cloudinary's exactly.
- The median score was 0.9900, and 20 of the 31 scored at or above the 0.988 target.
- The lowest was
g_autoat 0.70: Cloudinary picks the crop with its own model, Flatpix asks libvips where the interesting part is, and they choose different windows.
Most scores under the target are compression noise: both servers encode JPEG and WebP with their own settings. The practical rule is that sizes and crops match, and automatic crops are the thing to look at by eye.
What it costs
Running Flatpix yourself costs a server and your time. The software is AGPL-licensed and ships as one Docker image. On a 12-thread machine it rendered a 4000 by 3000 JPEG to an 800 by 600 WebP in about 0.27 CPU-seconds, and served cached images at over 6,000 requests a second. Hosted Flatpix is a flat monthly price: Starter $39 (25,000 originals, 500 GB delivered), Growth $99 (250,000 originals, 2 TB) and Scale $249 (unlimited originals, 10 TB), with no credits and no overage bills. Your originals stay in your own bucket, which you pay for separately. On Cloudflare R2, storage is $0.015 per GB-month and there is no egress fee.
The cost of moving is mostly the export and the testing. For a store with tens of thousands of images, plan a day for the export and a day for testing the transformation list.
Keep your Cloudinary URLs
Point your existing URLs at Flatpix and change one domain. A flat $39, $99 or $249 a month, or free to run yourself. Your first month is free.
Questions
Can I leave Cloudinary without changing my image URLs?
Yes, if the new server reads Cloudinary's URL format. ImageKit does it through its Cloudinary URL Rewriter, and Flatpix reads Cloudinary URLs directly. You keep the path and the transformation string and change only the host, or point your Cloudinary custom domain at the new server.
How do I export my images from Cloudinary?
Two ways. On a paid plan, turn on backup to your own S3, Google Cloud Storage or Azure container and run a one-time backup. On any plan, list your assets with the Admin API and download each one, saving it under its public ID. The Admin API allows 500 requests an hour on the free plan and 2,000 and up on paid plans.
Which Cloudinary transformations does Flatpix support?
Sizes, crop modes, crop position including g_auto, aspect ratio, pixel density, f_auto, q_auto, background, grayscale, rotation, chained transformations and fetch. Overlays, rounded corners, named transformations, automatic width and video are not in the open-source server yet.
Will the images look the same after I move?
Sizes and crops match. In a test of 31 transformations against Cloudinary's demo cloud, all 31 sizes matched exactly and the median pixel score was 0.990 out of 1.0. Automatic crops differ, because each service picks the interesting part of the picture its own way.
How long does a Cloudinary migration take?
For most sites, a few days of work: one to export the originals, one to test the transformation list on both hosts, and a DNS change. Then a few weeks of running both while old links in emails and feeds fade out.
Sources
All pages were read on 31 October 2026. Products and prices change, so confirm them at the source.
- Cloudinary: Backups and version management. Backup to your own S3, Google Cloud Storage or Azure storage on paid plans, and the one-time backup.
- Cloudinary: Admin API. Listing assets, pagination with next_cursor, and the hourly rate limits.
- Cloudinary: Transformation URL API reference. Every Cloudinary transformation parameter.
- ImageKit: Migrate from Cloudinary. The Cloudinary URL Rewriter and the parallel domain advice.
- ImageKit: Cloudinary backup bucket. Reading a Cloudinary backup bucket as an ImageKit origin.
- Flatpix on GitHub. The URL grammar, supported parameters, the Cloudinary comparison and the benchmark.
- Cloudflare R2: Pricing. Storage price and free egress.