Getting Started with Python, Bottle and Twilio SMS / MMS

Python, Bottle and Twilio logos

Python applications can easily send and respond to text and picture messages using a web API. Outbound messages are sent through Twilio’s RESTful API, while inbound messages are received by your application when Twilio makes an HTTP POST request. We will walk through how to set up a Bottle web app to handle both SMS and MMS messages.

Tools We Need

You’ll need Python 2 or 3. Although, Python 3 is recommended by the developer community for all new applications. Install one of those two Python versions on your system. We also need the following:

All the code for this tutorial can be found in an open source GitHub repository.
If you need help configuring your development environment before we dive into writing our application, check out this handy guide on setting up Python 3, Bottle and Gunicorn on Ubuntu 16.04 LTS.

Installing Application Dependencies

Our application will use the Twilio Python helper code library to send and reply to messages. Bottle and the helper library are installable from PyPI into a virtual environment. Open your terminal and use the virtualenv command to create a new virtual environment:

Invoke the virtualenv’s activate script, which makes it the active Python installation for our shell. Note that you need to do this in every terminal window that you want this virtualenv to be used.

The command prompt will change after activation to the name of the virtual environment within parentheses, like this example shown here:

Use the pip command to install the Bottle and Twilio Python packages into your virtual environment.

We installed the required dependencies. Now the Python code that is run with the virtualenv activated will be able to use those packages. It’s time to buy a phone number that we can use to build our Bottle web app that will handle SMS and MMS messages.

Obtain a Phone Number

Head over to the Twilio website and sign up for a free account or sign into your existing Twilio account.
Twilio sign up screen.
Twilio trial accounts allow you to send and receive messages to your own phone number. Trials are great for initial development before your application goes live. Upgrade your account to to send and receive messages to and from any phone number.

If you need a new phone number or want to see the existing numbers you have, go to the manage phone numbers screen via that link or click the “#” on the left Console navigation bar.

Twilio Console left nav phone numbers screen.

With our accounts credentials and a Twilio phone number in hand, we can write some Python code to send outbound messages.

Sending SMS Messages with Bottle

The Bottle web app will have two routes. One route will allow us to test that the app is running. The other route will handle and respond to incoming HTTP POST requests from Twilio. Create a new file named in your in the directory where you want to store this Python project.
Write the following code in the new file.

The lines starting with # are comments that give explanations for what the code lines below them are executing. Bottle web apps define URL routes with the @route and @post decorators, depending on the type of HTTP request the route should handle, whether a GET or POST, respectively.
We need to grab our account credentials, the Account SID and Auth Token, from the Twilio Console, to instantiate the client object.


We can start up the Bottle development server now that we have our Twilio account credentials plugged into the code. Make sure your virtual environment remains activated so that the application can use the Bottle and Twilio code libraries we installed earlier. Give the Bottle app a try by running it with python
Open a web browser and go to localhost:5000 (or We should see “Bottle web app up and running!” on the screen.
We can test the SMS sending function via the /send-sms/ URL. For example, try this URL to send the message “About to take a drive down the I-95” from your Twilio number to another phone number (make sure to replace the “from” and “to” numbers in the URL):

http://localhost:5000/send-sms/<your phone number>/<Twilio phone number>/about to take a drive down the i-95/

A simple success message should tell us that the SMS was sent to the recipient phone number.

Give it a second for the SMS to arrive and we should see something like the following if you’ve got an iPhone, or the equivalent on an Android:
We’ve got a skeleton of our Bottle app running that can send outbound SMS. Now we can add some MMS picture messaging into the mix.

Sending MMS Messages

Sending MMS message is very similar to how we just sent SMS, except that we need one more argument for our create_message function. We can specify a media_url with a URL to a picture in .gif, .jpg or .png format to send that as part of our MMS. It’s also possible to send movies and sound clips, which you can read more about in the docs.

Enhance the existing file with the following new highlighted lines.

Let’s give our app’s new MMS code a try. Try this URL in the browser, but replace the phone numbers with your Twilio number and the number you want to send the MMS to:

http://localhost:5000/send-mms/<your phone number>/<twilio phone number>/my favorite new game/


Here’s what it looks like when we successfully receive the MMS:

What if we want to respond to incoming SMS and MMS messages with our Bottle app? There is one issue with our web app running on our local development environment. Twilio cannot send a the HTTP POST request to the web app server. We can fix that issue during development by using a localhost tunneling tool.

Ngrok Localhost Tunneling

Ngrok is a localhost tunneling tool that bridges your local development environment to an external URL. Download and install the Ngrok version that’s appropriate for your operating system.

We can run Ngrok locally and expose our Bottle app that is running on port 5000. Run this command within the directory where the Ngrok executable is located.

Cool, now we can use the Forwarding URL so Twilio can send POST requests to our application when there is an inbound SMS. Replace the URL in the text box with your own Forwarding URL, like I did in this screenshot.

We can now set up Twilio to send a POST request to our application through Ngrok. Go to the manage phone numbers screen and click on the phone number you want to configure for replying to text messages.

Scroll down and look for the “Messaging” header. Change the “A Message Comes in” text box to input the ngrok Forwarding URL plus the “/twilio” route, as shown in the screenshot below.
Paste the ngrok Forwarding URL into the Twilio webhook configuration text box.
Click the “Save” button so that our changes take effect.
Update the file with the following new highlighted function that will handle Twilio’s POST requests when an SMS or MMS is sent to our phone number.

Our application is ready to go – time to give our phone number a try! Send “Hello” or whatever text you want to your phone number. Here is what the result looks like on my iPhone.

Nice work! This concise Bottle web app is a good start to build more complicated programs.

What’s next?

Awesome, our Bottle application can send and reply to inbound SMS and MMS messages. There’s so much more our application can do. Here are several more in-depth tutorials that’ll help you take the next step towards making your Python applications even more useful:

If you have questions or comments, please contact me via the following channels:

  • Twitter: @mattmakai
  • GitHub: mattmakai
  • Email:
  • Twitch (live coding along with other Twilio Developer Evangelists): Twilio channel
  • Eric Chou

    Hi Matt, great tutorial! I Twilio really kicks butt when it comes to simplicity. Just a few things I found when following this tutorial:

    1. Line 20 in your first code block return statement was missing ‘+’, you corrected it in later code blocks.
    2. Maybe add a section on where to add a Twilio phone number? I was brand new to Twilio so it was s question of mine, easy enough to debug but could save someone else time.
    3. The MMS example did not include the picture, the URL is still valid. No error message from Twilio. So not sure if it is because I only have a trial account. Will look more into it.
    4. For the POST example, probably worth pointing out and highlight the new import from ‘twilio import twiml’ at the top.

    Again, thank you for the tutorial. Very helpful!

    • Eric Chou

      Oh, nevermind about #3 above, the path was /send-mms/ and I used /send-sms/ instead because I was just editing the last part. Thanks!

  • Matt Makai

    Thanks Eric, great feedback! I’ve updated the post to address the missing plus sign and added a new screenshot along with text for getting to the phone numbers page. The from twilio import twiml is now highlighted as well. Thanks again.