TwiML™ Voice: <Gather>

Speech Recognition is now Generally Available

The <Gather> verb collects digits or transcribes speech from a caller, when the caller is done entering digits or speaking, Twilio submits that data to the provided 'action' URL in an HTTP GET or POST request, just like a web browser submits data from an HTML form. Collecting speech with 'input = speech' or 'input = dtmf speech' is charged at $.02 per 15 seconds. verbs that use 'speech' have a maximum duration of 60 seconds.

If no input is received before timeout, <Gather> falls through to the next verb in the TwiML document.

You may optionally nest <Say> and <Play> verbs within a <Gather> verb while waiting for input - see "Nesting Rules" below for more info and limitations.

Verb Attributes

The <Gather> verb supports the following attributes that modify its behavior:

Attribute Name Allowed Values Default Value
input dtmf, speech, dtmf speech dtmf
action relative or absolute url current document URL
method GET, POST POST
timeout positive integer 5 seconds
finishOnKey 0-9, #, *, and '' (the empty string) #
numDigits integer >= 1 unlimited
partialResultCallback relative or absolute url none
partialResultCallbackMethod GET, POST POST
language BCP-47 language tags en-US
hints "words, phrases that have many words" none
profanityFilter true, false true
speechTimeout positive integer, auto defaults to timeout attribute

Use one or more of these attributes in a <Gather> verb like so:

Loading Code Samples...
Language
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • TwiML
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
const gather = response.gather({
  input: 'speech dtmf',
  timeout: 3,
  numDigits: 1,
});
gather.say('Please press 1 or say sales for sales.');

console.log(response.toString());
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        var gather = new Gather(input: "speech dtmf", timeout: 3, numDigits: 1);
        gather.Say("Please press 1 or say sales for sales.");
        response.Append(gather);

        Console.WriteLine(response.ToString());;
    }
}
<?php
require_once './vendor/autoload.php';
use Twilio\Twiml;

$response = new Twiml();
$gather = $response->gather(['input' => 'speech dtmf', 'timeout' => 3,
    'numDigits' => 1]);
$gather->say('Please press 1 or say sales for sales.');

echo $response;
require 'twilio-ruby'

response = Twilio::TwiML::VoiceResponse.new
response.gather(input: 'speech dtmf', timeout: 3, num_digits: 1) do |gather|
  gather.say('Please press 1 or say sales for sales.')
end

puts response
from twilio.twiml.voice_response import Gather, VoiceResponse, Say

response = VoiceResponse()
gather = Gather(input='speech dtmf', timeout=3, num_digits=1)
gather.say('Please press 1 or say sales for sales.')
response.append(gather)

print(response)
import com.twilio.twiml.Gather;
import com.twilio.twiml.VoiceResponse;
import com.twilio.twiml.Say;
import com.twilio.twiml.TwiMLException;


