Concepts
Kept original
When the API returns your file unchanged because nothing smaller could be made, and what that costs.
What it means
Some files are already as small as they will get. A JPEG that was saved at low quality, or a PDF that holds only text, can come out of an encoder larger than it went in. When a compress request cannot make the file smaller, and you did not ask for a different format or size, you get your input back. The result says kept_original: true, and the request is free.
This applies to compress only. Convert and strip metadata always return the file they produced.
The retry that comes first
Before it gives up, the API makes one more attempt at a stronger setting. The second result is used only if it is smaller than the input.
| Kind | Second attempt |
|---|---|
| JPEG | Quality lowered by 20, but not below 20. |
| AVIF | Quality lowered by 25, but not below 20. |
| WebP | Lossy at quality lowered by 25, but not below 20. This holds even when you asked for 96 or above. |
| PNG | A narrower palette range, then the strongest lossless optimisation. |
| HEIC, GIF | No second attempt. |
| A lossless rewrite of the file structure, with no change to the images. | |
| Video | CRF raised by 4 (to at most 35 for H.264, 40 for H.265 and VP9) and a lower audio bitrate. |
| Audio | No second attempt. |
For video, a CRF you set yourself with video.crf is also used on the second attempt. Only the audio bitrate drops.
When the input is returned
| Kind | The input is returned when |
|---|---|
| Image | The result is still larger than the input, the output format is the same as the input format, and the resize step did not change the dimensions. |
| Neither the compressed file nor the rewritten file is smaller than the input. | |
| Video | The result is still larger than the input. This holds even if you asked for a different container or codec. |
| Audio | The result is not smaller than the input, and the output file type is the same as the input file type. |
For images and audio, the input is only returned when you did not ask for a change. If you asked for a different format, or the image was resized, you get the file you asked for even when it is larger. See the increased flag.
A format that original maps to another format counts as a change. A BMP compressed with image.format=original becomes a PNG, so it is returned as a PNG whatever its size.
What comes back
The response is a normal success: status 200 on a direct request, status succeeded on a job.
HTTP/1.1 200 OK
Content-Type: application/pdf
Smol-Original-Size: 48211
Smol-Output-Size: 48211
Smol-Savings-Percent: 0.0
Smol-Output-Format: pdf
Smol-Kept-Original: true
Smol-Billed: false- A PDF, a video or an audio file is returned byte for byte.
output_sizeequalsoriginal_size. - An image is returned with its pixels untouched. If
image.strip_metadatais on, which is the default, its metadata is still removed without re-encoding. The orientation tag and the colour profile are kept so that the image displays as before. The output can then be slightly smaller than the input. PNG files are returned byte for byte, with their metadata still in them. output_formatis the input's own format. A video you asked to have written as MP4 comes back as the MOV you sent, withvideo_codec: null.
The increased flag
increased: true means the file you got is larger than the file you sent, and it is not your original. savings_percent is negative. It happens when you asked for a change that the API carried out:
- A compress request with a different output format, for example a small JPEG written as PNG.
- A compress request where the resize step changed the image's dimensions.
- An audio compress request to a different file type, for example MP3 to FLAC.
- Any convert request. A conversion is judged by its format, not its size.
- A strip metadata request, when rewriting the file adds more bytes than the metadata took.
kept_original and increased are never both true.
Billing
| Result | Billed |
|---|---|
kept_original: true | No |
increased: true | Yes. The change you asked for was made. |
| Smaller output | Yes |
The Smol-Billed header on a direct request and the billed field on a job state the outcome for each request. See Billing.
Handling it in code
You can save the response body in every case. It is always a valid file. Branch on the flag only if you want to skip a write or record the outcome.
import { readFile, writeFile } from "node:fs/promises";
const response = await fetch("https://api.smolmac.com/v1/compress", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SMOL_API_KEY}` },
body: await readFile("photo.jpg"),
});
if (!response.ok) throw new Error((await response.json()).error.message);
if (response.headers.get("smol-kept-original") === "true") {
// Nothing smaller could be made. Keep using the file you already have.
} else {
await writeFile("photo.min.jpg", Buffer.from(await response.arrayBuffer()));
}