> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://developers.deepgram.com/docs/audio-keep-alive/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.deepgram.com/_mcp/server. # Audio Keep Alive Streaming:Nova Use the `KeepAlive` message to keep your WebSocket connection open during periods of silence, preventing timeouts and optimizing costs. ## Purpose Send a `KeepAlive` message every 3-5 seconds to prevent the 10-second timeout that triggers a `NET-0001` error and closes the connection. Ensure the message is sent as a text WebSocket frame—sending it as binary may result in incorrect handling and potential connection issues. ## Example Payloads To send the `KeepAlive` message, send the following JSON message to the server: **`JSON`** ```json JSON { "type": "KeepAlive" } ``` The server will not send a response back when you send a `KeepAlive` message. If no audio data or `KeepAlive` messages are sent within a 10-second window, the connection will close with a `NET-0001` error. ## Language Specific Implementations Below are code examples to help you get started using `KeepAlive`. ### Sending a `KeepAlive` message in JSON Format Construct a JSON message containing the `KeepAlive` type and send it over the WebSocket connection in each respective language. **`JavaScript`** ```javascript JavaScript const WebSocket = require("ws"); // Assuming 'headers' is already defined for authorization const ws = new WebSocket("wss://api.deepgram.com/v1/listen", { headers }); // Assuming 'ws' is the WebSocket connection object const keepAliveMsg = JSON.stringify({ type: "KeepAlive" }); ws.send(keepAliveMsg); ``` **`Python`** ```python Python import json import websocket # Assuming 'headers' is already defined for authorization ws = websocket.create_connection("wss://api.deepgram.com/v1/listen", header=headers) # Assuming 'ws' is the WebSocket connection object keep_alive_msg = json.dumps({"type": "KeepAlive"}) ws.send(keep_alive_msg) ``` **`Go`** ```go Go package main import ( "encoding/json" "log" "net/http" "github.com/gorilla/websocket" ) func main() { // Define headers for authorization headers := http.Header{} // Assuming headers are set here for authorization conn, _, err := websocket.DefaultDialer.Dial("wss://api.deepgram.com/v1/listen", headers) if err != nil { log.Fatal("Error connecting to WebSocket:", err) } defer conn.Close() // Construct KeepAlive message keepAliveMsg := map[string]string{"type": "KeepAlive"} jsonMsg, err := json.Marshal(keepAliveMsg) if err != nil { log.Fatal("Error encoding JSON:", err) } // Send KeepAlive message err = conn.WriteMessage(websocket.TextMessage, jsonMsg) if err != nil { log.Fatal("Error sending KeepAlive message:", err) } } ``` **`C#`** ```csharp C# using System; using System.Net.WebSockets; using System.Text; using System.Threading; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { // Set up the WebSocket URL and headers Uri uri = new Uri("wss://api.deepgram.com/v1/listen"); string apiKey = "DEEPGRAM_API_KEY"; // Create a new client WebSocket instance using (ClientWebSocket ws = new ClientWebSocket()) { // Set the authorization header ws.Options.SetRequestHeader("Authorization", "Token " + apiKey); // Connect to the WebSocket server await ws.ConnectAsync(uri, CancellationToken.None); // Construct the KeepAlive message string keepAliveMsg = "{\"type\": \"KeepAlive\"}"; // Convert the KeepAlive message to a byte array byte[] keepAliveBytes = Encoding.UTF8.GetBytes(keepAliveMsg); // Send the KeepAlive message asynchronously await ws.SendAsync(new ArraySegment(keepAliveBytes), WebSocketMessageType.Text, true, CancellationToken.None); } } } ``` **`Java`** ```java Java import java.net.URI; import java.net.http.HttpClient; import java.net.http.WebSocket; import java.util.concurrent.CompletableFuture; // Assuming 'ws' is the WebSocket connection object HttpClient client = HttpClient.newHttpClient(); WebSocket ws = client.newWebSocketBuilder() .header("Authorization", "Token DEEPGRAM_API_KEY") .buildAsync(URI.create("wss://api.deepgram.com/v1/listen"), new WebSocket.Listener() {}) .join(); // Send KeepAlive message as a text frame ws.sendText("{\"type\": \"KeepAlive\"}", true); ``` ### Streaming Examples Make a streaming request and use `KeepAlive` to keep the connection open. **`JavaScript`** ```javascript JavaScript const WebSocket = require("ws"); const authToken = "DEEPGRAM_API_KEY"; // Replace 'DEEPGRAM_API_KEY' with your actual authorization token const headers = { Authorization: `Token ${authToken}`, }; // Initialize WebSocket connection const ws = new WebSocket("wss://api.deepgram.com/v1/listen", { headers }); // Handle WebSocket connection open event ws.on("open", function open() { console.log("WebSocket connection established."); // Send audio data (replace this with your audio streaming logic) // Example: Read audio from a microphone and send it over the WebSocket // For demonstration purposes, we're just sending a KeepAlive message setInterval(() => { const keepAliveMsg = JSON.stringify({ type: "KeepAlive" }); ws.send(keepAliveMsg); console.log("Sent KeepAlive message"); }, 3000); // Sending KeepAlive messages every 3 seconds }); // Handle WebSocket message event ws.on("message", function incoming(data) { console.log("Received:", data); // Handle received data (transcription results, errors, etc.) }); // Handle WebSocket close event ws.on("close", function close() { console.log("WebSocket connection closed."); }); // Handle WebSocket error event ws.on("error", function error(err) { console.error("WebSocket error:", err.message); }); // Gracefully close the WebSocket connection when done function closeWebSocket() { const closeMsg = JSON.stringify({ type: "CloseStream" }); ws.send(closeMsg); } // Call closeWebSocket function when you're finished streaming audio // For example, when user stops recording or when the application exits // closeWebSocket(); ``` **`Python`** ```python Python import websocket import json import time import threading auth_token = "DEEPGRAM_API_KEY" # Replace 'DEEPGRAM_API_KEY' with your actual authorization token headers = { "Authorization": f"Token {auth_token}" } # WebSocket URL ws_url = "wss://api.deepgram.com/v1/listen" # Define the WebSocket on_open function def on_open(ws): print("WebSocket connection established.") # Send KeepAlive messages every 3 seconds def keep_alive(): while True: keep_alive_msg = json.dumps({"type": "KeepAlive"}) ws.send(keep_alive_msg) print("Sent KeepAlive message") time.sleep(3) # Start a thread for sending KeepAlive messages keep_alive_thread = threading.Thread(target=keep_alive) keep_alive_thread.daemon = True keep_alive_thread.start() # Define the WebSocket on_message function def on_message(ws, message): print("Received:", message) # Handle received data (transcription results, errors, etc.) # Define the WebSocket on_close function def on_close(ws): print("WebSocket connection closed.") # Define the WebSocket on_error function def on_error(ws, error): print("WebSocket error:", error) # Create WebSocket connection ws = websocket.WebSocketApp(ws_url, on_open=on_open, on_message=on_message, on_close=on_close, on_error=on_error, header=headers) # Run the WebSocket ws.run_forever() ``` ## Using Deepgram SDKs Deepgram's SDKs make it easier to build with Deepgram in your preferred language. For more information on using Deepgram SDKs, refer to the SDKs documentation in the GitHub Repository. * [JS SDK](https://github.com/deepgram/deepgram-js-sdk) * [Python SDK](https://github.com/deepgram/deepgram-python-sdk) * [Go SDK](https://github.com/deepgram/deepgram-go-sdk) * [.NET SDK](https://github.com/deepgram/deepgram-dotnet-sdk) **`JavaScript`** ```javascript JavaScript const { DeepgramClient } = require("@deepgram/sdk"); const live = async () => { const deepgram = new DeepgramClient({ apiKey: "DEEPGRAM_API_KEY" }); let connection; let keepAlive; const setupDeepgram = async () => { connection = await deepgram.listen.v1.connect({ model: "nova-3", utterance_end_ms: "1500", interim_results: "true", }); if (keepAlive) clearInterval(keepAlive); keepAlive = setInterval(() => { console.log("KeepAlive sent."); connection.sendKeepAlive({ type: "KeepAlive" }); }, 3000); // Sending KeepAlive messages every 3 seconds connection.on("open", () => { console.log("Connection opened."); }); connection.on("close", () => { console.log("Connection closed."); clearInterval(keepAlive); }); connection.on("message", (data) => { if (data.type === "Metadata") { console.log(data); } else if (data.type === "Results") { console.log(data.channel); } else if (data.type === "UtteranceEnd") { console.log(data); } else if (data.type === "SpeechStarted") { console.log(data); } }); connection.on("error", (err) => { console.error(err); }); connection.connect(); await connection.waitForOpen(); }; setupDeepgram(); }; live(); ``` **`Python`** ```python Python # For more Python SDK migration guides, visit: # https://github.com/deepgram/deepgram-python-sdk/tree/main/docs import os from deepgram import DeepgramClient from deepgram.core.events import EventType API_KEY = os.getenv("DEEPGRAM_API_KEY") def main(): try: deepgram = DeepgramClient( api_key=API_KEY, config={"keepalive": "true"} # Comment this out to see the effect of not using keepalive ) with deepgram.listen.websocket.v('1').stream( model="nova-3", language="en-US", smart_format=True, ) as dg_connection: def on_message(result): if hasattr(result, 'channel') and result.channel.alternatives: sentence = result.channel.alternatives[0].transcript if len(sentence) == 0: return print(f"speaker: {sentence}") def on_metadata(result): print(f"\n\n{result}\n\n") def on_error(error): print(f"\n\n{error}\n\n") dg_connection.on(EventType.MESSAGE, on_message) dg_connection.on(EventType.METADATA, on_metadata) dg_connection.on(EventType.ERROR, on_error) dg_connection.start_listening() except Exception as e: print(f"Could not open socket: {e}") if __name__ == "__main__": main() ``` **`Go`** ```go Go package main import ( "bufio" "context" "fmt" "os" interfaces "github.com/deepgram/deepgram-go-sdk/pkg/client/interfaces" client "github.com/deepgram/deepgram-go-sdk/pkg/client/live" ) func main() { // init library client.InitWithDefault() // Go context ctx := context.Background() // set the Transcription options tOptions := interfaces.LiveTranscriptionOptions{ Model="nova-3", Language: "en-US", Punctuate: true, } // create a Deepgram client cOptions := interfaces.ClientOptions{ EnableKeepAlive: true, // Comment this out to see the effect of not using keepalive } // use the default callback handler which just dumps all messages to the screen dgClient, err := client.New(ctx, "", cOptions, tOptions, nil) if err != nil { fmt.Println("ERROR creating LiveClient connection:", err) return } // connect the websocket to Deepgram wsconn := dgClient.Connect() if wsconn == nil { fmt.Println("Client.Connect failed") os.Exit(1) } // wait for user input to exit fmt.Printf("This demonstrates using KeepAlives. Press ENTER to exit...\n") input := bufio.NewScanner(os.Stdin) input.Scan() // close client dgClient.Stop() fmt.Printf("Program exiting...\n") } ``` **`Java`** ```java Java import com.deepgram.DeepgramClient; import com.deepgram.resources.listen.v1.websocket.V1WebSocketClient; import com.deepgram.resources.listen.v1.types.ListenV1KeepAlive; import com.deepgram.resources.listen.v1.types.ListenV1KeepAliveType; import com.deepgram.resources.listen.v1.websocket.V1ConnectOptions; import java.util.concurrent.*; DeepgramClient deepgram = DeepgramClient.builder().build(); V1ConnectOptions options = V1ConnectOptions.builder() .model("nova-3") .language("en-US") .smartFormat(true) .build(); V1WebSocketClient wsClient = deepgram.listen().v1().v1WebSocket(); wsClient.connect(options).get(10, TimeUnit.SECONDS); wsClient.onResults(result -> System.out.println("Received: " + result)); // Send KeepAlive messages every 3 seconds ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(() -> { wsClient.sendKeepAlive(ListenV1KeepAlive.builder() .type(ListenV1KeepAliveType.KEEP_ALIVE) .build()); System.out.println("KeepAlive sent."); }, 3, 3, TimeUnit.SECONDS); ``` ## Word Timings Word timings in streaming transcription results are based on the audio stream itself, not the lifetime of the WebSocket connection. If you send KeepAlive messages without any audio payloads for a period of time, then resume sending audio, the timestamps will continue from where the audio left off—not from when the KeepAlive messages were sent. Here is an example timeline demonstrating the behavior. | Event | Wall Time | Word Timing Range on Results Response | | ---------------------------------------------------------------- | ---------- | ------------------------------------- | | Websocket opened, begin sending audio payloads | 0 seconds | 0 seconds | | Results received | 5 seconds | 0-5 seconds | | Results received | 10 seconds | 5-10 seconds | | Pause sending audio payloads, while sending `KeepAlive` messages | 10 seconds | *n/a* | | Resume sending audio payloads | 30 seconds | *n/a* | | Results received | 35 seconds | 10-15 seconds | --- > Send keep alive messages while streaming audio to keep the connection open.