Translate an HTML page
Translating a live web page usually means someone copy-pastes text out of tags, translates it, and pastes it back in — hoping nobody breaks an attribute along the way. This endpoint reads the DOM, translates only what a visitor actually sees, and hands back the same markup with the same structure intact.
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 tag-breaking problem
Machine translation tools built for plain prose choke on HTML because they don't know the difference between a sentence and a script tag. Feed a raw page through a generic translator and you'll often get broken attributes, translated class names, or href values quietly mangled — the kind of bug that doesn't show up until a link stops working in production. translate.html parses the document first, so translation only ever touches text nodes and the handful of attributes that are meant to carry language, like alt and title.
What actually gets translated
Visible text, alt attributes on images, title tooltips, and meta description content move to the target language. Tag names, class and id attributes, inline styles, script and style block contents, and the overall document tree stay exactly as they were. Nesting, comments, and whitespace-sensitive formatting inside
or blocks are left untouched, because code samples in a tutorial page shouldn't get translated into another language by accident.The request itself
POST the HTML fragment or full document to /translate/html along with the target language, and the task runs asynchronously. You get a task_id back immediately, and the translated HTML arrives later through a signed webhook call or a signed link that stays valid for 24 hours — whichever fits how your deployment pipeline already checks for finished work.
Why markup-aware translation matters for automation
A localization pipeline that treats HTML as HTML, not as a blob of text, is one that can run unattended. Marketing pages, product descriptions, help-center articles and email templates are almost always authored in HTML, and a script that submits every page in a sitemap overnight, tag by tag, structure preserved, removes the manual QA pass that used to catch a translator's stray closing tag. Because pricing is a small flat fee plus a per-word rate, translating a thousand short pages costs proportionally the same as translating one — there's no minimum batch size and no discount tier to negotiate, just a predictable line item your team can budget against.
What you can do with it
Marketing page localization
An e-commerce site submits its product landing pages as HTML and gets back the same layout in Portuguese, ready to publish without a developer re-wiring the template.
Help center translation
A SaaS support team translates hundreds of help articles authored in HTML while preserving embedded screenshots, anchor links and step-by-step formatting.
Transactional email templates
A billing system translates its HTML email templates into each customer's language while keeping merge tags and button styling exactly where they were.
CMS content pipeline
A headless CMS calls the endpoint on publish, translating each new blog post's HTML body automatically into the site's other locales.
FAQ
How do I translate HTML through the API?
POST the HTML content and target language to /translate/html, store the returned task_id, and retrieve the translated markup by webhook or a signed link valid for 24 hours.
Is the HTML translation API free?
No, there's no free tier or trial; it costs $0.003 per request plus $0.0135 per 1000 words, and a failed task is never charged.
Does it translate tags, classes or attributes like href?
No, only visible text and language-carrying attributes such as alt and title are translated; tag names, classes, ids and href values stay unchanged.
Will it touch content inside script or style tags?
No, script blocks, style blocks and inline code inside pre or code tags are left exactly as written.
Can I submit a full HTML document, not just a fragment?
Yes, both full documents and standalone fragments are supported, and the response mirrors whichever structure you sent.
Can I translate many pages in bulk?
Yes, submit one async request per page and collect each translated file as it finishes, which is how most sitemap-wide migrations are run.
Is this endpoint live?
Yes, /translate/html is live and accepting requests now.
What happens to my HTML after translation?
Source and translated files are deleted after the retention window and are never used to train models.
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/translate/html \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"…"}'const res = await fetch("https://api.kit.forhosting.com/translate/html", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "…"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/translate/html",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "…"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/translate/html", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"…"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"…"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/translate/html", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"text": "…"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "translate.html",
"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_tokens | 20000 |
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. |