Check image quality
Find out whether an upload is blurry, too dark or full of sensor noise before it reaches a listing, a profile or a print order. It judges whether the photo is usable, not what it shows, and you decide the bar. You pay per use, with no subscription.
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.
Not every rejected upload is inappropriate content — plenty are just bad photos: out of focus, shot in the dark, or full of sensor noise.
The quiet problem no one flags manually
A blurry product photo doesn't violate any policy, so it sails past content moderation — and still tanks conversion, still looks unprofessional, still generates a support message asking for a better picture. Nobody wants to build a manual review step just for photo sharpness, and nobody has the staff to eyeball every upload for exposure and noise either. image.quality automates exactly that judgment, scoring the technical condition of an image rather than what it depicts.
Where it belongs in a pipeline
Most teams run image.quality as the very first gate on new uploads — before storage, before moderation, before it ever reaches a customer-facing page — since there's little point moderating or tagging a photo that's unusable anyway. Chain it with image.moderate for a single combined checkpoint that rejects both unsafe and unusable images, or with image.tag and image.classify once a photo has already passed the quality bar.
Pricing is a small per-request base plus a per-image rate, both published, and a request that fails after three automatic retries is never charged.
What you can do with it
Marketplace and classifieds listings
Reject blurry or poorly lit product photos at upload time instead of letting a low-quality listing hurt buyer trust.
Profile photo uploads
Prompt users to retake a dark or out-of-focus profile picture immediately, before it's ever shown to anyone else.
Print and merchandise storefronts
Enforce a minimum sharpness bar on customer-supplied artwork so nothing ships as a blurry, unusable print.
Bulk archive cleanup
Scan an existing photo library to identify and flag technically poor images that were uploaded before any check existed.
FAQ
Is image quality assessment free?
There's no free tier — free tiers get abused and slow everyone down. No subscription, no tokens, no invented credits, and a failed task is never charged.
How is image.quality different from image.moderate?
Quality checks whether a photo is technically usable — sharp, well lit, low noise; moderation checks whether its content is appropriate to publish. They're separate, complementary checks.
Can I set my own quality threshold?
Yes — the assessment gives you a technical condition score you can map to your own accept, warn or reject logic per use case.
Can I scan an entire existing photo library for quality issues?
Yes, each image is its own async task, so a full library can be checked the same way as new uploads, just at a larger volume.
What happens if a quality check fails?
It's retried automatically up to three times; if it still fails you get a clear error and pay nothing for that request.
Related tools
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, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/image/quality \
-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/quality", {
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/quality",
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/quality", 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/quality", 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.quality",
"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. |
422 | task_failed | The task failed after 3 retries. You are never charged for it. |
Technical notes
This endpoint scores technical image quality so those uploads get caught before a listing, profile or gallery ships with an unusable photo.
What gets measured
You set the bar: a marketplace might accept looser standards than a print-on-demand storefront that needs genuinely sharp source images. POST an image to /image/quality and get back an assessment of its technical condition — covering issues like blur, poor lighting or excessive noise — so your application can reject or request a re-upload before the photo ever reaches a live listing or public profile.
Why this sits apart from content checks
Quality assessment answers a different question than moderation or classification: not 'what is this image' but 'is this image technically usable'. A perfectly appropriate, perfectly on-topic photo can still fail here if it's dark and grainy, and a technically pristine photo can still need moderation for what it shows — the two checks are complementary, not overlapping, which is exactly why they're separate endpoints you can call together or independently.
Built to run at upload speed
Because photo uploads spike unpredictably — a product launch, a marketing push, a viral post — the endpoint queues instantly and returns a task_id right away rather than holding a connection open while it scores the image. The assessment follows by webhook the moment it's ready, or through a signed link retrievable for 24 hours, so upload flows stay responsive no matter how many photos land at once.
Technical questions
What does the image quality API actually check?
Technical condition — issues like blur, poor lighting and excessive noise — rather than the subject matter or appropriateness of the photo.
How is image quality assessment priced?
A small fixed fee per request plus a per-image rate, both published on this page, with no hidden credits or tokens.
How fast do results come back?
A task_id returns immediately, and the assessment follows by signed webhook, or via a signed link valid for 24 hours.