All guides

Target size guide

Compress an image to 100 KB (or any size limit) without guessing

Set a byte budget and let a binary search on quality find the best image that fits, with an honest answer when the target is impossible.

Plenty of systems reject images above a byte limit: form validators, CMS upload fields, email gateways, app store listings, government portals. The usual workflow is to drag a quality slider, export, check the file size, and repeat until the number fits. That loop wastes time and usually ends one of two ways - a file just under the limit at needlessly low quality, or five attempts that never quite land.

A target-size mode replaces the loop. You state the byte budget, the encoder finds the highest quality that fits, and you get a clear answer when the budget is impossible.

Why quality sliders are the wrong tool

Quality settings do not map to file sizes. The same "quality 80" produces a 40 KB file for a flat illustration and a 400 KB file for a detailed photograph, because compressibility depends on the image content. So a slider can never answer the question you are actually asking, which is "give me the best image that fits in 100 KB."

The mechanical fix is a search: encode at some quality, measure the output, adjust, repeat. Doing that by hand is tedious. Doing it in code is a solved problem.

How target size works on Tinify.dev

When you set a target size, the encoder runs a binary search on the quality setting - up to seven encode passes - and keeps the highest quality result that fits inside your byte budget. A few rules keep the feature honest:

  • The floor is 10 KB. Targets below 10 KB are rejected up front rather than producing unusable output.
  • The target must be smaller than the input. Asking a 80 KB file to become 100 KB is not compression; the request is rejected with a clear error instead of returning the original and calling it a success.
  • It works for AVIF, WebP, JPEG, and PNG. Other formats are declined with target_size_unsupported_format.
  • It cannot be combined with lossless mode. Lossless output size is determined by the pixels, not by a quality setting, so there is nothing to search. Combining the two returns target_size_conflict.
  • When the budget is impossible, the result says so. You get the smallest file the search reached plus target_size_achieved: false - not a silent failure, and not a fake success.

Using the web tool

The compressor has a target size field next to the quality mode selector. Enter a value in kilobytes, drop up to 50 files (40 MB each), and download the results. No account is needed, and files are deleted after two hours.

If the image genuinely cannot reach your target - say a 24-megapixel photograph and a 15 KB budget - consider resizing first. Dimensions dominate file size; a 1200px-wide copy of a 6000px original reaches small byte budgets easily, while the original never will.

Using the API

The compress endpoint takes a target_size_bytes parameter:

curl -X POST https://api.tinify.dev/api/v1/images/compress \
  -H "Authorization: Bearer $TINIFY_API_KEY" \
  -F "file=@photo.jpg" \
  -F "target_size_bytes=102400"

The response reports what actually happened:

{
  "data": {
    "status": "succeeded",
    "optimized": true,
    "original_bytes": 483211,
    "result_bytes": 98304,
    "target_size_achieved": true,
    "download_url": "/api/download/...",
    "expires_at": "2026-07-24T12:00:00Z"
  },
  "request_id": "1b6139e2-..."
}

Check target_size_achieved in code before treating the file as done. When it is false, the returned file is still the smallest the search produced - often close to the target - but your pipeline should decide whether "close" is acceptable or whether to resize and retry.

With the @tinify-dev/client SDK the same call is:

const result = await client.compress("./photo.jpg", {
  target_size_bytes: 100 * 1024,
});
if (result.data.target_size_achieved === false) {
  // resize first, then retry - or accept the best-effort file
}

API keys are free at tinify.dev/developers with 500 operations per month included; paid plans are $9/month for 2,000 operations and $29/month for 10,000 - details on the pricing page. Each target-size compression counts as one operation regardless of how many internal encode passes the search runs.

Picking a sensible budget

SituationApproach
Form or CMS upload limitTarget 5-10% under the stated limit to leave margin
Email attachmentsBudget per image so the total stays under the gateway cap
Avatar or thumbnail fieldsResize to the display dimensions first, then set a target
"Keep pages fast" in generalPrefer a quality mode; targets are for hard limits

Two of those rows deserve emphasis. First, leave margin: some validators count metadata or multipart overhead, so aiming exactly at the limit can still bounce. Second, if you do not have a hard limit, you do not need a target - the default balanced mode already aims for the point where extra bytes stop buying visible quality, and it never returns a larger file than the input (it reports optimized: false instead).

When the honest answer is no

Some images cannot reach some budgets at acceptable quality, and no encoder setting changes that. The productive order of operations is:

  1. Crop away pixels the final display will never show (crop).
  2. Resize to the actual display dimensions (resize).
  3. Consider a smaller format - a JPEG photograph converted to AVIF often fits budgets the JPEG cannot.
  4. Then apply the target size to the smaller image.

A target-size feature that occasionally says "not achievable" is more useful than one that always says yes and quietly ships mush. That is the trade we chose.