Transformation Serializer
The bidirectional translator between Cloudinary transformation URL strings and the structured transformation model — the JSON/TypeScript object form of the same transformation.
"c_scale,w_200/e_blur:500" ⇄ [{ actionType: 'scale', dimensions: { width: 200 } },
{ actionType: 'blur', strength: 500 }]Reach for it whenever a transformation has to be edited rather than merely rendered: a UI that lets someone drag a crop handle needs the model, and the delivery URL needs the string.
What this service exposes#
| Surface | Endpoint | Use it when |
|---|---|---|
| HTTP API | POST /api/v0/encode, POST /api/v0/decode |
You are on a server, or in a language other than JavaScript. |
| ESM bundle | GET /esm/latest/serializer.mjs |
You are in a browser and want zero round-trips per keystroke. |
| JSON Schema | GET /schema/v0/transformation.json |
You want to validate or generate types for a model. |
| Specification | GET /docs/latest/specification |
You want the language itself: its grammar, its canonical form, and what the encoder and decoder guarantee. |
Try it in 30 seconds#
Decode a string into a model:
curl -s https://production-transformation-serializer-us-east-1.cloudinary.com/api/v0/decode \
-H 'content-type: application/json' \
-d '{"transformationString":"c_scale,w_200/e_blur:500"}'{
"model": [
{ "actionType": "scale", "dimensions": { "width": 200 } },
{ "actionType": "blur", "strength": 500 }
]
}…and encode it back:
curl -s https://production-transformation-serializer-us-east-1.cloudinary.com/api/v0/encode \
-H 'content-type: application/json' \
-d '{"model":[{"actionType":"scale","dimensions":{"width":200}},{"actionType":"blur","strength":500}]}'{ "transformationString": "c_scale,w_200/e_blur:500" }Or do the same in the browser, with no network round-trip at all:
<script type="module">
import { encode, decode } from 'https://production-transformation-serializer-us-east-1.cloudinary.com/esm/latest/serializer.mjs';
decode('c_scale,w_200/e_blur:500');
</script>The playground runs exactly that bundle in your browser — nothing you type there is sent anywhere.
The console on this page already has it#
Every page of these docs loads the published bundle and puts encode and decode on window.
Open devtools, right here, and call them:
decode('c_scale,w_200/e_blur:500');
encode([{ actionType: 'scale', dimensions: { width: 200 } }]);It is the real bundle, pinned to the version this page documents — not a sandbox, and not a
reimplementation that could disagree with what ships. serializer is there too, if you prefer the
{ encode, decode } pair.
Two things that surprise people#
Encoding normalises. Qualifiers come out in alphabetic order within an action, so
{ width: 500, height: 300 } encodes to c_scale,h_300,w_500, not c_scale,w_500,h_300. A
decode → encode round-trip is therefore stable but not byte-identical to the input string.
Unknown syntax survives. Anything the decoder does not recognise becomes a custom action
rather than being dropped, so decoding and re-encoding an exotic transformation gives you back
what you started with. You do not have to wait for the model to learn a qualifier before you can
safely pass it through.
Versioning#
v0 in /api/v0 and /schema/v0 names the contract these pages describe. A change that would
break a caller — a renamed endpoint, a model that means something different — ships under v1
beside it, so a URL you integrate against today keeps working as long as v0 is served.
The browser bundle needs no contract version: /esm/v0.1.0/serializer.mjs carries its release
and is frozen for good. Nor do these pages: /docs/latest describes the release named in the
sidebar.
Going deeper#
The specification defines the transformation language itself: its grammar, the schema, expressions and conditions, the canonical form, and what the encoder and decoder guarantee.