Skip to main content
Put comma-separated parameters between /t/ and the file path. The first request renders and caches the result, the rest are served from cache.
Drop the parameters to get the stored original back untouched: GET /t/photos/portrait.jpg. Auth: public, rate limited. For URLs that cannot be guessed or edited, use signed URLs, which are self-hosted only. On Cloud the same path sits behind a bucket prefix, /b/{bucketId}/t/.... See your base URL. Everything after it is identical.

Recipes

Image parameters

g_face uses saliency detection, not face detection. It keeps whatever region scores as most interesting, which on a portrait is normally the face. Corner radius is clamped to half the shorter side. Cut corners are transparent, so pair r with f_png, f_webp or f_avif, or add b to fill them and stay on JPEG.

Quality

Leave q unset and each format gets the quality it deserves: 80 for AVIF, 85 for WebP, 90 for JPEG, 100 for PNG. Large files shift a few points, clamped to 70-95. An explicit 1 to 100 is used as given.

Formats

Omit f and Openinary picks the best format the browser accepts, in order AVIF, WebP, then JPEG or PNG. f_auto goes further: it encodes every supported candidate, compares byte counts and serves the smallest, at the cost of a slower first request. Input: JPEG, PNG, WebP, AVIF, GIF (first frame), HEIC/HEIF (converted to JPEG at upload), PSD (layers composited) Output: AVIF, WebP, JPEG, PNG, GIF

Video parameters

A bare /t/clip.mp4 streams the original untouched. Add q_auto to opt into the default encode without choosing a CRF. The default q_60 favors encoding speed over file size, which is what makes large sources viable. Raise it when output quality matters more than job time. Videos also apply fixed limits: 720p maximum when you request no explicit w or h, a 200 MB cap on the source, and a 5 minute encode timeout. See video processing. Input: MP4 (H.264/H.265), MOV, WebM (VP8/VP9) · Output: MP4, WebM, MOV
A video transformation that is not cached yet answers 202 with a statusUrl, not the original. Poll that URL until it reports completed, then request the transform again. Keep its transformation segment: jobs are keyed on the path and its parameters. For assets you know you will serve, prewarm at upload so the first visitor never sees the 202.

Pass-through formats

Audio and 3D files are stored and delivered, never transformed. Request them with no transformation segment and the stored bytes come back untouched, as in GET /t/audio/podcast.mp3 or GET /t/models/duck.glb. Adding parameters to one returns 400 rather than the original, so a “resized” variant that is really the untouched file never gets cached.

Response

Returns the binary content, with Cache-Control set for browser caching and X-Content-Type-Options: nosniff. The content type comes from the extension via the shared media table, never from sniffing the body, which is why uploads are validated by content in the first place.

Gotchas

Only the short parameter keys work. The parser splits a segment at its first underscore, so thumbnail_time_5 reads as the key thumbnail, fails, and the segment is then treated as a folder name, ending in a 404. Video URLs accept the image-only parameters a, ar, r and b and silently ignore them. The URL still works, the output is just re-encoded without them. For compatibility with Cloudinary-shaped URLs, c also accepts lfill, fill_pad, limit, mfit, thumb and lpad, and g also accepts c, n, s, e, w, faces, face_center, faces_center, north_center and south_center.

Authenticated Transform

Signed URLs that cannot be guessed or edited.

Upload Files

Upload media and pre-generate variants.

Video Status

Poll a queued video transformation.

Automatic Format Selection

How the default format and quality are chosen.