Receiving Faxes

This guide walks through receiving a fax with Twilio Programmable Fax. We include sample code for many web languages and frameworks. For other frameworks (or languages) you can choose to use a helper library or directly respond with TwiML to receive a fax.

To receive a fax, you will require:

  • An Incoming Phone Number configured as a fax number.
    • Note: this will cause the number to be unavailable to receive calls using Programmable Voice
  • A FaxUrl which Twilio will query when a fax is received.

Set Up a Phone Number for Fax

First, ensure that you have an Incoming Phone Number on your account that supports receiving faxes. The number you select should have true for the fax item in the capabilities object. Alternatively, you can check using the console:

If you don't have a fax-capable number, you'll need to first purchase one. You can either use the Available Phone Numbers REST API resource (query with FaxEnabled=true), or Console Phone Numbers Search (/console/phone-numbers/search) (check the box to search for numbers with the Fax capability) to do so.

Next, you need to configure the number's Voice Receive Mode so that the number receives faxes rather than voice calls. Again, you can use the API's Incoming Phone Numbers resource (POST to the instance resource with VoiceReceiveMode=fax) or the Console. If using the Console, select the phone number you want to use from the list, and change the value of the "Accepts" dropdown box to "Faxes":

At this point, the number's VoiceUrl will now behave as its FaxUrl. Again, note that the number will now be unable to receive regular voice calls.

Receiving a Fax with the Twilio Helper Libraries

The following examples show how to receive a fax with common web languages and frameworks and are ready for you to incorporate the code in your application.

If you are not using one of these languages and frameworks:

  • If you are using one of these languages with a different framework, you can use the Twilio helper library in a similar way to receive faxes.
  • If you are using a different language, you can respond to Twilio's request with TwiML to receive the fax. Read beyond the sample code for more details.
Loading Code Samples...
Language
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 4.x
require 'rubygems'
require 'sinatra'

# Define a handler for when the fax is initially sent
post '/fax/sent' do
  # Let's manually build some TwiML. We can choose to receive the
  # fax with <Receive>, or reject with <Reject>.
  content_type 'text/xml'

  <<-TWIML
    <Response>
        <Receive action="/fax/received"/>
    </Response>'
    TWIML
end

# Define a handler for when the fax is finished sending to us - if successful,
# We will have a URL to the contents of the fax at this point
post '/fax/received' do
  # log the URL of the PDF received in the fax
  logger.info(params['MediaUrl'])

  # Respond with empty 200/OK to Twilio
  status 200
  body ''
end
using System.Web.Mvc;

namespace TwilioFax.Web.Controllers
{
    public class FaxController : Controller
    {
        // Define a handler for when the fax is initially sent
        [HttpPost]
        public ActionResult Sent()
        {
            // Let's manually build some TwiML. We can choose to receive the
            // fax with <Receive>, or reject with <Reject>.
            const string xmlString = "<Response>" +
                                        "<Receive action =\"/fax/received\"/>" +
                                      "</Response>";

            return this.Content(xmlString, "text/xml");
        }

        // Define a handler for when the fax is finished sending to us - if successful,
        // We will have a URL to the contents of the fax at this point
        [HttpPost]
        public ActionResult Received()
        {
            // log the URL of the PDF received in the fax
            System.Diagnostics.Debug.WriteLine(Request["MediaUrl"]);

            // Respond with empty 200/OK to Twilio
            return new EmptyResult();
        }
    }
}
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class FaxController extends Controller {

    public function __construct()
    {
        parent::__construct();

        // set content-type for all requests returned by this controller
        $this->set_output->set_content_type('text/xml');
    }

    // Define a handler for when the fax is initially sent
    public function sent()
    {
        $twimlResponse = new SimpleXMLElement("<Response></Response>");
        $receiveEl = $twimlResponse->addChild('Receive');
        $receiveEl->addAttribute('action', '/fax/received');

        $this->output->set_output($twimlResponse->asXML());
    }

    // Define a handler for when the fax is finished sending to us - if successful,
    // We will have a URL to the contents of the fax at this point
    public function received()
    {
        // log the URL of the PDF received in the fax
        log_message('info', $this->input->post("MediaUrl"));

        // Respond with empty 200/OK to Twilio
        $this->set_status_header(200);
        $this->output->set_output('');
    }
}
#!/usr/bin/env python
"""Fax snippet."""

from flask_script import Manager
from flask import Flask, Response, request

app = Flask(__name__)


@app.route('/fax/sent', methods=['POST'])
def fax_sent():
    """Define a handler for when the fax is initially sent."""
    # Let's manually build some TwiML. We can choose to receive the
    # fax with <Receive>, or reject with <Reject>.
    twiml = """
        <Response>
            <Receive action="/fax/received"/>
        </Response>
    """

    return Response(twiml, mimetype='text/xml')


@app.route('/fax/received', methods=['POST'])
def fax_received():
    """Define a handler for when the fax finished sending to us."""
    # We will have a URL to the contents of the fax at this point
    # log the URL of the PDF received in the fax
    print(request.form.get('MediaUrl'))

    # Respond with empty 200/OK to Twilio
    return '', 200


if __name__ == "__main__":
    Manager(app).run()
import spark.Route;

import static spark.Spark.post;

public class IndexFax {

    private static Route faxSent = (request, response) -> {
        // Let's manually build some TwiML. We can choose to receive the
        // fax with <Receive>, or reject with <Reject>.
        String twiml = "<Response>" +
                            "<Receive action=\"/fax/received\"/>" +
                        "</Response>";

        // Send Fax twiml response
        response.type("text/xml");
        return twiml;
    };

    // Define a handler for when the fax is finished sending to us - if successful,
    // We will have a URL to the contents of the fax at this point
    private static Route faxReceived  = (request, response) -> {
        // log the URL of the PDF received in the fax
        System.out.println(request.params(":mediaUrl"));

        // Respond with empty 200/OK to Twilio
        response.status(200);
        return null;
    };

    public static void main(String[] args) {
        post("/fax/sent", faxSent);

        post("/fax/received", faxReceived);
    }
}
const http = require('http');
const express = require('express');
const bodyParser = require('body-parser');

const app = express();

// Parse any incoming POST parameters
app.use(bodyParser({ extended: false }));

// Define a handler for when the fax is initially sent
app.post('/fax/sent', (req, res) => {
  // Let's manually build some TwiML. We can choose to receive the
  // fax with <Receive>, or reject with <Reject>.
  const twiml = `
  <Response>
    <Receive action="/fax/received"/>
  </Response>
  `;

  // Send Fax twiml response
  res.type('text/xml');
  res.send(twiml);
});

// Define a handler for when the fax is finished sending to us - if successful,
// We will have a URL to the contents of the fax at this point
app.post('/fax/received', (req, res) => {
  // log the URL of the PDF received in the fax
  console.log(req.body.MediaUrl);

  // Respond with empty 200/OK to Twilio
  res.status(200);
  res.send();
});

// Start the web server
http.createServer(app).listen(3000, () => {
  console.log('Express server listening on port 3000');
});
testable: false
Receive an incoming fax

Receiving a Fax with TwiML

When Twilio receives a call to an incoming phone number that has been configured as a Fax number, we will make an HTTP request to the FaxUrl configured for that number. Your server should respond with TwiML that instructs Twilio how to proceed.

You can check out the parameters of the TwiML request, as well as the available <Receive> and <Reject> TwiML verbs and their usage in the TwiML documentation.

Fax Log Storage

Twilio will store copies of media files for received faxes. The media files are available at the URL specified on the Fax instance resource.

Log data for each fax will be available via the REST API for 180 days after creation. When old fax records are pruned, Twilio will also delete the media associated with the pruned records. If you wish to delete data before that, you can delete just the media, or the entire resource, including the media.

Receiving Faxes with Twilio

Now you've seen how to receive faxes with common web languages and frameworks, as well as pointers if you are using a different framework or language.

Want to see more advanced features? Next, see the Fax REST API documentation.

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.

Loading Code Samples...
SDK Version:
  • 5.x
SDK Version:
  • 7.x
SDK Version:
  • 5.x
SDK Version:
  • 6.x
SDK Version:
  • 4.x
require 'rubygems'
require 'sinatra'

# Define a handler for when the fax is initially sent
post '/fax/sent' do
  # Let's manually build some TwiML. We can choose to receive the
  # fax with <Receive>, or reject with <Reject>.
  content_type 'text/xml'

  <<-TWIML
    <Response>
        <Receive action="/fax/received"/>
    </Response>'
    TWIML
end

# Define a handler for when the fax is finished sending to us - if successful,
# We will have a URL to the contents of the fax at this point
post '/fax/received' do
  # log the URL of the PDF received in the fax
  logger.info(params['MediaUrl'])

  # Respond with empty 200/OK to Twilio
  status 200
  body ''
end
using System.Web.Mvc;

namespace TwilioFax.Web.Controllers
{
    public class FaxController : Controller
    {
        // Define a handler for when the fax is initially sent
        [HttpPost]
        public ActionResult Sent()
        {
            // Let's manually build some TwiML. We can choose to receive the
            // fax with <Receive>, or reject with <Reject>.
            const string xmlString = "<Response>" +
                                        "<Receive action =\"/fax/received\"/>" +
                                      "</Response>";

            return this.Content(xmlString, "text/xml");
        }

        // Define a handler for when the fax is finished sending to us - if successful,
        // We will have a URL to the contents of the fax at this point
        [HttpPost]
        public ActionResult Received()
        {
            // log the URL of the PDF received in the fax
            System.Diagnostics.Debug.WriteLine(Request["MediaUrl"]);

            // Respond with empty 200/OK to Twilio
            return new EmptyResult();
        }
    }
}
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class FaxController extends Controller {

    public function __construct()
    {
        parent::__construct();

        // set content-type for all requests returned by this controller
        $this->set_output->set_content_type('text/xml');
    }

    // Define a handler for when the fax is initially sent
    public function sent()
    {
        $twimlResponse = new SimpleXMLElement("<Response></Response>");
        $receiveEl = $twimlResponse->addChild('Receive');
        $receiveEl->addAttribute('action', '/fax/received');

        $this->output->set_output($twimlResponse->asXML());
    }

    // Define a handler for when the fax is finished sending to us - if successful,
    // We will have a URL to the contents of the fax at this point
    public function received()
    {
        // log the URL of the PDF received in the fax
        log_message('info', $this->input->post("MediaUrl"));

        // Respond with empty 200/OK to Twilio
        $this->set_status_header(200);
        $this->output->set_output('');
    }
}
#!/usr/bin/env python
"""Fax snippet."""

from flask_script import Manager
from flask import Flask, Response, request

app = Flask(__name__)


@app.route('/fax/sent', methods=['POST'])
def fax_sent():
    """Define a handler for when the fax is initially sent."""
    # Let's manually build some TwiML. We can choose to receive the
    # fax with <Receive>, or reject with <Reject>.
    twiml = """
        <Response>
            <Receive action="/fax/received"/>
        </Response>
    """

    return Response(twiml, mimetype='text/xml')


@app.route('/fax/received', methods=['POST'])
def fax_received():
    """Define a handler for when the fax finished sending to us."""
    # We will have a URL to the contents of the fax at this point
    # log the URL of the PDF received in the fax
    print(request.form.get('MediaUrl'))

    # Respond with empty 200/OK to Twilio
    return '', 200


if __name__ == "__main__":
    Manager(app).run()
import spark.Route;

import static spark.Spark.post;

public class IndexFax {

    private static Route faxSent = (request, response) -> {
        // Let's manually build some TwiML. We can choose to receive the
        // fax with <Receive>, or reject with <Reject>.
        String twiml = "<Response>" +
                            "<Receive action=\"/fax/received\"/>" +
                        "</Response>";

        // Send Fax twiml response
        response.type("text/xml");
        return twiml;
    };

    // Define a handler for when the fax is finished sending to us - if successful,
    // We will have a URL to the contents of the fax at this point
    private static Route faxReceived  = (request, response) -> {
        // log the URL of the PDF received in the fax
        System.out.println(request.params(":mediaUrl"));

        // Respond with empty 200/OK to Twilio
        response.status(200);
        return null;
    };

    public static void main(String[] args) {
        post("/fax/sent", faxSent);

        post("/fax/received", faxReceived);
    }
}
const http = require('http');
const express = require('express');
const bodyParser = require('body-parser');

const app = express();

// Parse any incoming POST parameters
app.use(bodyParser({ extended: false }));

// Define a handler for when the fax is initially sent
app.post('/fax/sent', (req, res) => {
  // Let's manually build some TwiML. We can choose to receive the
  // fax with <Receive>, or reject with <Reject>.
  const twiml = `
  <Response>
    <Receive action="/fax/received"/>
  </Response>
  `;

  // Send Fax twiml response
  res.type('text/xml');
  res.send(twiml);
});

// Define a handler for when the fax is finished sending to us - if successful,
// We will have a URL to the contents of the fax at this point
app.post('/fax/received', (req, res) => {
  // log the URL of the PDF received in the fax
  console.log(req.body.MediaUrl);

  // Respond with empty 200/OK to Twilio
  res.status(200);
  res.send();
});

// Start the web server
http.createServer(app).listen(3000, () => {
  console.log('Express server listening on port 3000');
});
testable: false