Skip to contentSkip to navigationSkip to topbar
Page toolsOn this page
Looking for more inspiration?Visit the

Gather User Input with Keypad


Learn to gather user input through a phone's keypad with Twilio Programmable Voice by using the TwiML <Gather> verb to capture DTMF tones during a live call. You can use this guide to send voice notifications, create self-service automation, build inbound contact centers, and create outbound contact centers.

See Related reference documentation to learn more about the TwiML elements used in this guide.


Complete the prerequisites

complete-the-prerequisites page anchor

Complete the Twilio prerequisites

complete-the-twilio-prerequisites page anchor

Complete the language prerequisites

complete-the-language-prerequisites page anchor

Select your programming language and complete the prerequisites:

PythonNode.jsPHPC# or .NETJavaRuby
  • Install Python 3.3 or later(link takes you to an external page).
  • Install Flask(link takes you to an external page) and the Twilio Python Helper Library(link takes you to an external page). Using pip(link takes you to an external page), run the following command:
    pip install flask twilio
  • Install and set up ngrok(link takes you to an external page).

Get credentials and set as environment variables

get-credentials-and-set-as-environment-variables page anchor

Extract your credentials from your Twilio account then save these credentials as environment variables.

Twilio ConsoleLegacy Console
  1. Go to the Twilio Console(link takes you to an external page). The Let's get building page appears.

  2. Click API keys and Auth tokens. The API keys & auth tokens page appears with the Auth Tokens tab selected.

  3. Scroll to your Account SID.

  4. Click the copy button next to your Account SID.

  5. Run the following command, replacing YOUR_ACCOUNT_SID with your Account SID.

    macOS TerminalWindows command linePowerShell
    export TWILIO_ACCOUNT_SID=YOUR_ACCOUNT_SID

    This command creates an environment variable on your development system for your account SID.

  6. To display the Auth Token, click the eye button in the Primary auth token box.

  7. Highlight and copy the Auth Token.

  8. Run the following command, replacing YOUR_AUTH_TOKEN with your Authentication Token.

    macOS TerminalWindows command linePowerShell
    export TWILIO_AUTH_TOKEN=YOUR_AUTH_TOKEN

    This command creates an environment variable on your development system for your auth token.

To learn more about features, see Interactive Voice Response.


To collect input from the user during a phone call, use the <Gather> TwiML verb. IVR systems rely on user input from the keypad.

Using the TwiML <Say> and <Play> verbs, you program the IVR voice prompts. When the IVR answers a call, it asks end users to make decisions using their phone keypad.

To forward the call to one department, the IVR tells the end user to press 1. For a different department, the IVR tells the end user to press 2.

This guide prompts the end user for a number that connects them to a certain department within the IVR system.

PythonNode.jsPHPC# or .NETJavaRuby

Python only requires the Twilio Python helper library as noted in the prerequisites.

Use <Gather> to collect user input via the keypad (DTMF tones)Link to code sample: Use <Gather> to collect user input via the keypad (DTMF tones)
1
from flask import Flask
2
from twilio.twiml.voice_response import VoiceResponse, Gather
3
4
app = Flask(__name__)
5
6
7
@app.route("/voice", methods=['GET', 'POST'])
8
def voice():
9
"""Respond to incoming phone calls with a menu of options"""
10
# Start our TwiML response
11
resp = VoiceResponse()
12
13
# Start our <Gather> verb
14
gather = Gather(num_digits=1)
15
gather.say('For sales, press 1. For support, press 2.')
16
resp.append(gather)
17
18
# If the user doesn't select an option, redirect them into a loop
19
resp.redirect('/voice')
20
21
return str(resp)
22
23
if __name__ == "__main__":
24
app.run(debug=True)

Twilio waits for end user input. How long Twilio waits depends on the timeout you set. If the end user doesn't enter any input within this period, Twilio processes the call using other instructions in the TwiML document. When Twilio reaches the end of the TwiML document, it ends the call.

Without any end user input, Twilio repeats the prompt. To repeat the prompt, this code uses the <Redirect> verb.

The previous code doesn't include any logic that processes end user input.

Twilio repeats the prompt endlessly regardless of end user actions.

By default, if the user does enter input in the <Gather>, Twilio sends another HTTP request to the current webhook URL with a POST parameter containing the Digits entered by the user.

In the sample above, we weren't handling this input at all. Let's update that logic to also process user input if it is present.

