---
seo_title: API de Compresión de Imágenes — Comprime PNG, JPEG y WebP | EnConvert
meta_desc: Comprime imágenes PNG, JPEG y WebP con POST /v1/convert/compress-image. Optimización sin pérdida primero y tamaño de archivo objetivo opcional con reducción de escala proporcional.
keywords: api de compresion de imagenes, comprimir png api, comprimir jpeg api, comprimir webp api, compresion de imagenes sin perdida api, reducir tamaño de imagen api, optimizador de imagenes rest api, comprimir imagen por programación
---

# API de Compresión de Imágenes

Comprime imágenes PNG, JPEG y WebP con el endpoint `POST /v1/convert/compress-image` — el formato nunca cambia (entra PNG, sale PNG). La compresión es primero sin pérdida: se eliminan los metadatos y la imagen se recodifica con los ajustes sin pérdida más fuertes para su formato, por lo que el resultado nunca es más grande que la entrada. Pasa `target_size_kb` para fijar un presupuesto de tamaño de archivo; si la optimización sin pérdida por sí sola no lo alcanza, la imagen se reduce de escala con la relación de aspecto bloqueada hasta que quepa.

---

## Endpoint

```
POST /v1/convert/compress-image
```

**Content-Type:** `multipart/form-data`

**Entrada aceptada:** archivos `.png`, `.jpg`, `.jpeg`, `.webp`

**Formato de salida:** el mismo que la entrada (`image/png`, `image/jpeg` o `image/webp`)

---

## Autenticación

Requiere una clave de API privada o un token JWT de una clave pública.

```
X-API-Key: sk_live_your_private_key
```

O:

```
Authorization: Bearer <jwt_token>
```

---

## Parámetros de la solicitud

| Parámetro | Tipo | Obligatorio | Predeterminado | Descripción |
|-----------|------|----------|---------|-------------|
| `file` | file | Sí | -- | El archivo de imagen `.png`, `.jpg`, `.jpeg` o `.webp` a comprimir. |
| `target_size_kb` | `integer` | No | -- | Tamaño de archivo objetivo en kilobytes. Omitido: solo optimización sin pérdida. Establecido: la imagen además se reduce de escala (relación de aspecto bloqueada) hasta que quepa en el objetivo. |
| `output_filename` | `string` | No | Nombre del archivo de entrada | Nombre de archivo de salida personalizado. La extensión del archivo de entrada se conserva. |
| `direct_download` | `boolean` | No | `true` | Cuando es `true`, devuelve los bytes de la imagen sin procesar. Cuando es `false`, devuelve metadatos JSON con una URL de descarga prefirmada. |

---

## Detalles de la conversión

**Etapa 1 — sin pérdida (siempre se ejecuta):**

- Los metadatos (EXIF, XMP, fragmentos de texto PNG) se **eliminan**; el perfil de color ICC y el indicador de orientación EXIF se **conservan** para que los colores y la rotación no cambien
- **PNG:** se recodifica con la máxima compresión zlib, más una conversión a paleta cuando la imagen tiene 256 colores únicos o menos y el resultado es demostrablemente idéntico píxel a píxel
- **JPEG:** se recodifica reutilizando las tablas de cuantización originales con codificación Huffman progresiva optimizada — no se introduce pérdida de cuantización adicional
- **WebP:** recodificación sin pérdida real (VP8L) con el máximo esfuerzo
- Gana el más pequeño entre los bytes originales y todos los candidatos — **la salida nunca es más grande que la entrada**

**Etapa 2 — reducción de dimensiones (solo con `target_size_kb`, y solo si la etapa 1 no lo alcanza):**

- La imagen se reduce de escala con **la relación de aspecto bloqueada** (remuestreo LANCZOS) y se recodifica, buscando de forma binaria el factor de escala con las mayores dimensiones que quepan en el objetivo
- Los JPEG reducidos y los WebP de origen con pérdida se recodifican a calidad 85; los PNG y los WebP de origen sin pérdida permanecen sin pérdida en el tamaño reducido

<div class="alert alert-info">
<strong>Nota de mejor esfuerzo:</strong> Si el objetivo es inalcanzable incluso en la escala mínima, el endpoint devuelve el archivo más pequeño que consiguió en lugar de un error — comprueba <code>file_size</code> (o el encabezado <code>X-File-Size</code>) para ver qué se alcanzó.
</div>

---

## Respuesta

### Descarga directa (`direct_download=true`, predeterminado)

```
HTTP 200 OK
Content-Type: image/png
Content-Disposition: inline; filename="photo_20260717_123456789.png"
```

Devuelve los bytes de la imagen sin procesar en el mismo formato que la entrada.

### Respuesta con metadatos (`direct_download=false`)

```json
{
    "presigned_url": "https://spaces.example.com/...",
    "object_key": "env/files/{project_id}/compress-image/photo_20260717_123456789.png",
    "filename": "photo_20260717_123456789.png",
    "file_size": 45678,
    "conversion_time_seconds": 0.5
}
```

---

## Ejemplos de código

### Python