public class Example {
    public static void main(String[] args) {
        Say say = new Say.Builder("Please press 1 or say sales for sales.")
            .build();
        Gather gather = new Gather.Builder().input("speech dtmf").timeout(3)
            .numDigits(1).say(say).build();
        VoiceResponse response = new VoiceResponse.Builder().gather(gather)
            .build();

        try {
            System.out.println(response.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Gather input="speech dtmf" timeout="3" numDigits="1">
        <Say>Please press 1 or say sales for sales.</Say>
    </Gather>
</Response>
Gather Speech or DTMF

input

A list of inputs that Twilio should accept for <Gather>. Can be "dtmf", "speech" or "dtmf speech". Defaults to "dtmf". dtmf input takes precedence over speech, if numDigits or finishOnKey is matched the <Gather> will immediately end.

action

The 'action' attribute takes an absolute or relative URL as a value. When the caller has finished entering digits or the timeout is reached Twilio will make a GET or POST request to this URL including the parameters below. If no 'action' is provided, Twilio will by default make a POST request to the current document's URL.

If you chose to gather digits from the caller, Twilio's request to your application will include a Digits parameter containing which numbers your caller entered during the <Gather>. If you specify speech as input, Twilio's request to your application will include SpeechResult and Confidence parameters. The SpeechResult parameter will have transcribed result of the speech and Confidence parameter will have a confidence score between 0.0 and 1.0 respectively. A higher confidence score means a greater likelihood that recognized words are correct.

After making this request, Twilio will continue the current call using the TwiML received in your response. Keep in mind that by default Twilio will re-request the current document's URL, which can lead to unwanted looping behavior if you're not careful. Any TwiML verbs occurring after a <Gather> are unreachable, unless the caller enters no digits or speech.

If the 'timeout' is reached before the caller enters any digits, or if the caller enters the 'finishOnKey' value before entering any other digits, Twilio will not make a request to the 'action' URL but instead continue processing the current TwiML document with the verb immediately following the <Gather>.

partialResultCallback

A relative or fully qualified URL. If provided, Twilio will make requests to your partialResultCallback in real-time as speech is recognized. These webhooks will contain UnstableSpeechResult parameter with partial transcriptions that may change as the recognition progresses.

Note: The Webhooks to partialResultCallback are async and doesn't require Twiml back. If you want to act based on the partial result, then use the REST API to Live Modify the call.

language

The language Twilio should recognize as specified using a BCP-47 language tag. Defaults to en-US, full list of supported languages here

hints

A list of words or phrases, up to 100 characters each that Twilio should expect during recognition. Up to 50 may be provided. These are very useful for improving recognition of single words or phrases. Entries into hints should be separated by a comma, spaces separate words within a phrase. For example: hints="word, a phrase, another longer phrase, term, thing, proper product name".

profanityFilter

Specifies if Twilio should filter out profanities, replacing all but the initial character in each filtered word with asterisks, e.g. 'f***'. If set to false profanities won't be filtered. Defaults to true.

speechTimeout

When using speech recognition, the speechTimeout attribute sets the limit in seconds that Twilio will wait for speech before stopping the recognition and posting speechResult to actionUrl. If both timeout and speechTimeout are used, timeout will be used for DTMF input and speechTimeout will be used for speech. If only timeout attribute is provided, then it will be used for both DTMF and speech input.

You can also specify auto for speechTimeout which will automatically stop speech recognition when we detect pause in speech and return the results immediately. Using auto for speechTimeout uses a different model that is optimized for address and number recognition.

method

The 'method' attribute takes the value 'GET' or 'POST'. This tells Twilio whether to request the 'action' URL via HTTP GET or POST. This attribute is modeled after the HTML form 'method' attribute. 'POST' is the default value.

timeout

The 'timeout' attribute sets the limit in seconds that Twilio will wait for the caller to press another digit or say another word before moving on and making a request to the 'action' URL. For example, if 'timeout' is '3', Twilio will wait three seconds for the caller to press another key or say another word before submitting the previously entered digits or speech to the 'action' URL. Twilio waits until completing the execution of all nested verbs before beginning the timeout period.

finishOnKey

The 'finishOnKey' attribute lets you choose one value that submits the received data when entered. For example, if you set 'finishOnKey' to '#' and the user enters '1234#', Twilio will immediately stop waiting for more input when the '#' is received and will submit "Digits=1234" to the 'action' URL. Note that the 'finishOnKey' value is not sent. The allowed values are the digits 0-9, '#' , '*' and the empty string (set 'finishOnKey' to '').

If the empty string is used, <Gather> captures all input and no key will end the <Gather> when pressed. In this case Twilio will submit the entered digits to the 'action' URL only after the timeout has been reached. The default 'finishOnKey' value is '#'. The value can only be a single character.

numDigits

The 'numDigits' attribute lets you set the number of digits you are expecting, and submits the data to the 'action' URL once the caller enters that number of digits. For example, one might set 'numDigits' to '5' and ask the caller to enter a 5 digit zip code. When the caller enters the fifth digit of '94117', Twilio will immediately submit the data to the 'action' URL.

Note: 'numDigits' attribute only applies for DTMF input.

Nesting Rules

You can nest the following verbs within <Gather>:

But you can't nest <Gather> within any other verbs. Note, however, that you cannot <Play> DTMF tones (using the digits attribute) within a <Gather>.

Examples

Example 1: Simple Gather

This is the simplest case for a <Gather>. When Twilio executes this TwiML the application will pause for up to five seconds, waiting for the caller to enter digits on her keypad.

Loading Code Samples...
Language
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • TwiML
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
response.gather();

console.log(response.toString());
using Twilio.TwiML;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        response.Gather();

        Console.WriteLine(response.ToString());;
    }
}
<?php
require_once './vendor/autoload.php';
use Twilio\Twiml;

$response = new Twiml();
$response->gather();

echo $response;
require 'twilio-ruby'

response = Twilio::TwiML::VoiceResponse.new
response.gather

puts response
from twilio.twiml.voice_response import Gather, VoiceResponse

response = VoiceResponse()
response.gather()

print(response)
import com.twilio.twiml.Gather;
import com.twilio.twiml.VoiceResponse;
import com.twilio.twiml.TwiMLException;


public class Example {
    public static void main(String[] args) {
        Gather gather = new Gather.Builder().build();
        VoiceResponse response = new VoiceResponse.Builder().gather(gather)
            .build();

        try {
            System.out.println(response.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/simple_gather.xml -->
<Response>
    <Gather/>
</Response>
Simple Gather
  • If the caller enters digits followed by a '#' symbol, Twilio submits those Digits in a POST request back to the current URL: http://example.com/simple_gather.xml
  • If the caller enters digits followed by five seconds of silence, Twilio submits those Digits in a POST request back to the current URL: http://example.com/simple_gather.xml
  • If the caller doesn't enter any digits and five seconds passes, Twilio does not make a request to any URL, but instead moves on to the next TwiML verb. Since there are no more verbs, Twilio hangs up.

Example 2: Action/method and nested <Say> or <Play> verb

In this more complex example we add the 'action' and 'method' attributes. After the caller enters digits on the keypad, Twilio sends them in a request to the 'action' URL. We also add a nested <Say> verb. This means that input can be gathered at any time during <Say>.

Loading Code Samples...
Language
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • TwiML
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
const gather = response.gather({
    action: '/process_gather.php',
    method: 'GET'
});
gather.say('Please enter your account number,\nfollowed by the pound sign');
response.say('We didn\'t receive any input. Goodbye!');

console.log(response.toString());
using Twilio.TwiML;
using Twilio.Http;
using Twilio.TwiML.Voice;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        var gather = new Gather(action: new Uri("/process_gather.php"), method: HttpMethod.Get);
        gather
            .Say("Please enter your account number,\nfollowed by the pound sign");
        response.Append(gather);
        response.Say("We didn't receive any input. Goodbye!");

        Console.WriteLine(response.ToString());;
    }
}
<?php
require_once './vendor/autoload.php';
use Twilio\Twiml;

$response = new Twiml();
$gather = $response->gather(['action' => '/process_gather.php',
    'method' => 'GET']);
$gather->say('Please enter your account number,\nfollowed by the pound sign');
$response->say('We didn\'t receive any input. Goodbye!');

echo $response;
require 'twilio-ruby'

response = Twilio::TwiML::VoiceResponse.new
response.gather(action: '/process_gather.php', method: 'GET') do |gather|
  gather.say('Please enter your account number,\nfollowed by the pound sign')
end
response.say('We didn\'t receive any input. Goodbye!')

puts response
from twilio.twiml.voice_response import Gather, VoiceResponse, Say

response = VoiceResponse()
gather = Gather(action='/process_gather.php', method='GET')
gather.say('Please enter your account number,\nfollowed by the pound sign')
response.append(gather)
response.say('We didn\'t receive any input. Goodbye!')

print(response)
import com.twilio.twiml.Gather;
import com.twilio.twiml.VoiceResponse;
import com.twilio.twiml.Say;
import com.twilio.twiml.TwiMLException;
import com.twilio.twiml.Method;

public class Example {
    public static void main(String[] args) {
        Say say = new Say
            .Builder("Please enter your account number,\nfollowed by the pound sign").build();
        Gather gather = new Gather.Builder().action("/process_gather.php")
            .method(Method.GET).say(say).build();
        Say say2 = new Say
            .Builder("We didn't receive any input. Goodbye!").build();
        VoiceResponse response = new VoiceResponse.Builder().gather(gather)
            .say(say2).build();

        try {
            System.out.println(response.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/complex_gather.xml -->
<Response>
    <Gather action="/process_gather.php" method="GET">
        <Say>
            Please enter your account number,
            followed by the pound sign
        </Say>
    </Gather>
    <Say>We didn't receive any input. Goodbye!</Say>
</Response>
Complex Gather with Action/Method and Nested Say
<?php
// page located at http://example.com/process_gather.php
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
echo "<Response><Say>You entered " . $_REQUEST['Digits'] . "</Say></Response>";
?>
  • If the caller enters a digit during the speaking of the text, the <Say> verb will stop speaking and wait for digits, '#' sign, or a timeout.
  • If <Gather> tag times out without input, the <Say> verb will complete and the <Gather> verb will exit without submitting. Twilio will then process the next verb in the document, which in this case is a <Say> verb which informs the caller that no input was received.
  • If the caller enters 12345 and then hits # or allows five seconds to pass, Twilio will submit the digits as a GET request to http://yourserver/process_gather.php?Digits=12345.

Example 3: Speech Gather

This TwiML creates a <Gather> with speech. When Twilio executes this TwiML the application will prompt the user and accept speech for up to 60 seconds. Once the caller stops speaking for five seconds, Twilio will post her transcribed speech to the action url.

Loading Code Samples...
Language
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • TwiML
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
const gather = response.gather({
    input: 'speech',
    action: '/completed'
});
gather.say('Welcome to Twilio, please tell us why you\'re calling');

console.log(response.toString());
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        var gather = new Gather(input: "speech", action: new Uri("/completed"));
        gather.Say("Welcome to Twilio, please tell us why you're calling");
        response.Append(gather);

        Console.WriteLine(response.ToString());;
    }
}
<?php
require_once './vendor/autoload.php';
use Twilio\Twiml;

$response = new Twiml();
$gather = $response->gather(['input' => 'speech', 'action' => '/completed']);
$gather->say('Welcome to Twilio, please tell us why you\'re calling');

echo $response;
require 'twilio-ruby'

response = Twilio::TwiML::VoiceResponse.new
response.gather(input: 'speech', action: '/completed') do |gather|
  gather.say('Welcome to Twilio, please tell us why you\'re calling')
end

puts response
from twilio.twiml.voice_response import Gather, VoiceResponse, Say

response = VoiceResponse()
gather = Gather(input='speech', action='/completed')
gather.say('Welcome to Twilio, please tell us why you\'re calling')
response.append(gather)

print(response)
import com.twilio.twiml.Gather;
import com.twilio.twiml.VoiceResponse;
import com.twilio.twiml.Say;
import com.twilio.twiml.TwiMLException;


public class Example {
    public static void main(String[] args) {
        Say say = new Say
            .Builder("Welcome to Twilio, please tell us why you're calling").build();
        Gather gather = new Gather.Builder().input("speech")
            .action("/completed").say(say).build();
        VoiceResponse response = new VoiceResponse.Builder().gather(gather)
            .build();

        try {
            System.out.println(response.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/simple_gather.xml -->
<Response>
    <Gather input="speech" action="/completed">
           <Say>Welcome to Twilio, please tell us why you're calling</Say>
        </Gather>
</Response>
Speech Gather

Hints and Advanced Uses

  • When there are nested <Say> and <Play> verbs, the timeout begins after either the audio completes, or the first key is pressed.
  • When a <Gather> times out without user input, it will not submit to its action url, but will instead fall through to the next verb. If you wish to have the application submit on a timeout, use the <Redirect> verb:
Loading Code Samples...
Language
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • TwiML
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
const gather = response.gather({
    action: '/process_gather.php',
    method: 'GET'
});
gather.say('Enter something, or not');
response.redirect({
    method: 'GET'
}, '/process_gather.php?Digits=TIMEOUT');

console.log(response.toString());
using Twilio.TwiML;
using Twilio.Http;
using Twilio.TwiML.Voice;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        var gather = new Gather(action: new Uri("/process_gather.php"), method: HttpMethod.Get);
        gather.Say("Enter something, or not");
        response.Append(gather);
        response.Redirect(new Uri("/process_gather.php?Digits=TIMEOUT"), method: HttpMethod.Get);

        Console.WriteLine(response.ToString());;
    }
}
<?php
require_once './vendor/autoload.php';
use Twilio\Twiml;

$response = new Twiml();
$gather = $response->gather(['action' => '/process_gather.php',
    'method' => 'GET']);
$gather->say('Enter something, or not');
$response->redirect('/process_gather.php?Digits=TIMEOUT', ['method' => 'GET']);

echo $response;
require 'twilio-ruby'

response = Twilio::TwiML::VoiceResponse.new
response.gather(action: '/process_gather.php', method: 'GET') do |gather|
    gather.say('Enter something, or not')
end
response.redirect('/process_gather.php?Digits=TIMEOUT', method: 'GET')

puts response
from twilio.twiml.voice_response import Gather, Redirect, VoiceResponse, Say

response = VoiceResponse()
gather = Gather(action='/process_gather.php', method='GET')
gather.say('Enter something, or not')
response.append(gather)
response.redirect('/process_gather.php?Digits=TIMEOUT', method='GET')

print(response)
import com.twilio.twiml.Gather;
import com.twilio.twiml.Redirect;
import com.twilio.twiml.VoiceResponse;
import com.twilio.twiml.Say;
import com.twilio.twiml.TwiMLException;
import com.twilio.twiml.Method;

public class Example {
    public static void main(String[] args) {
        Say say = new Say.Builder("Enter something, or not").build();
        Gather gather = new Gather.Builder().action("/process_gather.php")
            .method(Method.GET).say(say).build();
        Redirect redirect = new Redirect.Builder().method(Method.GET)
            .url("/process_gather.php?Digits=TIMEOUT").build();
        VoiceResponse response = new VoiceResponse.Builder().gather(gather)
            .redirect(redirect).build();

        try {
            System.out.println(response.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/gather_hints.xml -->
<Response>
    <Gather action="/process_gather.php" method="GET">
        <Say>Enter something, or not</Say>
    </Gather>
    <Redirect method="GET">
        /process_gather.php?Digits=TIMEOUT
    </Redirect>
</Response>
Gather with Redirect

When <Gather> times out, Twilio moves on to the next verb, in this case <Redirect>. The <Redirect> verb instructs Twilio to make a new GET request to "/process_gather.php?Digits=TIMEOUT".

Language Appendix

A .csv of languages is available here.

Language Language Tag
Afrikaans (South Africa) af-ZA
Amharic (Ethiopia) am-ET
Armenian (Armenia) hy-AM
Azerbaijani (Azerbaijani) az-AZ
Indonesian (Indonesia) id-ID
Malay (Malaysia) ms-MY
Bengali (Bangladesh) bn-BD
Bengali (India) bn-IN
Catalan (Spain) ca-ES
Czech (Czech Republic) cs-CZ
Danish (Denmark) da-DK
German (Germany) de-DE
English (Australia) en-AU
English (Canada) en-CA
English (Ghana) en-GH
English (United Kingdom) en-GB
English (India) en-IN
English (Ireland) en-IE
English (Kenya) en-KE
English (New Zealand) en-NZ
English (Nigeria) en-NG
English (Philippines) en-PH
English (South Africa) en-ZA
English (Tanzania) en-TZ
English (United States) en-US
Spanish (Argentina) es-AR
Spanish (Bolivia) es-BO
Spanish (Chile) es-CL
Spanish (Colombia) es-CO
Spanish (Costa Rica) es-CR
Spanish (Ecuador) es-EC
Spanish (El Salvador) es-SV
Spanish (Spain) es-ES
Spanish (United States) es-US
Spanish (Guatemala) es-GT
Spanish (Honduras) es-HN
Spanish (Mexico) es-MX
Spanish (Nicaragua) es-NI
Spanish (Panama) es-PA
Spanish (Paraguay) es-PY
Spanish (Peru) es-PE
Spanish (Puerto Rico) es-PR
Spanish (Dominican Republic) es-DO
Spanish (Uruguay) es-UY
Spanish (Venezuela) es-VE
Basque (Spain) eu-ES
Filipino (Philippines) f il-PH
French (Canada) fr-CA
French (France) fr-FR
Galician (Spain) gl-ES
Georgian (Georgia) ka-GE
Gujarati (India) gu-IN
Croatian (Croatia) hr-HR
Zulu (South Africa) zu-ZA
Icelandic (Iceland) is-IS
Italian (Italy) it-IT
Javanese (Indonesia) jv-ID
Kannada (India) kn-IN
Khmer (Cambodian) km-KH
Lao (Laos) lo-LA
Latvian (Latvia) lv-LV
Lithuanian (Lithuania) lt-LT
Hungarian (Hungary) hu-HU
Malayalam (India) ml-IN
Marathi (India) mr-IN
Dutch (Netherlands) nl-NL
Nepali (Nepal) ne-NP
Norwegian Bokmål (Norway) nb-NO
Polish (Poland) pl-PL
Portuguese (Brazil) pt-BR
Portuguese (Portugal) pt-PT
Romanian (Romania) ro-RO
Sinhala (Sri Lanka) si-LK
Slovak (Slovakia) sk-SK
Slovenian (Slovenia) sl-SI
Sundanese (Indonesia) su-ID
Swahili (Tanzania) sw-TZ
Swahili (Kenya) sw-KE
Finnish (Finland) fi-FI
Swedish (Sweden) sv-SE
Tamil (India) ta-IN
Tamil (Singapore) ta-SG
Tamil (Sri Lanka) ta-LK
Tamil (Malaysia) ta-MY
Telugu (India) te-IN
Vietnamese (Vietnam) vi-VN
Turkish (Turkey) tr-TR
Urdu (Pakistan) ur-PK
Urdu (India) ur-IN
Greek (Greece) el-GR
Bulgarian (Bulgaria) bg-BG
Russian (Russia) ru-RU
Serbian (Serbia) sr-RS
Ukrainian (Ukraine) uk-UA
Hebrew (Israel) he-IL
Arabic (Israel) ar-IL
Arabic (Jordan) ar-JO
Arabic (United Arab Emirates) ar-AE
Arabic (Bahrain) ar-BH
Arabic (Algeria) ar-DZ
Arabic (Saudi Arabia) ar-SA
Arabic (Iraq) ar-IQ
Arabic (Kuwait) ar-KW
Arabic (Morocco) ar-MA
Arabic (Tunisia) ar-TN
Arabic (Oman) ar-OM
Arabic (State of Palestine) ar-PS
Arabic (Qatar) ar-QA
Arabic (Lebanon) ar-LB
Arabic (Egypt) ar-EG
Persian (Iran) fa-IR
Hindi (India) hi-IN
Thai (Thailand) th-TH
Korean (South Korea) ko-KR
Chinese, Mandarin (Traditional, Taiwan) cmn-Hant-TW
Chinese, Cantonese (Traditional, Hong Kong) yue-Hant-HK
Japanese (Japan) ja-JP
Chinese, Mandarin (Simplified, Hong Kong) cmn-Hans-HK
Chinese, Mandarin (Simplified, China) cmn-Hans-CN

Troubleshooting

  • Problem: <Gather> isn't receiving caller input when using a VoIP phone. Solution: Some VoIP phones have trouble sending DTMF digits. This is usually because these phones use compressed, bandwidth conserving audio protocols that interfere with the transmission of the digit's signal. Consult your phone's documentation on DTMF problems.
  • Problem: Twilio is not sending the Digits parameter to the <Gather> URL. Solution: Check to ensure your application is not responding to the <Gather> 'action' URL with an HTTP 3xx redirect. Twilio will follow the redirect, but won't resend the Digits parameter.

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd browsing the Twilio tag on Stack Overflow.

1 / 1
Loading Code Samples...
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • TwiML
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
const gather = response.gather({
  input: 'speech dtmf',
  timeout: 3,
  numDigits: 1,
});
gather.say('Please press 1 or say sales for sales.');

console.log(response.toString());
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        var gather = new Gather(input: "speech dtmf", timeout: 3, numDigits: 1);
        gather.Say("Please press 1 or say sales for sales.");
        response.Append(gather);

        Console.WriteLine(response.ToString());;
    }
}
<?php
require_once './vendor/autoload.php';
use Twilio\Twiml;

$response = new Twiml();
$gather = $response->gather(['input' => 'speech dtmf', 'timeout' => 3,
    'numDigits' => 1]);
$gather->say('Please press 1 or say sales for sales.');

echo $response;
require 'twilio-ruby'

response = Twilio::TwiML::VoiceResponse.new
response.gather(input: 'speech dtmf', timeout: 3, num_digits: 1) do |gather|
  gather.say('Please press 1 or say sales for sales.')
end

puts response
from twilio.twiml.voice_response import Gather, VoiceResponse, Say

response = VoiceResponse()
gather = Gather(input='speech dtmf', timeout=3, num_digits=1)
gather.say('Please press 1 or say sales for sales.')
response.append(gather)

print(response)
import com.twilio.twiml.Gather;
import com.twilio.twiml.VoiceResponse;
import com.twilio.twiml.Say;
import com.twilio.twiml.TwiMLException;


public class Example {
    public static void main(String[] args) {
        Say say = new Say.Builder("Please press 1 or say sales for sales.")
            .build();
        Gather gather = new Gather.Builder().input("speech dtmf").timeout(3)
            .numDigits(1).say(say).build();
        VoiceResponse response = new VoiceResponse.Builder().gather(gather)
            .build();

        try {
            System.out.println(response.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Gather input="speech dtmf" timeout="3" numDigits="1">
        <Say>Please press 1 or say sales for sales.</Say>
    </Gather>
</Response>
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • TwiML
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
response.gather();

console.log(response.toString());
using Twilio.TwiML;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        response.Gather();

        Console.WriteLine(response.ToString());;
    }
}
<?php
require_once './vendor/autoload.php';
use Twilio\Twiml;

$response = new Twiml();
$response->gather();

echo $response;
require 'twilio-ruby'

response = Twilio::TwiML::VoiceResponse.new
response.gather

puts response
from twilio.twiml.voice_response import Gather, VoiceResponse

response = VoiceResponse()
response.gather()

print(response)
import com.twilio.twiml.Gather;
import com.twilio.twiml.VoiceResponse;
import com.twilio.twiml.TwiMLException;


public class Example {
    public static void main(String[] args) {
        Gather gather = new Gather.Builder().build();
        VoiceResponse response = new VoiceResponse.Builder().gather(gather)
            .build();

        try {
            System.out.println(response.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/simple_gather.xml -->
<Response>
    <Gather/>
</Response>
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • TwiML
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
const gather = response.gather({
    action: '/process_gather.php',
    method: 'GET'
});
gather.say('Please enter your account number,\nfollowed by the pound sign');
response.say('We didn\'t receive any input. Goodbye!');

console.log(response.toString());
using Twilio.TwiML;
using Twilio.Http;
using Twilio.TwiML.Voice;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        var gather = new Gather(action: new Uri("/process_gather.php"), method: HttpMethod.Get);
        gather
            .Say("Please enter your account number,\nfollowed by the pound sign");
        response.Append(gather);
        response.Say("We didn't receive any input. Goodbye!");

        Console.WriteLine(response.ToString());;
    }
}
<?php
require_once './vendor/autoload.php';
use Twilio\Twiml;

$response = new Twiml();
$gather = $response->gather(['action' => '/process_gather.php',
    'method' => 'GET']);
$gather->say('Please enter your account number,\nfollowed by the pound sign');
$response->say('We didn\'t receive any input. Goodbye!');

echo $response;
require 'twilio-ruby'

response = Twilio::TwiML::VoiceResponse.new
response.gather(action: '/process_gather.php', method: 'GET') do |gather|
  gather.say('Please enter your account number,\nfollowed by the pound sign')
end
response.say('We didn\'t receive any input. Goodbye!')

puts response
from twilio.twiml.voice_response import Gather, VoiceResponse, Say

response = VoiceResponse()
gather = Gather(action='/process_gather.php', method='GET')
gather.say('Please enter your account number,\nfollowed by the pound sign')
response.append(gather)
response.say('We didn\'t receive any input. Goodbye!')

print(response)
import com.twilio.twiml.Gather;
import com.twilio.twiml.VoiceResponse;
import com.twilio.twiml.Say;
import com.twilio.twiml.TwiMLException;
import com.twilio.twiml.Method;

public class Example {
    public static void main(String[] args) {
        Say say = new Say
            .Builder("Please enter your account number,\nfollowed by the pound sign").build();
        Gather gather = new Gather.Builder().action("/process_gather.php")
            .method(Method.GET).say(say).build();
        Say say2 = new Say
            .Builder("We didn't receive any input. Goodbye!").build();
        VoiceResponse response = new VoiceResponse.Builder().gather(gather)
            .say(say2).build();

        try {
            System.out.println(response.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/complex_gather.xml -->
<Response>
    <Gather action="/process_gather.php" method="GET">
        <Say>
            Please enter your account number,
            followed by the pound sign
        </Say>
    </Gather>
    <Say>We didn't receive any input. Goodbye!</Say>
</Response>
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • TwiML
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
const gather = response.gather({
    input: 'speech',
    action: '/completed'
});
gather.say('Welcome to Twilio, please tell us why you\'re calling');

console.log(response.toString());
using Twilio.TwiML;
using Twilio.TwiML.Voice;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        var gather = new Gather(input: "speech", action: new Uri("/completed"));
        gather.Say("Welcome to Twilio, please tell us why you're calling");
        response.Append(gather);

        Console.WriteLine(response.ToString());;
    }
}
<?php
require_once './vendor/autoload.php';
use Twilio\Twiml;

$response = new Twiml();
$gather = $response->gather(['input' => 'speech', 'action' => '/completed']);
$gather->say('Welcome to Twilio, please tell us why you\'re calling');

echo $response;
require 'twilio-ruby'

response = Twilio::TwiML::VoiceResponse.new
response.gather(input: 'speech', action: '/completed') do |gather|
  gather.say('Welcome to Twilio, please tell us why you\'re calling')
end

puts response
from twilio.twiml.voice_response import Gather, VoiceResponse, Say

response = VoiceResponse()
gather = Gather(input='speech', action='/completed')
gather.say('Welcome to Twilio, please tell us why you\'re calling')
response.append(gather)

print(response)
import com.twilio.twiml.Gather;
import com.twilio.twiml.VoiceResponse;
import com.twilio.twiml.Say;
import com.twilio.twiml.TwiMLException;


public class Example {
    public static void main(String[] args) {
        Say say = new Say
            .Builder("Welcome to Twilio, please tell us why you're calling").build();
        Gather gather = new Gather.Builder().input("speech")
            .action("/completed").say(say).build();
        VoiceResponse response = new VoiceResponse.Builder().gather(gather)
            .build();

        try {
            System.out.println(response.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/simple_gather.xml -->
<Response>
    <Gather input="speech" action="/completed">
           <Say>Welcome to Twilio, please tell us why you're calling</Say>
        </Gather>
</Response>
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 3.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 5.x
Format:
  • TwiML
const VoiceResponse = require('twilio').twiml.VoiceResponse;

const response = new VoiceResponse();
const gather = response.gather({
    action: '/process_gather.php',
    method: 'GET'
});
gather.say('Enter something, or not');
response.redirect({
    method: 'GET'
}, '/process_gather.php?Digits=TIMEOUT');

console.log(response.toString());
using Twilio.TwiML;
using Twilio.Http;
using Twilio.TwiML.Voice;
using System;


class Example
{
    static void Main()
    {
        var response = new VoiceResponse();
        var gather = new Gather(action: new Uri("/process_gather.php"), method: HttpMethod.Get);
        gather.Say("Enter something, or not");
        response.Append(gather);
        response.Redirect(new Uri("/process_gather.php?Digits=TIMEOUT"), method: HttpMethod.Get);

        Console.WriteLine(response.ToString());;
    }
}
<?php
require_once './vendor/autoload.php';
use Twilio\Twiml;

$response = new Twiml();
$gather = $response->gather(['action' => '/process_gather.php',
    'method' => 'GET']);
$gather->say('Enter something, or not');
$response->redirect('/process_gather.php?Digits=TIMEOUT', ['method' => 'GET']);

echo $response;
require 'twilio-ruby'

response = Twilio::TwiML::VoiceResponse.new
response.gather(action: '/process_gather.php', method: 'GET') do |gather|
    gather.say('Enter something, or not')
end
response.redirect('/process_gather.php?Digits=TIMEOUT', method: 'GET')

puts response
from twilio.twiml.voice_response import Gather, Redirect, VoiceResponse, Say

response = VoiceResponse()
gather = Gather(action='/process_gather.php', method='GET')
gather.say('Enter something, or not')
response.append(gather)
response.redirect('/process_gather.php?Digits=TIMEOUT', method='GET')

print(response)
import com.twilio.twiml.Gather;
import com.twilio.twiml.Redirect;
import com.twilio.twiml.VoiceResponse;
import com.twilio.twiml.Say;
import com.twilio.twiml.TwiMLException;
import com.twilio.twiml.Method;

public class Example {
    public static void main(String[] args) {
        Say say = new Say.Builder("Enter something, or not").build();
        Gather gather = new Gather.Builder().action("/process_gather.php")
            .method(Method.GET).say(say).build();
        Redirect redirect = new Redirect.Builder().method(Method.GET)
            .url("/process_gather.php?Digits=TIMEOUT").build();
        VoiceResponse response = new VoiceResponse.Builder().gather(gather)
            .redirect(redirect).build();

        try {
            System.out.println(response.toXml());
        } catch (TwiMLException e) {
            e.printStackTrace();
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- page located at http://example.com/gather_hints.xml -->
<Response>
    <Gather action="/process_gather.php" method="GET">
        <Say>Enter something, or not</Say>
    </Gather>
    <Redirect method="GET">
        /process_gather.php?Digits=TIMEOUT
    </Redirect>
</Response>