Skip to content

Examples

The same call in each language: resize photo.jpg to 800px wide, convert to WebP, compress at quality 80, and strip EXIF metadata. Swap in your own key.

curl

curl -X POST https://api.purlo.dev/v1/image \
  -H "Authorization: Bearer purlo_YOUR_KEY" \
  -F 'operations={"resize":{"w":800},"format":"webp","quality":80,"strip":true}' \
  -F "image=@photo.jpg" \
  -o out.webp

JavaScript (fetch, Node 18+ or browser)

import { readFile, writeFile } from 'node:fs/promises';

const operations = {
  resize: { w: 800 },
  format: 'webp',
  quality: 80,
  strip: true,
};

const form = new FormData();
form.append('operations', JSON.stringify(operations));
form.append('image', new Blob([await readFile('photo.jpg')]), 'photo.jpg');

const res = await fetch('https://api.purlo.dev/v1/image', {
  method: 'POST',
  headers: { Authorization: 'Bearer purlo_YOUR_KEY' },
  body: form,
});

if (!res.ok) {
  const { error } = await res.json();
  throw new Error(`${error.code}: ${error.message}`);
}

await writeFile('out.webp', Buffer.from(await res.arrayBuffer()));

In a browser, drop the node:fs/promises import and build the Blob from a <input type="file"> element's files[0] instead.

PHP (curl)

<?php

$operations = [
    'resize'  => ['w' => 800],
    'format'  => 'webp',
    'quality' => 80,
    'strip'   => true,
];

$ch = curl_init('https://api.purlo.dev/v1/image');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer purlo_YOUR_KEY'],
    CURLOPT_POSTFIELDS => [
        'operations' => json_encode($operations),
        'image'      => new CURLFile('photo.jpg'),
    ],
    CURLOPT_RETURNTRANSFER => true,
]);

$body   = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status !== 200) {
    fwrite(STDERR, $body . PHP_EOL);
    exit(1);
}

file_put_contents('out.webp', $body);

Python (requests)

import json
import requests

operations = {
    "resize": {"w": 800},
    "format": "webp",
    "quality": 80,
    "strip": True,
}

with open("photo.jpg", "rb") as image:
    resp = requests.post(
        "https://api.purlo.dev/v1/image",
        headers={"Authorization": "Bearer purlo_YOUR_KEY"},
        data={"operations": json.dumps(operations)},
        files={"image": image},
    )

resp.raise_for_status()

with open("out.webp", "wb") as f:
    f.write(resp.content)

Fetching by URL instead of uploading

All four languages accept a url field instead of an image file. curl example:

curl -X POST https://api.purlo.dev/v1/image \
  -H "Authorization: Bearer purlo_YOUR_KEY" \
  -F 'operations={"resize":{"w":800},"format":"webp","quality":80,"strip":true}' \
  -F "url=https://example.com/photo.jpg" \
  -o out.webp

See Reference for details, and Errors & limits for what URLs get rejected.