Record Bad Customer Service Calls in 30 Lines of Ruby

tl;dr If you’d like to record a phone call, three-way call 888.909.1024 or +44 203 389 52 12 into the conversation and you’ll get a text with the recording when you hang up. 

About this time last year, Ryan Block’s “Comcast Call from Hell” made the social network rounds. It was an infuriating eight minute clip of him trying to cancel his service but getting stonewalled by the customer service rep repeatedly asking questions like, “Why is it that you aren’t wanting to have the number one Internet service available?”

Fortunately, Ryan recorded the phone call for, let’s say, “quality assurance purposes.” When it went viral, Comcast stepped in, apologized and made things right.

But what if he hadn’t had that recording?

Next time you find yourself in Ryan’s shoes, ask the rep to hold for a few seconds and three-way call 888.909.1024 (or+44 203 389 52 12 in the UK) into the conversation (and for the sake of staying on the right side of wiretapping laws, tell them that they’re being recorded). When you hang up, you’ll get a text with a link to the recording.


This hack lets you record a call on any iPhone or Android device without installing an app, and it was built using only thirty lines of Ruby:

In the rest of this post, we’ll break down this code in hopes that it can serve as the foundation for your own recording project.

Getting Started

Before we start coding, we’ve got some setup to do.

First, buy a voice and SMS enabled phone number from your Twilio Dashboard (if you’re in the United States, all numbers fit this criteria).


Second, download ngrok which we’ll use to give your local machine a publicly accessible URL (for more details, check out Kevin Whinnery’s brief ngrok tutorial).

Once downloaded, you’ll start ngrok from the command line by passing in the port your server uses. Since Sinatra’s default port is 4567, run it like this (and make sure you leave it running for the rest of this tutorial):


ngrok has created a tunnel through which Twilio can send HTTP requests to our local development machine. We’re going to do two things with that ngrok URL:

  • Set it as an environment variable called BASE_URL. There are about eighteen ways to set environment variables for Ruby. I’ll defer to Phil Nash’s excellent post on environment variables to explain those. Here we’ll do it the simplest way by running this in a shell:
  • Paste that URL into the Voice request field on your Twilio number page, then append /call  to it, then save it (we will write the code to handle this request in the next section). Final product should look like this:

6442tg5tqbzCw_YCWdwaUH0Ce4M5Rqhzgst7v-YTESvsx5pXRrgjvtDu7-Y1VSGd2FDIU2A7tr9UkOj0vdnEB0-xi9wG327rkOj-GZLTSVbYqpmQGIUo9sppNKeJ3iYdSPdMII0Third, we need to set up our Ruby project. Create a new directory wherever you keep your code, then change into it:

If you use an environment manager like rvm or rbenv (and you should), set that up here:

Back out and back into your directory for those settings to take effect:

Create a new Gemfile and add Sinatra and the Twilio Ruby gems:

Back in the shell, install bundler, then your gems:

Create a file called app.rb  and require our two gems at the top of that file:

With our plumbing in place, we can now move on to the code to power our call recording.

Record a Phone Call in Ruby

When someone calls our Twilio phone number, Twilio makes a POST request to that URL you just copied into your dashboard. Twilio expects a response in the form of Twilio-flavored XML called TwiML. We can use the Twilio Ruby gem to generate this XML instead of writing it out by hand.

Our TwiML does two things:

  • Greet the caller in a robot voice
  • Record the call

To generate the TwiML, add this code to the bottom of app.rb:

Those last two lines set the response headers to return XML and then return the text of the generated response.

Back in your shell, start your server:

Then call your number and say something worthy of recording. Once you hang up, check out your Twilio recording logs and listen to your message.

That’s it! Eight lines to record a phone call. Pretty cool, huh?

Send an SMS in Ruby

Of course, that recording doesn’t do the caller much good if they have to sign into your Twilio dashboard to play to it. That’s okay though! Recordings are saved at publicly accessible, though highly obfuscated URLs, and it’s easy to text them a link to it.

To initiate an outbound SMS, we need the account credentials found on our account dashboard:


Kill your Sinatra server, then set these values as environment variables:

Back in app.rb, paste this code to create a method that will instantiate a Twilio REST client using your account credentials:

With this client we can connect to Twilio’s REST API and send an SMS. And when do we want to send an SMS? That’s right, when the recording is finished.

We can add a callback URL to our <Record>  verb that will be called when recording finishes.

In the post '/call'  method, and replace the r.Record  line with this:

Now when recording is finished, Twilio will make a POST request to the ‘/after-record’ route (which we will soon create). Included in the parameters of that request will be three pieces of information of particular interest to us:

  • params['From']  – The phone number of the caller
  • params['To']  – The Twilio number that was called
  • params['RecordingUrl']  – the publicly accessible URL of the recording

These parameters match up nicely with the three pieces of information we need to send a text message:

  • What phone number gets the SMS? The number of the person who called.
  • What number sends the SMS? Our Twilio number.
  • What’s in the body of the message? The recording url.

At the end of app.rb , paste this code to create the /after-call  handler:

As for the 200  return value at the end — that’s to be a good web citizen by responding to Twilio’s HTTP request with a success code.

Restart your Sinatra server, give your phone number a call, say something funny before hanging up, then wait for the text message to roll in.

Next Steps

Thirty lines of code and you’ve got a service to protect consumers from the pains of bad customer service. But that’s just the beginning. Building on this foundation, you could:

  • Build a web interface where folks can share their good and bad customer experiences with the rest of the world. They could sign-in using their phone number as a user ID and a PIN sent to them via SMS (it’s super simple to do this using Authy).
  • Create a service for podcasters and journalists to interview folks. You could even turn on the transcription tag to help create show notes. That would look like:
  • Use the <Gather> verb to build a phone tree (or “IVR” in telecom speak) with custom voicemails for everyone in your company.

Whatever you build, I’d love to see it. Let me know at @greggyb or


    Wire tapping laws (for private persons) are ridiculous. Why should anyone be required to indicate that a person should tell the truth because what they say is being recorded. If someone says something awful that’s caught on a recording they should stand by what they said instead of complaining that “they didn’t know there would be proof they said the awful thing”.

  • Mandela MusicAgent Manga

    can one provide with how to do this in php?