Generate a BlurHash
Before a photo finishes downloading, most apps show nothing, or worse, a flash of white. This endpoint generates a tiny encoded string that renders as a soft, blurred preview of the actual image, so the layout feels alive from the first frame instead of empty.
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
The blank-space problem
Photo-heavy feeds, galleries and marketplaces all face the same rendering problem: images are the heaviest asset on the page, and until they arrive, something has to occupy their space. A gray box or a spinner works, but it tells the user nothing about what's coming and makes the layout feel unfinished. A blurred approximation of the actual photo, by contrast, gives an immediate sense of color and composition, and the shift from blur to sharp photo reads as a natural reveal rather than a layout jump.
What the string actually encodes
Send an image to POST /image/blurhash and the task returns a short encoded string, typically well under a hundred characters, that captures the image's rough shape and color distribution. That string can be embedded directly in your API response or database record — no extra image file to store or fetch — and decoded client-side into a blurred canvas or CSS background in a few lines of widely available client code.
Where the technique comes from
The approach behind BlurHash-style encoding builds on a much older idea in image compression: represent an image as a sum of smooth basis functions rather than individual pixels, keeping only the first few terms to describe its overall look. That's conceptually related to how JPEG itself achieves compression, just taken to an extreme where you keep only enough information to describe the general shape and palette, discarding everything that would let you reconstruct fine detail — which is exactly the point for a placeholder.
How the result comes back
Every task on this API is asynchronous: submitting an image returns a task_id immediately, and the encoded string arrives through a signed webhook or a signed link valid for 24 hours. Because the output is just a short string rather than a file, it's cheap to store permanently alongside the original image record and reused on every render without recomputation.
Fitting it into a real pipeline
The natural place to call this is once, at upload time, storing the resulting string next to the image URL in your database so every future page load already has it available before the real photo is even requested. At $0.002 per request with failed attempts never billed, generating a placeholder for every image in a catalog costs a fraction of what the bandwidth savings and perceived speed improvement are worth.
What you can do with it
Photo feeds and social apps
Show a blurred preview the instant a feed renders, then swap in the full photo as it loads, avoiding blank tiles while scrolling.
E-commerce product galleries
Generate a placeholder for every product image at upload time so gallery pages never show empty boxes during the first paint.
Image-heavy marketplaces
Store a blur string with every listing photo to keep search results feeling instant even on slow mobile connections.
Native and hybrid mobile apps
Decode the compact string locally to render a smooth placeholder before any network request for the actual image completes.
FAQ
How does BlurHash differ from a low-res thumbnail?
BlurHash returns a short text string, not an image file, so there's nothing extra to store or download; a thumbnail is still a separate file that needs its own request.
Is the BlurHash API free to use?
The tool above runs free in your browser. The API is paid — each call draws from your prepaid ForHosting KIT balance: top up from $10.00 (it never expires), pay each request's published price, and a call with no balance returns HTTP 402. No subscription, no tokens, and a failed task is never charged.
How large is the resulting string?
Typically well under a hundred characters, small enough to store directly as a database field alongside the image record.
Do I need a special library to render it?
You decode the string client-side using widely available open decoders for web, iOS and Android; the API's job is just to generate the encoded string.
Can I generate placeholders for an entire image library in bulk?
Yes, submit one request per image; each is queued and billed independently, so processing a whole library is just repeated calls, no special batch mode needed.
How do I receive the generated string?
Via a signed webhook, recommended for automated pipelines, or a signed link valid for 24 hours.
What image formats can I submit?
Standard raster formats such as JPEG and PNG are supported for generating the placeholder encoding.
Should I regenerate the string if I resize the image?
No, the encoded string captures the overall shape and color of the image and stays valid regardless of the display size you render it at.
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/blurhash \
-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/blurhash", {
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/blurhash",
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/blurhash", 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/blurhash", 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.blurhash",
"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. |