# Universal Image Compressor

Compress any image format without knowing the specific endpoint. Accepts 37+ image formats including standard formats, RAW camera files, and Photoshop files.

## Quick reference

| | |
|---|---|
| **Job type** | `image.universal-compress` |
| **Category** | images |
| **Endpoint** | `POST /compress/image` |
| **Input formats** | `.jpg`, `.png`, `.webp`, `.avif`, `.heic`, `.heif`, `.tiff`, `.tif`, `.bmp`, `.gif`, `.psd`, `.cr2`, `.cr3`, `.crw`, `.nef`, `.nrw`, `.arw`, `.sr2`, `.srf`, `.raf`, `.dng`, `.rw2`, `.raw`, `.orf`, `.pef`, `.3fr`, `.fff`, `.iiq`, `.srw`, `.x3f`, `.gpr`, `.mrw`, `.dcr`, `.kdc`, `.erf`, `.mef`, `.mos` |
| **Output format** | same as input |
| **Costing** | 1 credit per 5 MB |
| **Max file size** | 1 GB |
| **Options** | resize |

## Example

<!-- code-tabs:start default=curl -->
### cURL
```bash
# compress any image format
JOB_ID=$(curl -sS -X POST "https://api.tools.fast/compress" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -F "file=@photo.heic" | jq -r '.id')

# poll until complete
while true; do
  STATUS=$(curl -sS "https://api.tools.fast/compress/job/${JOB_ID}" \
    -H "X-Fast-Api-Key: $API_KEY" | jq -r '.status')
  [ "${STATUS}" = "Succeeded" ] && break
  [ "${STATUS}" = "Failed" ] || [ "${STATUS}" = "Canceled" ] && exit 1
  sleep 1
done

# download
curl -sS "https://api.tools.fast/compress/job/${JOB_ID}/download" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -o "photo-compressed.jpg"
```

### C#
```csharp
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Fast-Api-Key", "fast_prod_your_key_here");

using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(File.ReadAllBytes("photo.heic")), "file", "photo.heic");

var submit = await http.PostAsync("https://api.tools.fast/compress", form);
var job = await submit.Content.ReadFromJsonAsync<JsonElement>();
var jobId = job.GetProperty("id").GetString();

string status;
do
{
    await Task.Delay(1000);
    var poll = await http.GetFromJsonAsync<JsonElement>(
        $"https://api.tools.fast/compress/job/{jobId}");
    status = poll.GetProperty("status").GetString()!;
} while (status is "Queued" or "Running");

var output = await http.GetByteArrayAsync(
    $"https://api.tools.fast/compress/job/{jobId}/download");
File.WriteAllBytes("photo-compressed.jpg", output);
```

### PowerShell
```powershell
$headers = @{ "X-Fast-Api-Key" = "fast_prod_your_key_here" }

# compress any image format
$job = Invoke-RestMethod -Method Post "https://api.tools.fast/compress" `
  -Headers $headers `
  -Form @{ file = Get-Item "photo.heic" }

# poll until complete
do {
  $status = (Invoke-RestMethod "https://api.tools.fast/compress/job/$($job.id)" `
    -Headers $headers).status
  if ($status -in "Failed", "Canceled") { throw "Job $($job.id) $status" }
  Start-Sleep -Seconds 1
} while ($status -ne "Succeeded")

# download
Invoke-RestMethod "https://api.tools.fast/compress/job/$($job.id)/download" `
  -Headers $headers -OutFile "photo-compressed.jpg"
```
<!-- code-tabs:end -->

## Accepted input formats

### Standard image formats

`.jpg`, `.jpeg`, `.png`, `.webp`, `.avif`, `.heic`, `.heif`, `.tiff`, `.tif`, `.bmp`, `.gif`

### Adobe Photoshop

`.psd`

### RAW camera formats

`.cr2`, `.cr3`, `.crw`, `.nef`, `.nrw`, `.arw`, `.sr2`, `.srf`, `.raf`, `.dng`, `.rw2`, `.raw`, `.orf`, `.pef`, `.3fr`, `.fff`, `.iiq`, `.srw`, `.x3f`, `.gpr`, `.mrw`, `.dcr`, `.kdc`, `.erf`, `.mef`, `.mos`

## Format behavior

The universal compressor detects each image's characteristics and selects the output format automatically. Native formats are re-compressed in the same format; other formats are converted to JPG or PNG based on transparency.

| Input | Output | Behavior |
|-------|--------|----------|
| `.jpg` / `.jpeg` | `.jpg` | Native -- same format |
| `.png` (transparent) | `.png` | Native -- same format |
| `.png` (opaque) | `.jpg` | Converted -- no alpha channel detected |
| `.webp`, `.avif`, `.heic`, `.heif`, `.tiff`, `.bmp`, `.gif`, `.psd` | `.jpg` or `.png` | Converted -- based on transparency |
| All RAW formats (`.cr2`, `.nef`, `.arw`, etc.) | `.jpg` | Always converted -- RAW is always opaque |

Transparency is detected using libvips `hasalpha`. Images with an alpha channel produce `.png` output; opaque images produce `.jpg`.

## Options

The Universal compressor supports **resize** -- scale down images while compressing. See [Options](options.md#resize) for the full resize reference.

<!-- code-tabs:start default=curl -->
### cURL
```bash
# compress + resize to 1080p
curl -sS -X POST "https://api.tools.fast/compress" \
  -H "X-Fast-Api-Key: $API_KEY" \
  -F "file=@photo.heic" \
  -F 'options={"_schemaVersion":1,"resize":{"enabled":true,"preset":"1080p","mode":"pixels","value":null}}'
```

### C#
```csharp
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(File.ReadAllBytes("photo.heic")), "file", "photo.heic");
form.Add(new StringContent(
    """{"_schemaVersion":1,"resize":{"enabled":true,"preset":"1080p","mode":"pixels","value":null}}"""),
    "options");

var response = await http.PostAsync("https://api.tools.fast/compress", form);
```

### PowerShell
```powershell
Invoke-RestMethod -Method Post "https://api.tools.fast/compress" `
  -Headers @{ "X-Fast-Api-Key" = $Key } `
  -Form @{
    file    = Get-Item "photo.heic"
    options = '{"_schemaVersion":1,"resize":{"enabled":true,"preset":"1080p","mode":"pixels","value":null}}'
  }
```
<!-- code-tabs:end -->

## Notes

- Use this endpoint when you want a single integration point for all image formats, rather than routing to format-specific endpoints.
- For format-specific control (where input format = output format), use the dedicated [JPG](jpg.md), [PNG](png.md), or [GIF](gif.md) compressors instead.

## Related

- [JPG](jpg.md)
- [PNG](png.md)
- [GIF](gif.md)
