Image to Base64
Some contexts simply cannot fetch an external image — an HTML email client blocking remote loads, a PDF generator that only understands inline data, an offline-first app. The image to Base64 API converts an image into a ready-to-paste data URI so it travels embedded inside the document instead of as a separate request. Send the image, get back the encoded string with the correct MIME prefix already attached.
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
Why inlining an image is still necessary
Base64 encoding of binary data inside text predates the modern web by decades, built originally to push binary attachments through email systems that only handled plain text. That same trick solved a very different problem once HTML email and PDFs needed images that couldn't rely on an external fetch succeeding at render time. The web moved on to fast CDNs for most images, but the narrow cases where inlining is the only option never went away.
What the endpoint actually returns
POST an image to /image/to-base64 and the task returns a single string: the data URI, formatted as data:image/[type];base64,[encoded content], with the correct MIME type detected from the file itself rather than guessed from its name. That string drops directly into an img src attribute, a CSS background-image rule, or a PDF template field with no further assembly required on your end.
The tradeoff worth knowing
Base64 encoding inflates a file's size by roughly a third, and an inlined image can't be cached separately by a browser the way a linked file can. That tradeoff is exactly why this technique belongs in specific situations — email, PDFs, offline bundles, tiny icons under a few kilobytes — rather than as a default way to serve images on a normal web page, where a direct link almost always performs better.
How it fits an automated pipeline
Because the conversion is asynchronous, it slots into a template-rendering pipeline the same way any other data-fetch step does: a transactional email service calls this endpoint while assembling a receipt or newsletter, waits for the webhook, then splices the returned string into the HTML before sending. PDF generation scripts do the same thing when a logo or chart needs to be embedded rather than linked.
Simple, predictable pricing
Encoding is billed at a single flat fee per request regardless of the image's dimensions, since the work scales with file size, not pixel count, and stays lightweight either way. A request that fails is retried automatically up to three times before returning a clear error, and you're never charged for a conversion that didn't complete.
What you can do with it
HTML email logo embedding
A transactional email service inlines a company logo as a data URI so it renders correctly in inboxes that block remote image loading by default.
PDF invoice generation
A billing system embeds a signature or logo image directly into a generated PDF template, avoiding any dependency on external image fetching at render time.
Offline-first web app assets
A progressive web app inlines small UI icons as data URIs so the interface renders correctly even when the device has no network connection.
Single-file HTML reports
An internal reporting tool embeds chart thumbnails as base64 strings so an exported HTML report works as one self-contained file with no broken image links.
FAQ
What does the image to Base64 API return exactly?
A single data URI string in the format data:image/[type];base64,[content], with the MIME type detected from the actual file, ready to paste into an img tag or CSS rule.
Which image formats can be converted?
PNG, JPEG, WebP and GIF are all supported; the returned data URI's MIME type reflects whichever format was detected in the source file.
Does Base64 encoding make the file bigger?
Yes, encoding increases size by roughly a third over the original binary, which is why inlining works best for small images like icons and logos rather than large photos.
When should I use a data URI instead of a normal image link?
Use it when the destination can't reliably fetch an external file — HTML emails, PDFs, offline app bundles — and avoid it for regular web pages where a linked, cacheable image performs better.
Is the image to Base64 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 do I receive the encoded result?
The task runs asynchronously and returns a task_id right away; the data URI arrives via signed webhook, or you can pull it from a signed link valid for 24 hours.
Is there a size limit on the source image?
Very large source files simply take a little longer and produce a longer encoded string; extremely large images are generally poor candidates for inlining regardless of the limit.
What happens if the conversion fails?
The task retries automatically up to three times before returning a clear error, and a failed conversion is never charged.
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/to-base64 \
-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/to-base64", {
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/to-base64",
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/to-base64", 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/to-base64", 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.to_base64",
"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. |