---
seo_title: HEIC to PNG API: Convert HEIC/HEIF Images to PNG | EnConvert
meta_desc: Convert HEIC to PNG with a REST API. POST /v1/convert/heic-to-png accepts .heic or .heif uploads and returns a lossless PNG as raw bytes or a presigned URL.
keywords: heic to png api, convert heic to png api, heif to png api, heic to png rest api, heic to png python, heic to png node js, heic decoding api, lossless heic to png conversion
---

# HEIC to PNG API

The HEIC to PNG API converts a HEIC/HEIF image to PNG format with a single request to `POST /v1/convert/heic-to-png`. Upload a `.heic` or `.heif` file as multipart/form-data and receive a lossless PNG with full color fidelity as raw bytes, or set `direct_download=false` to get JSON metadata with a presigned download URL.

---

## Endpoint

```
POST /v1/convert/heic-to-png
```

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

**Accepted input:** `.heic or .heif` files

**Output format:** `.png` (`image/png`)

---

## Authentication

Requires either a private API key or a JWT token from a public key.

```
X-API-Key: sk_your_private_key
```

Or:

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

---

## Request Parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `file` | file | Yes | -- | The `.heic or .heif` image file to convert. |
| `output_filename` | `string` | No | Input filename | Custom output filename. The `.png` extension is added automatically. |
| `direct_download` | `boolean` | No | `true` | When `true`, returns raw image bytes. When `false`, returns JSON metadata with a presigned download URL. |

---

## Conversion Details

- Uses **pillow-heif** for HEIC decoding and **Pillow** for PNG encoding
- Color data is preserved losslessly in the PNG output
- Non-RGBA/RGB color modes are converted to RGBA
- PNG output uses lossless compression


---

## Response

### Direct Download (`direct_download=true`, default)

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

Returns raw image bytes.

### Metadata Response (`direct_download=false`)

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

---

## Code Examples

### Python

```python
import requests

with open("photo.heic", "rb") as f:
    response = requests.post(
        "https://api.enconvert.com/v1/convert/heic-to-png",
        headers={"X-API-Key": "sk_your_private_key"},
        files={"file": ("photo.heic", f)}
    )

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

### Node.js

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

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

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

### PHP

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

### Go

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

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

---

## Error Responses

| Status | Condition |
|--------|-----------|
| `400 Bad Request` | File is not a `.heic or .heif` file |
| `400 Bad Request` | Image conversion failed (corrupt or unsupported file) |
| `401 Unauthorized` | Missing or invalid API key / JWT token |
| `402 Payment Required` | Monthly ops allowance exhausted |
| `402 Payment Required` | Storage limit reached |
| `413 Payload Too Large` | File exceeds plan's maximum file size |

---

## Limits

| Limit | Value |
|-------|-------|
| Max file size | Plan-dependent (Founding: 5 MB) |
| Output quality | Maximum (not configurable) |
| Monthly conversions | Plan-dependent |

---

## Frequently asked questions

### How do I convert HEIC to PNG with a REST API?

Send a `POST` request to `/v1/convert/heic-to-png` with your `.heic` or `.heif` file in a `multipart/form-data` body, authenticated via `X-API-Key` or a JWT `Authorization: Bearer` token. The converted PNG is returned as raw image bytes by default.

### Is the HEIC to PNG conversion lossless?

Yes. Color data is preserved losslessly and the PNG output uses lossless compression. Decoding uses pillow-heif and encoding uses Pillow.

### Does the API accept HEIF files as well as HEIC?

Yes. The endpoint accepts both `.heic` and `.heif` files; anything else is rejected with `400 Bad Request`.

### Can I get a download URL instead of raw PNG bytes?

Yes. Set `direct_download=false` and the API returns JSON metadata with a `presigned_url`, `filename`, `file_size`, and `conversion_time_seconds`.

### Why does the API return 402 Payment Required?

A `402 Payment Required` response means your plan's monthly ops allowance or storage limit has been reached.
