Guides

API compression settings

The levels, formats, resize options and metadata switch the Iminify API takes, what each one does to an image, and requests for common jobs.

Four settings decide what happens to an image: the level, the format, the size (width, height or scale) and keep_metadata. An upload, a recompress and a page scan all take the same fields, and all of them are optional: leave everything out and you get Smart compression in the image's own format, at its own size, with its metadata stripped. An upload and a recompress also take a size_limit, for a file that has to fit under a number of kilobytes.

They're the same choices as the settings panel on the website, and they run through the same encoders, so an image compressed here comes out exactly as it would there.

Levels

level What it does
smart The default. Finds the lowest quality that still looks like your upload, measured on the image, not guessed.
ultra The same search with lower targets. Files get smaller and fine texture softens a little.
lossless Changes no pixel, unless a size limit needs it to. The file shrinks only as far as a better encoding of the same pixels allows.
none Compresses nothing. Only the format, the resize, the metadata choice and a size limit are applied.

Smart and Ultra don't take a quality number from you, because the same number means something different in every encoder. For JPG, WebP and AVIF output they encode the image at several qualities and keep the smallest that still clears the level's target, measured against your upload: 40 dB PSNR for Smart and 34 dB for Ultra, then 70 and 50 on the SSIMULACRA 2 scale. For what those scores look like and what each costs in kilobytes, see SSIMULACRA 2 scores in practice. These are targets, not guarantees. An image that can't reach the target even at the level's quality ceiling is encoded at the ceiling, so a busy, detailed photo can come out a little under it, more often as JPG than as AVIF. The search runs on images up to 36 megapixels (the perceptual check up to 8); larger ones are encoded at the level's fixed quality ceiling. A PNG is reduced to a smaller palette and a GIF compressed at a fixed setting for the level, neither against a target.

Lossless repacks a JPEG, PNG or GIF without changing a pixel, except that a PNG tagged with a wide-gamut colour profile is converted to sRGB. A lossy WebP has no repack step, so Lossless re-encodes it at a very high quality.

When nothing comes out smaller than the upload and you asked for no other change, the upload itself is the answer. If it carries metadata and keep_metadata is off, the metadata is taken out without touching a pixel and the image ends as completed. Otherwise it ends as already-optimized, with the upload handed back exactly as it came as the optimized copy. none works the same way. You never get a bigger file from compression alone.

Formats

Iminify reads PNG, JPG, JPEG, WEBP, GIF, HEIC, HEIF, TIFF, TIF. It writes WebP, AVIF, PNG and JPG.

format What you get
left out The upload's own format. A HEIC or TIFF can't stay one, because Iminify doesn't write either, so it's treated as auto.
webp WebP. Every current browser shows it. An animated GIF stays animated.
avif AVIF. Usually the smallest for photographs, and the slowest to encode.
png PNG. Keeps transparency; Smart and Ultra reduce it to a palette.
jpg JPG, encoded with jpegli. jpeg is read as jpg.
auto Up to 8 megapixels, the image is encoded in every format that can hold it without losing transparency or animation, and the smallest file wins. Above that it goes straight to webp. With a size_limit, a still image is encoded only as JPG, WebP and AVIF.

Converting an animated GIF to PNG, JPG or AVIF keeps only its first frame; WebP keeps every frame. The converted format is optimized.format on the finished image.

Not sure between the two modern formats? AVIF against WebP on ten images at one quality score has the numbers, and the cases where WebP still wins; auto makes that call per image.

Resizing

Fields Result
width That width; the height follows the aspect ratio.
height That height; the width follows.
width and height Exactly that size. If the proportions differ from the image's, it's stretched to fit.
scale That percentage of each side, from 1 to 100. It can't be combined with width or height.

Sides go up to 65535 pixels, and the resized image can't be larger than 64 megapixels. The sizes are measured the way the image displays, so a phone photo stored on its side is resized as you see it, upright.

An animated GIF is resized frame by frame. An animated WebP or PNG can't be resized: the request is refused with animation_not_resizable, because only its first frame would come back. Without a resize or a format change, it comes back with every frame, its metadata removed unless keep_metadata is on.

Sending the width a page actually shows usually saves more than any level; How many KB should a website image be? measures it at four widths.

Size limit

size_limit is the most the optimized copy may weigh, in kilobytes of 1,000 bytes: size_limit=100 for a form or a page that takes files under 100 KB. The smallest is 5 KB. Counting a kilobyte as 1,000 bytes keeps a file that fits under the limit whichever way the form counts it.

The level runs first, and when its file is under the limit, that's the answer. When it isn't, Iminify encodes the image again at the best quality that still fits, and when even the lowest quality is over, it makes the image smaller in pixels, a step at a time, until the file fits.

  • Formats: only JPG, WebP and AVIF have a quality to lower. A PNG or GIF kept in its own format that is over the limit comes back as whichever of the three is smallest (WebP or AVIF under lossless and none), the way a HEIC does, so check optimized.format. Asking for format=png with a limit is refused.
  • Levels: the limit comes first. Under lossless, a file over the limit is encoded again with loss until it fits, and none fits it too.
  • Animations are never fitted, and keep their frames and their format unless you ask for another.
  • Page scans take no limit: the page report weighs every format at the level.
  • Recompressing applies only the limit you send with it, as it does a resize, so leave it out and the new image has none.

The finished image says how it came out in size_limit_status: under, resized when it was made smaller in pixels to fit (so optimized.width and optimized.height are smaller than you asked for), or over when it couldn't get there. A smaller width, keep_metadata off or a higher limit is the way under.

Metadata

By default the optimized copy has its EXIF metadata stripped: camera model, date, GPS location. Send keep_metadata=true to carry it across, into WebP and AVIF too. Either way the orientation is applied to the pixels first, so a stripped photo never comes back sideways, and a Display P3 or CMYK colour profile is converted to sRGB rather than dropped, so the colours stay put. The original you uploaded keeps its metadata in storage whatever you choose.

Content Credentials

Some images carry Content Credentials: a C2PA record of where the image came from, signed by the app or camera that made it. Every image from Google's Gemini has one that says Google's generative AI created it. The signature covers the file's exact bytes, so any change breaks it, and the optimized copy doesn't carry the record, whatever keep_metadata says. Iminify doesn't sign a new one of its own. The exception is an upload handed back unchanged, which keeps its record: with keep_metadata on, that's when nothing came out smaller, or when the level is none and nothing else was asked for. The upload itself stays in storage with its record either way, at original.download_url.

A finished image says what became of them in content_credentials: status is removed or kept, and generative_ai says whether the record names generative AI as the source. Iminify reads what the record states and doesn't check its signature. The field is null when the upload carried none. If someone needs to check where an image came from (a platform, a client, a newsroom), send them the original.

Common jobs

Job Fields
Web-ready photos format=webp, width=1600
The smallest file whatever the format level=ultra, format=auto
Smaller PNGs without touching a pixel level=lossless
iPhone photos to JPG, keeping the location format=jpg, keep_metadata=true
Thumbnails at a quarter size, no extra compression level=none, scale=25
A photo for a form that takes files under 100 KB format=jpg, size_limit=100
A photo at several widths for an <img srcset> (paid plans, see Responsive sizes) format=webp, responsive_widths=480, 768, 1200, 1600

In a multipart upload each field is a form field (-F "format=webp" with curl); everywhere else it's a key in the JSON body. A multipart form sends true and false as text, which is fine: keep_metadata takes true, false, 1, 0, yes and no.

Further reading

The measurements behind these settings, from the Iminify blog: