How to receive and download picture messages in Python with Twilio MMS

May 10, 2018
Written by
Sam Agnew
Twilion

Screen Shot 2018-05-10 at 5.26.51 PM

Have you ever needed to programmatically download an image from an MMS message sent to your Twilio number? Well here’s all the code you need to do this using Python and Flask:

import requests
from flask import Flask, request, redirect
from twilio.twiml.messaging_response import MessagingResponse


DOWNLOAD_DIRECTORY = '/Path/to/your/code/directory'
app = Flask(__name__)


@app.route("/sms", methods=['GET', 'POST'])
def sms_reply():
    """Respond to incoming with a simple text message."""

    resp = MessagingResponse()

    if request.values['NumMedia'] != '0':

        # Use the message SID as a filename.
        filename = request.values['MessageSid']   '.png'
        with open('{}/{}'.format(DOWNLOAD_DIRECTORY, filename), 'wb') as f:
           image_url = request.values['MediaUrl0']
           f.write(requests.get(image_url).content)

        resp.message("Thanks for the image!")
    else:
        resp.message("Try sending a picture message.")

    return str(resp)

if __name__ == "__main__":
    app.run(debug=True)

To run the above code, you’ll need to have the Twilio Python helper library installed, as well as the Flask framework. Don’t forget to replace the value of the DOWNLOAD_DIRECTORY variable with a path to where you want to download the image on your machine.

Can you walk me through this step by step?

Absolutely! When someone texts your Twilio number, Twilio makes an HTTP request to your web app. Details about that message, such as the number of images and a URL to those images are passed via the NumMedia and MediaUrl0 request parameters respectively. Twilio expects an HTTP response from your web app in the form of TwiML, which is a set of XML tags to tell Twilio what to do next.

Before moving on, you’ll need to create a Twilio account and buy a phone number.

First make sure you have set up your local environment and that you have a directory where your code can live.

Open your terminal and install Flask, the popular micro web framework, which we’ll use to receive Twilio’s request and the requests module for downloading the image we get from our Twilio message:

pip install flask==1.0.2
pip install requests==2.18.4

Install the Twilio Python library to generate the response TwiML:

pip install twilio==6.13.0

Now that you have the dependencies taken care of, navigate to the directory you want your code to live in, and create a file called app.py. This will be the code for the Flask app that will receive the messages.

Here’s the code from the beginning of the post again. Copy and paste it into app.py and save the file:

import requests
from flask import Flask, request, redirect
from twilio.twiml.messaging_response import MessagingResponse


DOWNLOAD_DIRECTORY = '/Path/to/your/code/directory'
app = Flask(__name__)


@app.route("/sms", methods=['GET', 'POST'])
def sms_reply():
    """Respond to incoming with a simple text message."""

    resp = MessagingResponse()

    if request.values['NumMedia'] != '0':

        # Use the message SID as a filename.
        filename = request.values['MessageSid']   '.png'
        with open('{}/{}'.format(DOWNLOAD_DIRECTORY, filename), 'wb') as f:
           image_url = request.values['MediaUrl0']
           f.write(requests.get(image_url).content)

        resp.message("Thanks for the image!")
    else:
        resp.message("Try sending a picture message.")

    return str(resp)

if __name__ == "__main__":
    app.run(debug=True)

The above code consists of a global Flask app object that contains one route with the path /sms. Whenever a POST request is sent to /sms on our web app, the sms_reply function will be called. This will download the image if there is one and save it to a directory of your choice. Be sure to replace the DOWNLOAD_DIRECTORY global variable with the path to where you want the image downloaded.

But how does Twilio see my app to send it this request?

Excellent question. Our app needs a publicly accessible URL so Twilio can send it the webhook request when a message is received. To avoid having to deploy code just to test our app, we’ll use a nifty tool called ngrok to open a tunnel to our local machine.

Ngrok generates a custom forwarding URL that we will use to tell Twilio where to find our application. Download ngrok and run it in your terminal on port 5000:

./ngrok http 5000

Now we just need to point a phone number at our app.
Open the phone number configuration screen in your Twilio console. Scroll down to the “a message comes in” field. You should see something like this:


Enter the URL for that was generated by ngrok. It should look something like http://your-ngrok-url.ngrok.io/sms, and don’t forget the /sms at the end!

Click save, then text a picture to your number to see  it download onto your machine!

ImageDownload

Why would I even want to do this?

I know what you’re thinking, “Surely there are better ways to get an image from my phone to my machine” and you’re right. But this is a necessary first step to building larger projects that do some sort of image manipulation on picture messages sent from users. Once you can programmatically download an image, you can do cool things with it using a library like Pillow.

For examples on what to do next, you can:

If you want to do this with Node.js, you can also check this post out.

Feel free to drop me a line if you have any question or just want to show off what you build: