> ## Documentation Index
> Fetch the complete documentation index at: https://assemblyai.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Model selection

The `speech_models` parameter lets you specify which model(s) to use for transcription. If omitted, it defaults to `["universal-3-pro", "universal-2"]`. With this default, `universal-3-pro` handles its 6 supported languages; for all other languages, the request will automatically fall back to `universal-2`.

## Available models

<Tabs>
  <Tab language="python-sdk" title="Python SDK">
    | Name                                                                  | Parameter                             | Description                                                                                                                                                       | Best for                                                                                                                               |
    | --------------------------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
    | **Universal-3.5 Pro** <span class="preview-pill">Preview</span>       | `speech_models=['universal-3-5-pro']` | (Preview) Latest flagship model, 18 language support, native code switching, and contextual prompting. See details [here](/pre-recorded-audio/universal-3-5-pro). | Early access to the next-gen pre-recorded model.                                                                                       |
    | **Universal-3 Pro** <span class="recommended-pill">Recommended</span> | `speech_models=['universal-3-pro']`   | Our highest accuracy, fastest model. Works great out of the box, with optional prompting for more control.                                                        | Highest-accuracy transcription, post-call analytics, meeting notetakers, medical transcription, domain-specific accuracy via prompting |
    | **Universal-2**                                                       | `speech_models=['universal-2']`       | Our accurate, cost-effective model with support across 99 languages.                                                                                              | High-volume batch transcription, 99-language coverage, price-sensitive workloads, fallback for unsupported U3 Pro languages            |
  </Tab>

  <Tab language="javascript-sdk" title="JavaScript SDK">
    | Name                                                                  | Parameter                              | Description                                                                                                                                                       | Best for                                                                                                                               |
    | --------------------------------------------------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
    | **Universal-3.5 Pro** <span class="preview-pill">Preview</span>       | `speech_models: ['universal-3-5-pro']` | (Preview) Latest flagship model, 18 language support, native code switching, and contextual prompting. See details [here](/pre-recorded-audio/universal-3-5-pro). | Early access to the next-gen pre-recorded model.                                                                                       |
    | **Universal-3 Pro** <span class="recommended-pill">Recommended</span> | `speech_models: ['universal-3-pro']`   | Our highest accuracy, fastest model. Works great out of the box, with optional prompting for more control.                                                        | Highest-accuracy transcription, post-call analytics, meeting notetakers, medical transcription, domain-specific accuracy via prompting |
    | **Universal-2**                                                       | `speech_models: ['universal-2']`       | Our accurate, cost-effective model with support across 99 languages.                                                                                              | High-volume batch transcription, 99-language coverage, price-sensitive workloads, fallback for unsupported U3 Pro languages            |
  </Tab>

  <Tab language="api" title="API">
    | Name                                                                  | API Parameter                            | Description                                                                                                                                                       | Best for                                                                                                                               |
    | --------------------------------------------------------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
    | **Universal-3.5 Pro** <span class="preview-pill">Preview</span>       | `"speech_models": ["universal-3-5-pro"]` | (Preview) Latest flagship model, 18 language support, native code switching, and contextual prompting. See details [here](/pre-recorded-audio/universal-3-5-pro). | Early access to the next-gen pre-recorded model.                                                                                       |
    | **Universal-3 Pro** <span class="recommended-pill">Recommended</span> | `"speech_models": ["universal-3-pro"]`   | Our highest accuracy, fastest model. Works great out of the box, with optional prompting for more control.                                                        | Highest-accuracy transcription, post-call analytics, meeting notetakers, medical transcription, domain-specific accuracy via prompting |
    | **Universal-2**                                                       | `"speech_models":["universal-2"]`        | Our accurate, cost-effective model with support across 99 languages.                                                                                              | High-volume batch transcription, 99-language coverage, price-sensitive workloads, fallback for unsupported U3 Pro languages            |
  </Tab>
</Tabs>

## Set the model

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    You can change the model by setting the `speech_models` in the POST request body:

    ```python highlight={12}  expandable theme={null}
    import requests
    import time

    base_url = "https://api.assemblyai.com"

    headers = {
        "authorization": "<YOUR_API_KEY>"
    }

    data = {
        "audio_url": "https://assembly.ai/wildfires.mp3",
        "speech_models": ["universal-3-pro", "universal-2"],
        "language_detection": True
    }

    url = base_url + "/v2/transcript"
    response = requests.post(url, json=data, headers=headers)

    transcript_id = response.json()['id']
    polling_endpoint = base_url + "/v2/transcript/" + transcript_id

    while True:
      transcription_result = requests.get(polling_endpoint, headers=headers).json()

      if transcription_result['status'] == 'completed':
        print(transcription_result['text'])
        break

      elif transcription_result['status'] == 'error':
        raise RuntimeError(f"Transcription failed: {transcription_result['error']}")

      else:
        time.sleep(3)

    ```
  </Tab>

  <Tab language="python-sdk" title="Python SDK">
    You can change the model by setting `speech_models` in the transcription config:

    ```python highlight={8}  theme={null}
    import assemblyai as aai

    aai.settings.api_key = "<YOUR_API_KEY>"

    audio_file = "https://assembly.ai/wildfires.mp3"

    config = aai.TranscriptionConfig(
        speech_models=["universal-3-pro", "universal-2"],
        language_detection=True
    )
    transcript = aai.Transcriber(config=config).transcribe(audio_file)

    if transcript.status == aai.TranscriptStatus.error:
      raise RuntimeError(f"Transcription failed: {transcript.error}")

    print(transcript.text)
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    You can change the model by setting the `speech_models` in the POST request body:

    ```javascript highlight={12}  expandable theme={null}
    const baseUrl = "https://api.assemblyai.com";

    const headers = {
      authorization: "<YOUR_API_KEY>",
    };

    const data = {
      audio_url: "https://assembly.ai/wildfires.mp3",
      speech_models: ["universal-3-pro", "universal-2"],
      language_detection: true,
    };

    const url = `${baseUrl}/v2/transcript`;
    let res = await fetch(url, {
      method: "POST",
      headers: { ...headers, "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    if (!res.ok) throw new Error(`Error: ${res.status}`);
    const response = await res.json();

    const transcriptId = response.id;
    const pollingEndpoint = `${baseUrl}/v2/transcript/${transcriptId}`;

    while (true) {
      res = await fetch(pollingEndpoint, { headers });
      if (!res.ok) throw new Error(`Error: ${res.status}`);
      const transcriptionResult = await res.json();

      if (transcriptionResult.status === "completed") {
        console.log(transcriptionResult.text);
        break;
      } else if (transcriptionResult.status === "error") {
        throw new Error(`Transcription failed: ${transcriptionResult.error}`);
      } else {
        await new Promise((resolve) => setTimeout(resolve, 3000));
      }
    }
    ```
  </Tab>

  <Tab language="javascript-sdk" title="JavaScript SDK">
    You can change the model by setting the `speech_models` in the transcript parameters:

    ```javascript highlight={12}  expandable theme={null}
    import { AssemblyAI } from "assemblyai";

    const client = new AssemblyAI({
      apiKey: "<YOUR_API_KEY>",
    });

    const audioFile = "https://assembly.ai/wildfires.mp3";

    const params = {
      audio: audioFile,
      speech_models: ["universal-3-pro", "universal-2"],
      language_detection: true,
    };

    const run = async () => {
      const transcript = await client.transcripts.transcribe(params);

      if (transcript.status === "error") {
        throw new Error(`Transcription failed: ${transcript.error}`);
      }

      console.log(transcript.text);
    };

    run();
    ```
  </Tab>
</Tabs>

## Identify the model used

After transcription completes, you can check which model was actually used to process your request by reading the `speech_model_used` field. This is useful when you provide multiple models in the `speech_models` array, as the system may fall back to a different model depending on language support.

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    ```python expandable theme={null}
    import requests
    import time

    base_url = "https://api.assemblyai.com"

    headers = {
        "authorization": "<YOUR_API_KEY>"
    }

    data = {
        "audio_url": "https://assembly.ai/wildfires.mp3",
        "speech_models": ["universal-3-pro", "universal-2"],
        "language_detection": True
    }

    url = base_url + "/v2/transcript"
    response = requests.post(url, json=data, headers=headers)

    transcript_id = response.json()['id']
    polling_endpoint = base_url + "/v2/transcript/" + transcript_id

    while True:
      transcription_result = requests.get(polling_endpoint, headers=headers).json()

      if transcription_result['status'] == 'completed':
        print(f"Model used: {transcription_result['speech_model_used']}")
        print(transcription_result['text'])
        break

      elif transcription_result['status'] == 'error':
        raise RuntimeError(f"Transcription failed: {transcription_result['error']}")

      else:
        time.sleep(3)
    ```
  </Tab>

  <Tab language="python-sdk" title="Python SDK">
    ```python theme={null}
    import assemblyai as aai

    aai.settings.api_key = "<YOUR_API_KEY>"

    audio_file = "https://assembly.ai/wildfires.mp3"

    config = aai.TranscriptionConfig(
        speech_models=["universal-3-pro", "universal-2"],
        language_detection=True
    )
    transcript = aai.Transcriber(config=config).transcribe(audio_file)

    if transcript.status == aai.TranscriptStatus.error:
        raise RuntimeError(f"Transcription failed: {transcript.error}")

    print(f"Model used: {transcript.json_response['speech_model_used']}")
    print(transcript.text)
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    ```javascript expandable theme={null}
    const baseUrl = "https://api.assemblyai.com";

    const headers = {
      authorization: "<YOUR_API_KEY>",
    };

    const data = {
      audio_url: "https://assembly.ai/wildfires.mp3",
      speech_models: ["universal-3-pro", "universal-2"],
      language_detection: true,
    };

    const url = `${baseUrl}/v2/transcript`;
    let res = await fetch(url, {
      method: "POST",
      headers: { ...headers, "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    if (!res.ok) throw new Error(`Error: ${res.status}`);
    const response = await res.json();

    const transcriptId = response.id;
    const pollingEndpoint = `${baseUrl}/v2/transcript/${transcriptId}`;

    while (true) {
      res = await fetch(pollingEndpoint, { headers });
      if (!res.ok) throw new Error(`Error: ${res.status}`);
      const transcriptionResult = await res.json();

      if (transcriptionResult.status === "completed") {
        console.log(`Model used: ${transcriptionResult.speech_model_used}`);
        console.log(transcriptionResult.text);
        break;
      } else if (transcriptionResult.status === "error") {
        throw new Error(`Transcription failed: ${transcriptionResult.error}`);
      } else {
        await new Promise((resolve) => setTimeout(resolve, 3000));
      }
    }
    ```
  </Tab>

  <Tab language="javascript-sdk" title="JavaScript SDK">
    ```javascript expandable theme={null}
    import { AssemblyAI } from "assemblyai";

    const client = new AssemblyAI({
      apiKey: "<YOUR_API_KEY>",
    });

    const audioFile = "https://assembly.ai/wildfires.mp3";

    const params = {
      audio: audioFile,
      speech_models: ["universal-3-pro", "universal-2"],
      language_detection: true,
    };

    const run = async () => {
      const transcript = await client.transcripts.transcribe(params);

      if (transcript.status === "error") {
        throw new Error(`Transcription failed: ${transcript.error}`);
      }

      console.log(`Model used: ${transcript.speech_model_used}`);
      console.log(transcript.text);
    };

    run();
    ```
  </Tab>
</Tabs>

## Complete example

Here is the full working code that demonstrates model selection with error handling:

<Tabs groupId="language">
  <Tab language="python" title="Python" default>
    ```python expandable theme={null}
    import requests
    import time

    base_url = "https://api.assemblyai.com"
    headers = {"authorization": "<YOUR_API_KEY>"}

    data = {
        "audio_url": "https://assembly.ai/wildfires.mp3",
        "speech_models": ["universal-3-pro", "universal-2"],
        "language_detection": True
    }

    response = requests.post(base_url + "/v2/transcript", headers=headers, json=data)

    if response.status_code != 200:
        print(f"Error: {response.status_code}, Response: {response.text}")
        response.raise_for_status()

    transcript_json = response.json()
    transcript_id = transcript_json["id"]
    polling_endpoint = f"{base_url}/v2/transcript/{transcript_id}"

    while True:
        transcript = requests.get(polling_endpoint, headers=headers).json()
        if transcript["status"] == "completed":
            print(f"Model used: {transcript['speech_model_used']}")
            print(f"\nTranscript:\n\n{transcript['text']}")
            break
        elif transcript["status"] == "error":
            raise RuntimeError(f"Transcription failed: {transcript['error']}")
        else:
            time.sleep(3)
    ```
  </Tab>

  <Tab language="python-sdk" title="Python SDK">
    ```python theme={null}
    import assemblyai as aai

    aai.settings.api_key = "<YOUR_API_KEY>"

    audio_file = "https://assembly.ai/wildfires.mp3"

    config = aai.TranscriptionConfig(
        speech_models=["universal-3-pro", "universal-2"],
        language_detection=True,
    )

    transcript = aai.Transcriber(config=config).transcribe(audio_file)

    if transcript.status == aai.TranscriptStatus.error:
        raise RuntimeError(f"Transcription failed: {transcript.error}")

    print(f"Model used: {transcript.json_response['speech_model_used']}")
    print(f"\nTranscript:\n\n{transcript.text}")
    ```
  </Tab>

  <Tab language="javascript" title="JavaScript">
    ```javascript expandable theme={null}
    const baseUrl = "https://api.assemblyai.com";

    const headers = {
      authorization: "<YOUR_API_KEY>",
    };

    async function transcribe() {
      const audioFile = "https://assembly.ai/wildfires.mp3";

      const data = {
        audio_url: audioFile,
        speech_models: ["universal-3-pro", "universal-2"],
        language_detection: true,
      };

      let res = await fetch(`${baseUrl}/v2/transcript`, {
        method: "POST",
        headers: { ...headers, "Content-Type": "application/json" },
        body: JSON.stringify(data),
      });
      if (!res.ok) throw new Error(`Error: ${res.status}`);
      const transcriptResponse = await res.json();
      const transcriptId = transcriptResponse.id;
      const pollingEndpoint = `${baseUrl}/v2/transcript/${transcriptId}`;

      while (true) {
        res = await fetch(pollingEndpoint, { headers });
        if (!res.ok) throw new Error(`Error: ${res.status}`);
        const transcript = await res.json();

        if (transcript.status === "completed") {
          console.log(`Model used: ${transcript.speech_model_used}`);
          console.log(`\nTranscript:\n\n${transcript.text}`);
          break;
        } else if (transcript.status === "error") {
          throw new Error(`Transcription failed: ${transcript.error}`);
        } else {
          await new Promise((resolve) => setTimeout(resolve, 3000));
        }
      }
    }

    transcribe();
    ```
  </Tab>

  <Tab language="javascript-sdk" title="JavaScript SDK">
    ```javascript expandable theme={null}
    import { AssemblyAI } from "assemblyai";

    const client = new AssemblyAI({
      apiKey: "<YOUR_API_KEY>",
    });

    const audioFile = "https://assembly.ai/wildfires.mp3";

    const params = {
      audio: audioFile,
      speech_models: ["universal-3-pro", "universal-2"],
      language_detection: true,
    };

    const run = async () => {
      const transcript = await client.transcripts.transcribe(params);

      if (transcript.status === "error") {
        throw new Error(`Transcription failed: ${transcript.error}`);
      }

      console.log(`Model used: ${transcript.speech_model_used}`);
      console.log(`\nTranscript:\n\n${transcript.text}`);
    };

    run();
    ```
  </Tab>
</Tabs>
