List voices
GET https://api.kittenml.com/v1/voices?model=kitten-tts-2-latest
The three KittenTTS 0.8 models have a fixed eight-voice catalog and no voice listing. See feature support by model.
Use this authenticated endpoint instead of hard-coding the voice catalog. It returns all 47 Kitten TTS 2 built-in voices with their title and language, the voice-cloning capability, the active saved voices owned by the caller's organization, and any shared voices that KittenML makes available to every organization.
Query parameters
| Parameter | Default | Accepted values |
|---|---|---|
model | Kitten TTS 2 | kitten-tts-2-latest |
limit | 100 | 1 through 100. Limits saved voices only, never built-ins or shared voices |
after | — | The last_custom_id of the previous page |
Always send model=kitten-tts-2-latest. The model fields in the response
repeat the ID you sent. A request that omits model still gets the Kitten TTS 2
catalog, but reports it under the model's earlier ID; see the legacy note in
Models. The three KittenTTS 0.8 models have a
fixed eight-voice catalog, listed in
KittenTTS 0.8 voices.
cURL
curl -L --fail-with-body -sS \
'https://api.kittenml.com/v1/voices?model=kitten-tts-2-latest' \
-H "Authorization: Bearer $KITTENML_API_KEY"
Python with httpx
pip install httpx
import os
import httpx
response = httpx.get(
"https://api.kittenml.com/v1/voices",
params={"model": "kitten-tts-2-latest"},
headers={"Authorization": f"Bearer {os.environ['KITTENML_API_KEY']}"},
follow_redirects=True,
timeout=30,
)
response.raise_for_status()
catalog = response.json()
for voice in catalog["data"]:
# Send a built-in's id as the voice string; send others as {"id": ...}.
print(f"{voice['type']:<8} {voice['language']} {voice['id']}")
print(f"request_id: {response.headers.get('x-request-id')}")
JavaScript with fetch
Node.js 18 and later include fetch, which follows redirects by default.
const url = new URL("https://api.kittenml.com/v1/voices");
url.searchParams.set("model", "kitten-tts-2-latest");
const response = await fetch(url, {
headers: {Authorization: `Bearer ${process.env.KITTENML_API_KEY}`},
});
const requestId = response.headers.get("x-request-id");
const catalog = await response.json();
if (!response.ok) {
throw new Error(`${catalog.error?.message} (request_id=${requestId})`);
}
for (const voice of catalog.data) {
// Send a built-in's id as the voice string; send others as {id}.
console.log(`${voice.type.padEnd(8)} ${voice.language} ${voice.id}`);
}
console.log(`request_id: ${requestId}`);
Response
This response is shortened to one built-in voice and one saved voice. A real response lists all 47 built-ins first, in number order, then the caller's saved voices, newest first, then any shared voices.
{
"object": "list",
"model": "kitten-tts-2-latest",
"data": [
{
"id": "frank_gravelly_male_18",
"object": "audio.voice",
"name": "18 — Frank — Gravelly Male",
"type": "built_in",
"model": "kitten-tts-2-latest",
"language": "en",
"experimental": false
},
{
"id": "voice_0123456789abcdef0123456789abcdef",
"created_at": 1787760000,
"name": "My saved voice",
"object": "audio.voice",
"type": "custom",
"model": "kitten-tts-2-latest",
"language": "en",
"experimental": false
}
],
"public_voices_unavailable": false,
"languages": [
{"code": "en", "experimental": false},
{"code": "ar", "experimental": false},
{"code": "de", "experimental": false},
{"code": "es", "experimental": false},
{"code": "fr", "experimental": false},
{"code": "it", "experimental": false},
{"code": "pt", "experimental": false},
{"code": "ru", "experimental": false},
{"code": "zh", "experimental": false},
{"code": "hi", "experimental": false}
],
"voice_cloning": {
"supported": true,
"custom_voices_included": true,
"saved_voices_supported": true,
"supported_languages": ["en"],
"create_endpoint": "/v1/audio/voices",
"consent_endpoint": "/v1/audio/voice_consents"
},
"has_more": false,
"first_custom_id": "voice_0123456789abcdef0123456789abcdef",
"last_custom_id": "voice_0123456789abcdef0123456789abcdef"
}
Each entry in data is an audio.voice object:
| Field | Meaning |
|---|---|
id | The value to select this voice with |
name | For a built-in, its title, such as 18 — Frank — Gravelly Male; for a saved or shared voice, the name it was created with |
type | built_in for the catalog below, custom for a saved voice your organization owns, or public for a shared voice |
model | The model ID you sent |
language | ISO 639-1 code of the language the voice speaks |
experimental | false for every current voice |
created_at | Unix timestamp in seconds; saved and shared voices only |
Select a built-in by sending its id as the voice string. Select a saved
voice with an object, "voice": {"id": "voice_..."}; a bare voice_...
string is checked against the built-in catalog and rejected with
400 invalid_voice. On the
input-streaming WebSocket, put either id in the
voice query parameter.
Entries with type: "public" are shared voices that KittenML makes available
to every organization. Select one by its name as the voice string, for
example "voice": "Warm Narrator", or by its id exactly like a saved voice;
on the WebSocket, either goes in the voice query parameter. Shared voice
names are unique and never reuse a built-in voice ID, which always selects the
built-in. They follow your own saved voices on every page and are not counted
by limit or the cursors.
public_voices_unavailable is true when the shared voices could not be read
for this response; the built-ins and your saved voices are still complete.
Saved and shared voices currently use English reference transcripts and report
language: "en".
Built-in voices
Kitten TTS 2 has 47 built-in voices. Select one by its voice ID: lowercase
words and the voice's two-digit number, separated by underscores. Copy the ID
from this table or from the response's id; the title is the voice's display
name (name). Voice IDs are case-sensitive. The default voice is
eleanor_somber_female_32.
| Voice ID | Title | Language |
|---|---|---|
matthew_exhausted_mechanic_male_01 | 01 — Matthew — Exhausted Mechanic Male | English |
willow_hushed_young_female_02 | 02 — Willow — Hushed Young Female | English |
dolores_southern_elderly_female_03 | 03 — Dolores — Southern Elderly Female | English |
victor_controlled_fury_older_male_04 | 04 — Victor — Controlled Fury Older Male | English |
dante_playful_smooth_young_male_05 | 05 — Dante — Playful Smooth Young Male | English |
alfred_tender_older_male_06 | 06 — Alfred — Tender Older Male | English |
saoirse_joyful_irish_female_07 | 07 — Saoirse — Joyful Irish Female | English |
claire_playful_professional_female_08 | 08 — Claire — Playful Professional Female | English |
raven_controlled_fury_young_female_09 | 09 — Raven — Controlled Fury Young Female | English |
bella_10 | 10 — Bella (Kitten V0.8) | English |
jasper_11 | 11 — Jasper (Kitten V0.8) | English |
luna_12 | 12 — Luna (Kitten V0.8) | English |
bruno_13 | 13 — Bruno (Kitten V0.8) | English |
rosie_14 | 14 — Rosie (Kitten V0.8) | English |
hugo_15 | 15 — Hugo (Kitten V0.8) | English |
kiki_16 | 16 — Kiki (Kitten V0.8) | English |
leo_17 | 17 — Leo (Kitten V0.8) | English |
frank_gravelly_male_18 | 18 — Frank — Gravelly Male | English |
herbert_wise_male_19 | 19 — Herbert — Wise Male | English |
diana_stern_female_20 | 20 — Diana — Stern Female | English |
laurence_dramatic_male_21 | 21 — Laurence — Dramatic Male | English |
maeve_cozy_female_22 | 22 — Maeve — Cozy Female | English |
walter_warm_male_23 | 23 — Walter — Warm Male | English |
edith_soft_female_24 | 24 — Edith — Soft Female | English |
miles_gentle_male_25 | 25 — Miles — Gentle Male | English |
grace_soothing_female_26 | 26 — Grace — Soothing Female | English |
reginald_distinguished_male_27 | 27 — Reginald — Distinguished Male | English |
iris_hushed_female_28 | 28 — Iris — Hushed Female | English |
marcus_smooth_male_29 | 29 — Marcus — Smooth Male | English |
serena_gentle_female_30 | 30 — Serena — Gentle Female | English |
julian_dreamy_male_31 | 31 — Julian — Dreamy Male | English |
eleanor_somber_female_32 | 32 — Eleanor — Somber Female | English |
otis_rumbling_male_33 | 33 — Otis — Rumbling Male | English |
vincent_hushed_male_34 | 34 — Vincent — Hushed Male | English |
martha_weathered_female_35 | 35 — Martha — Weathered Female | English |
sable_whispering_female_36 | 36 — Sable — Whispering Female | English |
victoria_regal_female_37 | 37 — Victoria — Regal Female | English |
arabic_38 | 38 — Arabic (العربية) | Arabic |
german_39 | 39 — German (Deutsch) | German |
english_40 | 40 — English | English |
spanish_41 | 41 — Spanish (Español) | Spanish |
french_42 | 42 — French (Français) | French |
italian_43 | 43 — Italian (Italiano) | Italian |
portuguese_44 | 44 — Portuguese (Português) | Portuguese |
russian_45 | 45 — Russian (Русский) | Russian |
chinese_simplified_46 | 46 — Chinese (Simplified) (简体中文) | Simplified Chinese |
hindi_47 | 47 — Hindi (हिन्दी) | Hindi |
Voices 01–37 speak English. Voices 38–47 each speak the language in
their name; select the language by selecting the voice. See
Language coverage.
Voice IDs use only letters, digits, and underscores, so they need no encoding in a URL, such as the input-streaming WebSocket query.
KittenTTS 0.8 voices
The three KittenTTS 0.8 models (kitten-tts-nano-0.8, kitten-tts-micro-0.8,
and kitten-tts-mini-0.8) share a fixed catalog of eight English voices. This
endpoint does not list them; send the value from this table as voice. Voice
values are case-sensitive, and the default is Bella.
| Voice | Character |
|---|---|
Bella | Warm and expressive |
Jasper | Clear and conversational |
Luna | Calm and smooth |
Bruno | Deep and steady |
Rosie | Bright and friendly |
Hugo | Authoritative |
Kiki | Lively and energetic |
Leo | Relaxed and natural |
A KittenTTS 0.8 voice is not accepted by Kitten TTS 2, and a Kitten TTS 2 voice is not accepted by a 0.8 model.
Saved-voice pagination
All 47 built-ins are returned on every successful page. limit controls only
the number of caller-owned saved voices and accepts 1–100. When has_more is
true, send last_custom_id as after:
curl -L --fail-with-body -sS \
'https://api.kittenml.com/v1/voices?model=kitten-tts-2-latest&limit=25&after=voice_0123456789abcdef0123456789abcdef' \
-H "Authorization: Bearer $KITTENML_API_KEY"
after must name a saved voice the caller owns. An unknown, revoked, or
foreign ID is rejected with 404 voice_not_found and param: "after" rather
than being treated as an empty page, so read the cursor from a previous
response's last_custom_id instead of constructing it.
The endpoint requires a durable organization or registered legacy API key
because its response can contain private saved-voice IDs. Another
organization cannot list your voices.
GET /v1/audio/voices is not a listing route and answers 405.
Create and revoke saved voices using the endpoints in Clone a voice. Runnable Python and JavaScript clients are available in the voice-listing TTS examples.