```python
import requests

with open("photo.png", "rb") as f:
    response = requests.post(
        "https://api.enconvert.com/v1/convert/compress-image",
        headers={"X-API-Key": "sk_live_your_private_key"},
        files={"file": ("photo.png", f)},
        data={"target_size_kb": 200}
    )

with open("photo_compressed.png", "wb") as out:
    out.write(response.content)
```

### Node.js

```javascript
const form = new FormData();
form.append("file", fs.createReadStream("photo.png"));
form.append("target_size_kb", "200");

const response = await fetch("https://api.enconvert.com/v1/convert/compress-image", {
    method: "POST",
    headers: { "X-API-Key": "sk_live_your_private_key" },
    body: form
});

fs.writeFileSync("photo_compressed.png", Buffer.from(await response.arrayBuffer()));
```

### PHP

```php
$ch = curl_init("https://api.enconvert.com/v1/convert/compress-image");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["X-API-Key: sk_live_your_private_key"],
    CURLOPT_POSTFIELDS => [
        "file" => new CURLFile("photo.png"),
        "target_size_kb" => 200
    ]
]);
$output = curl_exec($ch);
curl_close($ch);
file_put_contents("photo_compressed.png", $output);
```

### Go

```go
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("file", "photo.png")
file, _ := os.Open("photo.png")
io.Copy(part, file)
writer.WriteField("target_size_kb", "200")
writer.Close()

req, _ := http.NewRequest("POST", "https://api.enconvert.com/v1/convert/compress-image", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("X-API-Key", "sk_live_your_private_key")
resp, _ := http.DefaultClient.Do(req)
```

---

## Respuestas de error

| Estado | Condición |
|--------|-----------|
| `400 Bad Request` | El archivo no es un archivo `.png`, `.jpg`, `.jpeg` o `.webp` |
| `400 Bad Request` | El contenido del archivo no coincide con su extensión (el endpoint nunca cambia de formato) |
| `400 Bad Request` | Imagen animada (APNG / WebP animado) — no compatible |
| `400 Bad Request` | `target_size_kb` es cero o negativo |
| `422 Unprocessable Entity` | `target_size_kb` está presente pero no es un número entero |
| `400 Bad Request` | La conversión de la imagen falló (archivo corrupto o no compatible) |
| `401 Unauthorized` | Falta la clave de API/token JWT o no es válida |
| `402 Payment Required` | Se alcanzó el límite mensual de conversiones |
| `402 Payment Required` | Se alcanzó el límite de almacenamiento |
| `413 Payload Too Large` | El archivo supera el tamaño máximo permitido por tu plan |
| `400 Bad Request` | El lienzo de la imagen supera los 40.000.000 de píxeles (protección contra bombas de descompresión) |

---

## Límites

| Límite | Valor |
|-------|-------|
| Tamaño máximo de archivo | Según el plan (Free: 5 MB) |
| Dimensiones máximas de imagen | 40.000.000 de píxeles (p. ej. 8000x5000) |
| Formatos | PNG, JPEG, WebP (solo estáticos — sin animaciones) |
| Tamaño objetivo | Mejor esfuerzo — los objetivos inalcanzables devuelven el archivo más pequeño alcanzable |
| Conversiones mensuales | Según el plan |

---

## Preguntas frecuentes

### ¿Cómo comprimo una imagen sin perder calidad?

Envía la imagen a `/v1/convert/compress-image` sin `target_size_kb`. El endpoint elimina los metadatos y recodifica con los ajustes sin pérdida más fuertes para el formato — los PNG y los WebP sin pérdida permanecen idénticos píxel a píxel, y el JPEG conserva sus tablas de cuantización originales, por lo que no se introduce pérdida de cuantización adicional. El resultado nunca es más grande que tu entrada.

### ¿Cómo comprimo una imagen a un tamaño de archivo específico?

Pasa `target_size_kb` con tu presupuesto en kilobytes (por ejemplo, `200` para 200 KB). La optimización sin pérdida se ejecuta primero; si el archivo sigue por encima del presupuesto, la imagen se reduce de escala con la relación de aspecto bloqueada hasta que quepa. Si el objetivo es inalcanzable incluso en la escala mínima, obtienes el archivo más pequeño alcanzable en lugar de un error.

### ¿La compresión cambia el formato de la imagen?

No, nunca. PNG sigue siendo PNG, JPEG sigue siendo JPEG y WebP sigue siendo WebP — el endpoint rechaza los archivos cuyo contenido no coincide con su extensión en lugar de convertirlos silenciosamente.

### ¿Se eliminan los metadatos de mi imagen?

Los EXIF, XMP y fragmentos de texto PNG se eliminan, lo que a menudo ahorra espacio por sí solo. Dos cosas se conservan deliberadamente: el perfil de color ICC (para que los colores no cambien en visores con gestión de color) y el indicador de orientación EXIF (para que las fotos rotadas se sigan mostrando correctamente).

### ¿Puedo comprimir imágenes animadas?

No. Los archivos APNG y WebP animados se rechazan con un error `400` en lugar de aplanarse silenciosamente a un solo fotograma.
