Product packshots
Marketplaces don't just prefer white-background product photos, most of them require it as a listing condition, and a rejected photo means a delayed listing. This endpoint takes a product photo and produces a clean, centred packshot on pure white, sized and lit the way a marketplace's image checker expects.
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 listing that gets rejected before it's even live
Anyone who has tried to list a product on a major marketplace knows the image rules are strict and specifically checked: pure white background, product filling a defined percentage of the frame, no watermarks, no props, no shadows crossing the edge. A photo that looks perfectly fine to a human eye still gets auto-rejected if the background isn't close enough to true white, and re-shooting or manually editing every SKU to meet that bar is one of the least glamorous, most repetitive parts of running a catalogue.
What a packshot pass actually does
The task isolates the product from whatever background it was photographed against, places it on a pure white field, and centres and scales it to sit correctly in the frame — the same visual treatment a studio photographer would apply with a lightbox and careful retouching, but automated. You send the source photo, the task returns a marketplace-ready image, and the result is built to pass the same automated checks a marketplace runs on every listing photo.
Where the white-background convention came from
Pure white product photography has roots in traditional catalogue and print retail, where a plain background kept printing costs down and let the product read clearly on a page regardless of size. Online marketplaces inherited and formalised that convention, turning it from a stylistic preference into an enforced technical requirement, because a uniform grid of white-background thumbnails is dramatically easier to browse than a grid of inconsistent, cluttered ones.
Who needs this at volume
Sellers onboarding a large catalogue onto a marketplace for the first time need every SKU converted at once, not one photo at a time in a photo editor. Suppliers sending raw factory photos to a retailer need those images standardised before they're usable in any storefront. Photo studios doing volume product photography use it to skip the manual lightbox cleanup pass entirely and hand off a batch straight from the camera.
Fitting it into a listing pipeline
The endpoint runs asynchronously: submit the source photo, get a task_id back immediately, and receive the finished packshot by signed webhook the moment it's ready. It fits naturally right before a listing publish step, and pairs well with a resize or format-conversion step afterward so the same packshot can be produced once and adapted to each marketplace's exact size requirements.
What you can do with it
New marketplace onboarding
A seller migrating a full catalogue onto a new marketplace converts every product photo to a compliant white-background packshot in one pass instead of editing each by hand.
Supplier photo standardisation
A retailer receives inconsistent factory photos from dozens of suppliers and normalises them all to the same white-background standard before publishing.
Studio workflow shortcut
A product photography studio skips the manual lightbox retouching step and runs freshly shot photos straight through the packshot endpoint.
Multi-marketplace resale
A reseller listing the same product across several marketplaces, each with its own image rule, generates one compliant packshot that satisfies all of them.
FAQ
How do I turn a product photo into a white-background packshot through the api?
POST to /image/packshot with the source photo; you get a task_id back and the finished packshot arrives by webhook or signed link.
Will the result pass marketplace image compliance checks?
It's built to produce a true white background with a properly centred, scaled product, matching the checks most marketplaces run on listing photos.
Does it add a drop shadow under the product?
The default output is a clean packshot on pure white; check the request options for shadow handling if your listing style calls for it.
What image formats does it accept and return?
Common raster formats are accepted on input, and you choose the output format for the finished packshot.
Is there a free tier for the packshot 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 much does it cost to generate a packshot?
$0.062 per request plus $0.004 per image, charged only on tasks that complete successfully.
Is the packshot api available now?
It's in deployment and not yet accepting jobs; the endpoint and pricing described here are final and will go live shortly.
Can I process a whole product catalogue at once?
Yes, pair this endpoint with the Batch Processing API to generate packshots for an entire catalogue in one call, each image priced and metered separately.
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/packshot \
-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/packshot", {
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/packshot",
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/packshot", 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/packshot", 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.packshot",
"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. |