Transcript with timestamps
A plain transcript tells you what was said; it can't tell you when. This endpoint returns the same accurate transcript plus a timing marker for every word, so any downstream tool can jump straight to the exact second a phrase was spoken instead of scanning a wall of text.
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 gap a plain transcript leaves open
Text alone is enough to read what happened in a recording, but it breaks down the moment you need to act on a specific moment — cutting a video clip at the right phrase, jumping a listener to the part of a podcast that answers their question, or building a searchable index where a query returns the exact second, not just the episode. A transcript without timing is a summary of when it should be a map.
What comes back in the result
POST an audio file to /audio/transcribe-timestamps and the task returns the full transcript broken into words, each carrying a start and end time in seconds, alongside the same text a plain transcription would give you. That granularity is what separates it from a caption file that only marks whole lines — it's built for tools that need to reason about individual words, not just phrases.
Where word-level timing actually gets used
Video editors use it to snap a cut to the exact frame a word ends, karaoke-style caption tools use it to highlight each word as it's spoken, and search systems use it to let a user click a search result and land inside the audio at the right instant rather than the start of the file. None of that is possible from a transcript that only says what was said, not when.
How the timing is produced
The task processes the audio the same way a full transcription does, detecting speech and language automatically, but tracks the position of each recognized word against the underlying audio signal rather than discarding that information once the text is assembled. Long recordings are chunked automatically, and timing stays consistent across chunk boundaries so a cut near the seam of two segments still lands correctly.
Billing and reliability
Pricing is a small per-request base fee plus a per-minute rate, the same shape as plain transcription, so timestamped output doesn't carry a hidden premium beyond the minutes actually processed. The task is asynchronous end to end — submit audio, get a task_id back immediately, and receive the timestamped transcript by signed webhook or from a signed link valid for 24 hours; a failed job retries automatically up to three times and is never billed if it still doesn't complete.
What you can do with it
Video editing and clip creation
An editor searches a transcript for a quote and jumps directly to that timestamp in the source footage instead of scrubbing through the whole recording.
Word-level highlighted captions
A video platform highlights each spoken word in sync with playback, the kind of caption style used in social clips and language-learning videos.
Searchable podcast and lecture archives
A media library lets users search transcript text and click straight into the audio at the moment a phrase was actually said.
Precise audio clip extraction
An automation trims out just the sentence a caller asked a question in, using the word timestamps to set the exact cut points.
FAQ
How is this different from a regular transcription?
A plain transcription returns text; this endpoint returns the same text with a start and end time for every word, so tools can act on exact moments instead of just reading the content.
Do I get timing per word or just per sentence?
Timing is provided at the word level, which is finer-grained than the line-level timing found in subtitle formats like SRT or VTT.
How is the transcription with timestamps API priced?
A small base fee per request plus a per-minute rate based on audio length, published on this page; a failed transcription is never charged.
Which languages and audio lengths are supported?
The same language coverage and long-file chunking as standard transcription apply here, with the language detected automatically or set explicitly.
How do I receive the timestamped result?
By signed webhook once the task finishes, or by pulling it from a signed link that stays valid for 24 hours after completion.
Can I use this to build subtitles instead?
For ready-to-ship caption files, the SRT and VTT subtitle endpoints group timing into lines automatically; use this endpoint when you need word-level precision instead.
Is there a free tier to test it?
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.
What happens on transcription failure?
The task retries automatically up to three times before returning a clear error, and you're never charged for a request that doesn't succeed.
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/audio/transcribe-timestamps \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"audio":"https://ejemplo.com/audio.mp3"}'const res = await fetch("https://api.kit.forhosting.com/audio/transcribe-timestamps", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"audio": "https://ejemplo.com/audio.mp3"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/audio/transcribe-timestamps",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"audio": "https://ejemplo.com/audio.mp3"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/audio/transcribe-timestamps", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"audio":"https://ejemplo.com/audio.mp3"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"audio":"https://ejemplo.com/audio.mp3"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/audio/transcribe-timestamps", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"audio": "https://ejemplo.com/audio.mp3"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "audio.transcribe_timestamps",
"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 | 200 |
max_minutes | 180 |
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. |