Smart crop
A centred crop cuts off heads, half the product, or the one detail that made the photo worth using in the first place. This endpoint finds where the subject actually sits in the frame and crops around it, so a thousand product photos or article thumbnails still look intentional at any aspect ratio.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
The problem with fixed-centre cropping
Most crop tools slice a fixed box out of the middle of an image and hope the subject happened to be centred. It rarely is: a portrait shot slightly off-axis, a product photographed with room for a caption, a landscape where the horizon sits low — a blind centre crop turns any of these into a bad thumbnail. Smart crop looks at where the visual weight of the image actually is before deciding what to keep.
Who needs subject-aware cropping
Catalogs with thousands of supplier photos shot at inconsistent framing; publishers turning hero images into square social cards without a designer touching each one; marketplaces that need the same product image to work as a 1:1 tile, a 4:3 listing photo and a 16:9 banner. Anywhere one source image has to become several fixed shapes automatically, this is the step that keeps the subject in frame.
What happens to your image
You post the source file with the target dimensions, we return a task_id right away, and the job analyzes the frame to locate the region worth keeping before cropping to the exact size requested. When it's ready you're notified by signed webhook, or you fetch it from a signed link valid for 24 hours.
Fitting it into a catalog pipeline
Because it's async and billed only when a crop succeeds, it slots into ingestion pipelines cleanly: a supplier feed drops in five hundred raw photos, five hundred smart-crop requests go out, and webhooks return finished thumbnails as each one lands — no manual review queue, no charge for failures.
Why centre-cropping stuck around this long
Centre cropping survived for decades simply because it's cheap to compute — a fixed offset needs no analysis of the pixels at all. It works fine when every source photo is already framed identically, which is rare outside a studio with a locked tripod and a controlled lighting rig. The moment images arrive from different photographers, different cameras or different suppliers, framing stops being consistent, and that's exactly the gap subject-aware cropping closes, without adding a manual review step to a pipeline that's supposed to run unattended.
What you can do with it
Marketplace thumbnails
A supplier feed of product photos gets cropped to a uniform square grid without anyone manually recentering off-axis shots.
Article hero images
A CMS turns a wide editorial photo into a square social card automatically, keeping the subject's face in frame instead of the empty background.
Multi-format listings
The same product photo is cropped to 1:1, 4:3 and 16:9 for different placements on a storefront, each version still centred on the product.
User-uploaded avatars
Profile photos uploaded at arbitrary framing get cropped around the face rather than the literal middle of the image.
FAQ
Is the Smart Crop API available now?
Yes, it's live at POST /image/smart-crop with the pricing below already in effect.
How is it priced?
$0.002 per request plus $0.005 per image — a small base fee plus a flat per-image rate, published and unchanged by volume.
What image formats does it accept?
Common raster formats such as JPEG, PNG and WebP; the crop is returned in the same format as the source unless a target format is specified.
Can I set a specific aspect ratio?
Yes, you pass the target dimensions or ratio in the request and the crop is fit to that exact size around the detected subject.
Is it a free API?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
How do I get the result?
By signed webhook when the crop is ready, or via a signed link that stays valid for 24 hours.
Am I charged if the crop fails?
No. Failed tasks retry automatically up to three times and are never billed; you get a clear error instead.
Can I crop a whole catalog at once?
Yes — each request handles one image and returns its own task_id, so a catalog of thousands is just parallel requests collected by webhook.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/image/smart-crop \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"image":"https://ejemplo.com/imagen.jpg"}'const res = await fetch("https://api.kit.forhosting.com/image/smart-crop", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"image": "https://ejemplo.com/imagen.jpg"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/image/smart-crop",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"image": "https://ejemplo.com/imagen.jpg"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/image/smart-crop", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"image":"https://ejemplo.com/imagen.jpg"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"image":"https://ejemplo.com/imagen.jpg"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/image/smart-crop", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"image": "https://ejemplo.com/imagen.jpg"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "image.smart_crop",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 15 |
max_megapixels | 12 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |