Building a Simple SMS Message Application with Twilio and Django

me_wootyDjango is often referred to as a “batteries included” Python web framework due to the many features that come with it out-of-the-box. It is becoming an increasingly popular choice for developers who want to build web applications in Python.

Django is my personal choice when developing web apps as I love the huge collection of contributed libraries and the great community developing the software. When I think about how MVC web frameworks should work; Django fits it almost perfectly. Let’s build a simple application that responds with an SMS message when you send an SMS message to it.

What You’ll Learn

In this post we’re going to use Django to build a simple SMS application:

  • Linking a Twilio phone number to your Django web application
  • Responding to an SMS message with some basic TwiML
  • Using twilio-python to build responses pythonically
  • Using Django-twilio to make Django respond securely

Connecting Twilio to a Django View

Twilio uses webhooks to talk to our application: when Twilio receives an SMS it sends a HTTP request to a URL on our web application. We then return a response which Twilio transforms into an SMS message or a phone call.

Just like any device in the telephony network, you’re going to need a phone number in order to send and receive SMS. You can head over to the Twilio account portal and get one for free on a trial account. We need to set our URL in the account portal in the Request URL field in our phone number configuration:


We’ll be using the /sms/ url for this tutorial. If you want to host your local development environment on the web, I recommend using ngrok.

When it receives the request from Twilio, Django will check the URL configuration to decide which view to pass the request information. The view then sends our response back to Twilio.

We’re going to need to start a new Django project for this, so run the following code in terminal to set one up:

We’re using the project name djtwilio (mostly because it sounds like a bad ass disk jockey) but you’re welcome to use your own name for the project. Just remember to substitute djtwilio for your project name throughout the code.

We’ll need to define the urls in our URL configuration before we code anything else, otherwise the request won’t go anywhere:

Here we have set the configuration to link the /sms/ url to the sms_received view. In Django this view can be a function. You can also use class-based views, but for this example we’re using function-based views.

Responding to Twilio requests and Building TwiML

We can now start building our view function in the file:

Django view functions must always take at least one parameter: the request object. This is passed to the function with information such as HTTP header parameters, form POST data and a bunch of other stuff. We’re not interested in this just yet but Django requires it.

Twilio uses TwiML; a collection of XML tags that Twilio interprets as instructions.

This means we can create a string like this:

And Twilio will transform it into an SMS message, just like magic. Here our response is a message with some simple text. TwiML makes these complex telephony actions stupidly simple to implement.

Finally we return our TwiML string in a HttpResponse object. This is the standard method for sending HTTP responses in Django:

Because we are returning XML, HTTP standards say we should set the content type to text/xml. We want to follow the rules of the web, after all.

Startup the server through the command line:

CSRF exemption

Now if you try to send an SMS to the number linked to this view you’ll see an error.

Oh no! Twilio has a great app monitor which keeps track of errors for you, so you can see where things are going wrong. If we look at this error in the app monitor you’ll see this:


Further investigation of this error will show that we’ve received a 403 forbidden response.

Because Django is strict about security, especially when it comes to HTTP POST requests, it requires a CSRF token to validate the requests. To get around this you need to add a csrf_exempt decorator to the line above your view function:

The Django developers reading this are probably worried about using csrf_exempt on this view as it disables any authentication and security checking. We’d never want to do this in production so we’re just using it as an example here. We’ll provide a Twilio-specific secure solution further on.

The final code (including imports) to reply to an SMS message looks like this:

If we try sending an SMS message to our number now we can see if we get a response.

Boom. It works.

Introducing twilio-python

Wouldn’t it be easier if we didn’t have to remember which TwiML verbs to use? Sometimes those strings can be huge and the chances of writing malformed XML increases the bigger the responses get.

Twilio provides helper libraries in a variety of languages such as Python, Ruby, Java and C#. The twilio-python package can help us build TwiML responses with its MessagingResponse class.

We can install twilio-python using pip:

Let’s see how twilio-python can make our previous code example easier.

That gives us cleaner code which is also pretty pythonic too. No need to write any XML: we just add different verbs to a response object and return it when we’re done.

Django-Twilio To The Rescue

The twilio-python package makes is easy to build TwiML, but what about Django-specific features? And what about that big security hole with CSRF tokens? Is there a way we can make it easier to use twilio in Django? There is indeed!

Django-twilio, by Randall Degges, provides a collection of decorators for views that return TwiML or receive information from Twilio. We can use these decorators to clean up the code in our view function even more.

Just like the Twilio python helper library, we can install it with pip:

Here is the previous code example modified one last time to include django-twilio and it’s features:

The twilio_view decorator view provides some major benefits:
1. It ensures requests sent to the view originate from only, this prevents attackers from spoofing a request to the view.
2. It turns off CSRF exemption in favour of the security in number 1, which is actually far more secure.
3. It sends your response back in a HttpResponse object with the appropriate content type.
4. Finally, it works in Django debug mode. You can test views just like a normal web page, even with the twilio_view decorator, just set DEBUG = True.

Discovering Twilio Content In The Request

Now that we can reply to an SMS, let’s figure out what Twilio sent to us in the request and reply with a personalised reply. This is one of my favourite features of Twilio: all the data delivered to you looks like a normal HTTP POST or GET request.

At the top of our views, add the new imports:

With Django we can grab content in the request POST headers with the following code:

This looks at the HTTP request data and returns the sms content (the Body value), otherwise it just returns an empty string. We can then send back a personalised message:

So when a I send an SMS message with my name I will get an SMS reply like this:

Hello Paul, how are you today?

The complete code for this, with new lines highlighted:

What’s Next?

We’ve demonstrated the basics of receiving and responding to SMS messages with Twilio and Django. You should now have the foundations required to build complex systems that leverage the telephony system: SMS opt-in/out subscription services, providing surveys via SMS or even SMS text adventure games like zork. Go and explore with the Twilio API and see what you can build; it costs nothing to try it out.

This code for this article can be found on Github, so feel free to fork it and use it as a basis for your own app.

We’ll be continuing this series of posts related to Django in a few weeks by demonstrating how to build conference centres. Until then my fellow Djangonauts: enjoy your new skills.

  • Anthony

    Thanks for the starter kit, complete with github repo.

    • Paul Hallett

      Glad to help :)

  • ItsJustCoffee

    Thanks for the great write up and for bringing to light the useful Python and Django modules.

    • Paul Hallett

      Thanks! Glad it was helpful

  • Sławek Ehlert

    Hey. Nice one. Thanks! Shouldn’t the “costs nothing to try it out” link follow elsewhere?

    • Paul Hallett

      Should be solved now, thanks for pointing this out.

  • Tom A

    Perfect timing – I’m just integrating Twilio into a Django app. Thanks for a concise and useful article and congrats on the developer evangelist job!

    • Paul Hallett

      Glad I could help Tom. Let me know if you have any other questions.

  • Akhilesh Pillai

    Thank You!! Eagerly waiting for more such posts.

    • Twilio

      Hey Akhilesh, We’ll have more tutorial posts in this same vein published soon. Stay tuned to the blog and thanks for reading! Let us know if you have any questions.

  • Tai An

    Thank you Paul, this is very helpful.. I forgot the CSRF thing

    • Paul Hallett

      Yeah it will trip you up if you’re not careful. Glad I was able to help :)

  • JGallardo

    Can this be used to auto-text our different Tinder matches at set intervals each?

    We don’t want to end up like this dude lol

    • Paul Hallett

      The honest answer is yes because: he sent an iMessage as a group message. With Twilio, we’re using the traditional PSTN network, which doesn’t support group messaging. So you’d never have this incident!

  • Omar Co

    Hi Paul. Thank you for representing Python and Django! I’m interested in creating a interaction that involves a few questions and responses via SMS using Django & Twilio.
    For example:
    Twilio app: “How are you on a scale of 1 to 10?”.
    User: “4”.

    Twilio app: “I’m sorry you’re not doing well. What’s going on?”
    User: “Tired.”

    Twilio app: “Here are a few things you can do about your energy level…”.

    Do you have any examples or are there any out there that you know about? Thanks again!

  • Omar Co
  • melia

    Hello My name is Mike and I am looking for a way to send mass text messages to a church group for ~4000 members. How can do this? I appreciate your input. I am currently using email to text methods. But as you know they are not the most efficient way. Please advice. TY

    • Twilio

      Hey Mike,
      You can build a messaging app/solution for your Church members using Twilio. You can learn more about and contact if you have any questions. Additionally, if you don’t have developers to build the SMS app, we’re happy to connect you with a partner who can build it for you.

  • Jonah

    Hi Paul,

    Loved your post and while it has helped me a bit, I’d love if you could help me out of a jam.

    Here’s the deal:

    Two of my best friends are getting married in a couple of weeks. I’ve had this idea to have a “marriage texting diary” which will ask them a simple question (eg. “How was your day? What do you want to remember from today?) each day for the first year of their marriage, then I’ll compile all their responses and print a book for their 1st anniversary.

    Sounds cute, right?

    Well the challenge is that I’m not technically proficient by any means. I know nothing about coding or database architecture and while I’ve been trying to learn, it has been a real challenge.

    Any chance you could help me out/point me in the right direction?

    Your assistance would mean a ton to me and to the newlyweds.

    Thanks in advance,


  • Josh Sullivan

    I’m writing a script to display messages for each number in django_twilio.Caller. Any idea how to pass a twilio number in the urls?

  • Benjamin Bao

    Hi! I have a question, I deployed my django website to Heroku with twilio integrated, and I set the SMS Request URL to my website URL ( and implemented to reply with some basic texts. However I’m getting Error 11200, HTTP code 502 Bad Gateway.

  • Andres De Jesus

    I am having issues trying to use this tutorial with django 1.9 or 1.10 it keep saying patterns cannot be imported help would be greatly appreciated. thank you in advance

  • Admirador de Damas

    Starter Kit for .NET C# full real world sample ?