cd /news/ai-tools/build-a-text-to-speech-app-with-elev… · home › topics › ai-tools › article
[ARTICLE · art-154822] src=dev.to ↗ pub= topic=ai-tools verified=true sentiment=↑ positive

Build a Text-to-Speech App with ElevenLabs and Python

A developer published a Python walkthrough for building a text-to-speech app on ElevenLabs' API, using an async httpx client to POST text to the /text-to-speech/{voice_id} endpoint and save the returned MP3, then playing it back with pydub. The guide sets model_id to eleven_monolingual_v1 and exposes stability and similarity_boost voice settings, and notes ElevenLabs' voice cloning via the /voices/add endpoint.

by read5 min views3 publishedOct 21, 2026

If you’ve ever built a chatbot, an accessibility feature, or a voice‑enabled game, you know that a natural‑sounding voice can turn a static experience into something engaging and human‑like. Modern TTS engines are no longer limited to robotic monotones – they can capture emotion, intonation, and even mimic a specific speaker’s style.

That’s where ElevenLabs shines. Their API delivers high‑quality neural voices that are easy to integrate, and the pricing model works well for both hobby projects and production apps. In this post we’ll walk through building a simple Python app that sends text to ElevenLabs, receives an audio file, and plays it back. By the end you’ll have a reusable script you can drop into any project.

What you need Why
Python 3.8+ The example uses f‑strings and asyncio .
pip To install the required packages.
ElevenLabs API key You’ll need an account; sign up via the affiliate link: https://try.elevenlabs.io/kr07zfuqn1bp
A speaker or headphones To hear the generated audio.

Keep this token secret – treat it like a password.

pip install httpx python-dotenv pydub

.env file. ffmpeg installed on your system; on macOS you can use brew install ffmpeg, on Ubuntu sudo apt-get install ffmpeg.) Create a .env file in your project root:

ELEVENLABS_API_KEY=your_api_key_here

Below is a minimal async function that talks to ElevenLabs. It accepts the text you want spoken, the voice ID (we’ll use the default “Rachel” for now), and returns the path to a saved MP3 file.

import os
import httpx
from pathlib import Path
from dotenv import load_dotenv

load_dotenv()
API_KEY = os.getenv("ELEVENLABS_API_KEY")
BASE_URL = "https://api.elevenlabs.io/v1"

async def synthesize(
    text: str,
    voice_id: str = "EXAVITQu4vr4xnSDxMaL",  # default voice (Rachel)
    output_path: Path = Path("output.mp3"),
) -> Path:
    url = f"{BASE_URL}/text-to-speech/{voice_id}"
    headers = {
        "xi-api-key": API_KEY,
        "Content-Type": "application/json",
    }
    payload = {
        "text": text,
        "model_id": "eleven_monolingual_v1",
        "voice_settings": {
            "stability": 0.75,
            "similarity_boost": 0.75,
        },
    }

    async with httpx.AsyncClient(timeout=30.0) as client:
        response = await client.post(url, json=payload, headers=headers)

    response.raise_for_status()
    output_path.write_bytes(response.content)
    return output_path

What’s happening?

/text-to-speech/{voice_id}. model_id selects the neural model; eleven_monolingual_v1 is the most balanced for English. stability and similarity_boost let you tweak how consistent the voice sounds vs. how expressive it is. Feel free to experiment – a higher stability makes the voice more monotone, while a higher similarity_boost pushes it toward the reference voice.

from pydub import AudioSegment
from pydub.playback import play

def play_audio(file_path: Path):
    audio = AudioSegment.from_file(file_path, format="mp3")
    play(audio)
python
import asyncio
from pathlib import Path

async def main():
    text = (
        "Hello, fellow developer! "
        "With ElevenLabs, you can turn any string into a natural‑sounding voice."
    )
    output_file = Path("speech.mp3")

    print("Generating speech…")
    await synthesize(text, output_path=output_file)
    print(f"Saved to {output_file}")

    print("Playing back…")
    play_audio(output_file)

if __name__ == "__main__":
    asyncio.run(main())

Run the script:

python tts_demo.py

You should hear the phrase spoken in a clear, human‑like voice. 🎉

ElevenLabs also offers voice cloning – you can upload a few minutes of a speaker’s recordings and generate a custom voice ID. The workflow is:

/voices/add endpoint (or via the web UI). voice_id once the model is ready. synthesize function above. Here’s a quick curl example for up a sample (replace YOUR_API_KEY and sample.wav with your values):

curl -X POST "https://api.elevenlabs.io/v1/voices/add" \
  -H "xi-api-key: YOUR_API_KEY" \
  -F "name=MyCustomVoice" \
  -F "files[]=@sample.wav"

The response contains:

{
  "voice_id": "abc123def456",
  "name": "MyCustomVoice",
  "preview_url": "https://..."
}

Now just pass "abc123def456" as the voice_id to synthesize and you’ll hear your voice reading the text. This is a game‑changer for personalized assistants, audiobooks, and dubbing.

ElevenLabs enforces a per‑minute request quota based on your plan. If you exceed it, you’ll receive a 429 Too Many Requests response. A simple retry strategy can keep your app smooth:

import time

async def safe_synthesize(*args, **kwargs):
    retries = 3
    backoff = 2
    for attempt in range(retries):
        try:
            return await synthesize(*args, **kwargs)
        except httpx.HTTPStatusError as exc:
            if exc.response.status_code == 429 and attempt < retries - 1:
                wait = backoff ** attempt
                print(f"Rate limited, sleeping {wait}s…")
                time.sleep(wait)
                continue
            raise

Wrap your calls with await safe_synthesize(...) to automatically back‑off on throttling.

If you want to expose this TTS capability as a micro‑service, Flask or FastAPI work nicely:

from fastapi import FastAPI, Body
from fastapi.responses import FileResponse

app = FastAPI()

@app.post("/speak")
async def speak(text: str = Body(...)):
    out_file = await safe_synthesize(text)
    return FileResponse(out_file, media_type="audio/mpeg")

Deploy to Render, Fly.io, or any container platform, and you’ll have an HTTP endpoint that turns any string into speech on demand.

Tip Reason
Cache results Many apps reuse the same phrases (e.g., “Welcome back”). Store the MP3 locally to avoid unnecessary API calls.
Validate input length The free tier caps requests at 2 000 characters. Trim or split longer texts before sending.
Secure the API key Use secret management (AWS Secrets Manager, GCP Secret Manager) instead of plain .env in production.
Monitor usage ElevenLabs provides usage stats in the dashboard; set alerts if you approach your quota.

You now have a fully functional Python text‑to‑speech app powered by ElevenLabs. From a quick demo to a cloud‑hosted micro‑service or a custom voice clone, the API is flexible enough to fit most developer workflows.

Give it a spin, experiment with voice settings, and maybe even train a voice that sounds like you. The possibilities are only limited by your imagination (and the API quota).

Ready to bring natural speech to your next project? Try ElevenLabs today with the affiliate link: https://try.elevenlabs.io/kr07zfuqn1bp – you’ll get instant access to the API and a generous free tier to start building right away. Happy coding!

── more in #ai-tools 4 stories · sorted by recency
── more on @elevenlabs 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/build-a-text-to-spee…] indexed:0 read:5min 2026-10-21 · —