PythonNode.jsPHPC# or .NETJavaRuby
Branch your call logic based on the digits sent by the userLink to code sample: Branch your call logic based on the digits sent by the user
1
from flask import Flask, request
2
from twilio.twiml.voice_response import VoiceResponse, Gather
3
4
app = Flask(__name__)
5
6
7
@app.route("/voice", methods=['GET', 'POST'])
8
def voice():
9
"""Respond to incoming phone calls with a menu of options"""
10
# Start our TwiML response
11
resp = VoiceResponse()
12
13
# If Twilio's request to our app included already gathered digits,
14
# process them
15
if 'Digits' in request.values:
16
# Get which digit the caller chose
17
choice = request.values['Digits']
18
19
# <Say> a different message depending on the caller's choice
20
if choice == '1':
21
resp.say('You selected sales. Good for you!')
22
return str(resp)
23
elif choice == '2':
24
resp.say('You need support. We will help!')
25
return str(resp)
26
else:
27
# If the caller didn't choose 1 or 2, apologize and ask them again
28
resp.say("Sorry, I don't understand that choice.")
29
30
# Start our <Gather> verb
31
gather = Gather(num_digits=1)
32
gather.say('For sales, press 1. For support, press 2.')
33
resp.append(gather)
34
35
# If the user doesn't select an option, redirect them into a loop
36
resp.redirect('/voice')
37
38
return str(resp)
39
40
if __name__ == "__main__":
41
app.run(debug=True)

Channel input to an action

channel-input-to-an-action page anchor

You may want to have an entirely different endpoint in your app handle the processing of user input. This is possible using the "action" attribute of the <Gather> verb. Let's update our example to add a second endpoint that will be responsible for handling user input.

PythonNode.jsPHPC# or .NETJavaRuby
Add another route to handle the input from the userLink to code sample: Add another route to handle the input from the user
1
from flask import Flask, request
2
from twilio.twiml.voice_response import VoiceResponse, Gather
3
4
app = Flask(__name__)
5
6
7
@app.route("/voice", methods=['GET', 'POST'])
8
def voice():
9
"""Respond to incoming phone calls with a menu of options"""
10
# Start our TwiML response
11
resp = VoiceResponse()
12
13
# Start our <Gather> verb
14
gather = Gather(num_digits=1, action='/gather')
15
gather.say('For sales, press 1. For support, press 2.')
16
resp.append(gather)
17
18
# If the user doesn't select an option, redirect them into a loop
19
resp.redirect('/voice')
20
21
return str(resp)
22
23
24
@app.route('/gather', methods=['GET', 'POST'])
25
def gather():
26
"""Processes results from the <Gather> prompt in /voice"""
27
# Start our TwiML response
28
resp = VoiceResponse()
29
30
# If Twilio's request to our app included already gathered digits,
31
# process them
32
if 'Digits' in request.values:
33
# Get which digit the caller chose
34
choice = request.values['Digits']
35
36
# <Say> a different message depending on the caller's choice
37
if choice == '1':
38
resp.say('You selected sales. Good for you!')
39
return str(resp)
40
elif choice == '2':
41
resp.say('You need support. We will help!')
42
return str(resp)
43
else:
44
# If the caller didn't choose 1 or 2, apologize and ask them again
45
resp.say("Sorry, I don't understand that choice.")
46
47
# If the user didn't choose 1 or 2 (or anything), send them back to /voice
48
resp.redirect('/voice')
49
50
return str(resp)
51
52
if __name__ == "__main__":
53
app.run(debug=True)

The action attribute accepts a relative URL. This URL points to another route that your server can handle. To handle our call logic with separate code paths, use actions and redirects.


Use cases for keypad input with Twilio Programmable Voice

use-cases-for-keypad-input-with-twilio-programmable-voice page anchor

This guide covers a feature for the following use cases:

Send voice notifications with Twilio Programmable Voice

send-voice-notifications-with-twilio-programmable-voice page anchor

You can use this guide to send voice notifications that require a quick user response. For example, you can programmatically alert users about fraudulent activity on an account and prompt them to confirm or deny the transaction immediately using their phone's keypad.

To learn more advanced features that you can use with voice notifications, see Voice notifications.

Create self-service automation with Twilio Programmable Voice

create-self-service-automation-with-twilio-programmable-voice page anchor

You can use this guide to build phone systems that resolve customer requests without human intervention. For example, callers can securely authenticate their identity, check their bank account balance, or update an appointment status entirely by using keypad menus.

To learn more advanced features that you can use with self-service automation, see Voice self-service automation.

Create an inbound contact center with Twilio Programmable Voice

create-an-inbound-contact-center-with-twilio-programmable-voice page anchor

You can use this guide to route incoming customer calls to the right agent or department efficiently. By deploying an interactive keypad menu, you can direct customers based on their explicit selections, minimizing wait times and transfers.

To learn more advanced features that you can use with inbound contact centers, see Voice inbound contact center.

Create an outbound contact center with Twilio Programmable Voice

create-an-outbound-contact-center-with-twilio-programmable-voice page anchor

You can use this guide to enhance proactive customer outreach with immediate routing controls. For example, when an outbound dialer connects with a customer, it can offer keypad options to speak with a live agent, schedule a callback, or opt out of future communications.

To learn more advanced features that you can use with outbound contact centers, see Voice outbound contact center.


After following this guide, you can successfully collect DTMF tones from a user's telephone keypad during a phone call using Twilio Programmable Voice. You can test your system by calling your Twilio phone number, pressing the keypad buttons when prompted, and verifying that your application branches its logic based on the collected digits.


Explore the following guides to build on what you've learned in this guide: