Category: Google Voice

How to use Google Voice with FreePBX and Asterisk without using XMPP or buying new hardware

This post has been edited to include new and changed information.

Unfortunately, the original method described below worked for a time in mid-2018. It has not worked at all since then, for one simple reason: Something has changed on Google’s web site and the PyGoogleVoice script that is central to this method no longer works, period. If you run it from the command line, you just get a bunch of errors.

The source code for PyGoogleVoice is here. If you are conversant in Python, maybe you can fork the project and make a version that works. If so, it would be much appreciated if you would share your working version. There is a discussion here that may be informative, but it appears further development has stalled.

Or, if you are conversant in PHP, there is a PHP script posted here that works in a similar manner to PyGoogleVoice. Maybe you can modify it and get that one to work, and if so again it would be appreciated it you’d post the working version.

Or, there is something called selgooglevoice which is “A Selenium with Python replacement for pygooglevoice.” If someone could post detailed instructions for getting this to work, it would be appreciated. If it is using Selenium as the name implies, then it may be that you’d need to have a web browser running, which of course is not possible on a typical Asterisk/FreePBX server with no desktop environment. This is a case where code exists, but there is pretty much zero information on how to use it. EDIT: Jeff Dobkin posted a comment about using selgooglevoice on June 4, 2021 in the comments section, so apparently at least one person has it working! EDIT 2: It may be possible to use Selenium with a “headless” browser which would NOT require a desktop environment. See Setup Selenium with Python and Chrome on Ubuntu & Debian for possible installation instructions – we have NOT tested this but please leave a comment if you get it to work!

Perhaps the most promising potential solution that I have come across so far is contained in this thread about UI.Vision RPA. As shown in December 2023, it will only work with a single Google Voice account, and you must have the Google Chrome browser up and running and you must already be logged into Google Voice. Given the relative simplicity of the script, it might not be that difficult to modify it to support logging into Google Voice, setting up the call, and then logging out (so that multiple Google Voice accounts could be used). However, keep in mind that Google occasionally throws a curve ball during the login process by bringing up an unexpected screen or popup (usually related to security), so you would need to be able to detect and/or bypass that, and also I have read in various places that Google attempts to detect and block automated logins, and if that is the case it may make logging in a lot more difficult than I had originally envisioned. And, as with selgooglevoice, you would probably want to have Google Chrome (or Chromium, or probably any Chrome-based browser that will work with the UI.Vision RPA extension) running on the same system as Asterisk and FreePBX, which would probably mean you’d need to use a desktop version of Debian (or whatever Linux distro you use), although it could possibly be a very lightweight desktop environment (unless perhaps you can figure out how to make “headless Chrome” or “headless Chromium” work in this application). If you can get this to work, you may be able to use it in a similar manner to the way PyGoogleVoice was used in the instructions below, but it probably won’t be nearly as easy to set up.

I had previously suggested that you might also want to keep an eye on this thread, GV Outbound Calls After EOL in the hope that something useful might be posted there. Another thread that was started by the same person is here: GV Callback script. The major issue with the solution posted in those threads is that the script shown only runs on Windows, which of course means it cannot be run on the same system as Asterisk and FreePBX (and for many users involves paying for a Windows license). And given the Windows propensity to do system upgrades at inopportune times, this is not a solution I would trust.

If no one is able to fix any of these scripts (to support logging into Google Voice, setting up the call, and then logging out), the method shown below will not work at all, ever, period. We now seem to have entered an era where no one wants to post complete instructions on how they get something like this running, or if they do the major search engines won’t index it (for example, as I write this there are no links on either Google or Bing to the thread about UI.Vision RPA that I linked above). I have been searching in vain for a web article or video that would show all the steps involved in getting something like this working with Asterisk and FreePBX, to no avail. There are pieces here and there, but no one is combining those pieces and explaining how they did it. Even this article is rarely accessed anymore, though that is understandable because I’m not able to provide a complete solution here.

Up until mid-December of 2023, the only semi-reliable method for connecting FreePBX to Asterisk involved the use of an Obihai/Polycom device 🤮, for example using the method shown here to connect Google Voice to FreePBX. But now the OBi200, OBi202 and OBi212 are considered obsolete, and if you have not already set one up to work with Google Voice you are probably out of luck, first because they are no longer being sold, but even if you could obtain one, the Obitalk configuration portal no longer supports those devices, so you cannot now set them up to use Google Voice. And if your device configuration is ever lost for any reason, you will not be able to add your Google Voice settings back in.

The only other possible option available now for such devices that were not configured while the Obitak portal was still functional or that have lost their configuration (which, by the way, is an option that the self-proclaimed “Google Voice Product Expert” you may encounter in various forums will never tell you about, nor allow anyone else to tell you about in the forums he moderates) is to use third party firmware and then read this very long thread for further instructions. This will require you to have a certain degree of technical prowess (and to assume responsibility if you manage to put your Obihai/Polycom device into a completely non-functional state). But, ultimately no one knows how long the OBi devices that still support Google Voice will continue to do so, so if you don’t already have an Obihai/Polycom device that is working with Google Voice, I do not advise trying to obtain one – it could be a lot of hassle for something that will only work for a short time, if it works at all.

So, it appears those are your two choices if you want to continue using Google Voice with FreePBX – use hardware that is now considered obsolete and that has already been set up to use Google Voice prior to mid-December, 2023 or figure out how to make one of the scripts work. There is a third choice mentioned on some other sites (naf’s GVSIP) but if you go that route you’ll find that it’s a bit of a pain in the butt to set up and get working unless you are very experienced (though maybe easier than any other solution proposed above), and you run the very real risk that Google will shut down your Google Voice account if they catch you using it, though to my knowledge so far no one has reported that their account has been shut down for that reason.

I’m leaving this article here in case someone does manage to rewrite one of the scripts, but please be aware that if you attempt to do this, I’m sorry to say that you’ll probably be disappointed with the results if you don’t or can’t fix one of the scripts so that it works reliably. If you do, please leave a comment and share how you did it! Also please be aware that much of the information in the text below has become obsolete. For example, Callcentric no longer offers free DID’s; their price for a residential DID is currently $1/month in December, 2023 (you may be able to get similar deals from other providers).

In mid-July, 2018 Google Voice shut down XMPP access. The problem is that if you have been using the Google Voice module in FreePBX, it used the XMPP protocol to connect to Google Voice, and that’s what no longer works.

Various possible solutions are being offered, including buying a new VoIP device and using it as a bridge between Asterisk and Google Voice. Unfortunately, at the time of this writing such devices are made by only one manufacturer, Obihai, a company I could not possibly have a lower opinion of. I used to like and support Obihai, but they have nuked any warm and fuzzy feelings I had for them in the past, several times over. My opinion now is that if you buy a new Obihai device, then P.T. Barnum was right when he said that there’s a sucker born every minute, and when you were born you fulfilled the quota for that minute! But, this is not intended to be a rant about Obihai (you can find those all over the VoIP forums, except in Obihai’s own heavily censored forum), but rather a way to keep using Google Voice with FreePBX and Asterisk, so you don’t need to buy any new hardware.

The FreePBX Google Voice module has become useless, so this method may be a bit more “hands on” than you are used to. To cut to the chase, the basic technique can be found in one of RonR’s posts in the above-mentioned DSLReports thread. Go ahead and open that up in another tab in your browser, because I’ll be referencing it throughout this article. But, that post only provides some basic configuration information, and makes some assumptions that are not clearly stated, such as that you are using FreePBX and that you already know how to perform basic administrative tasks such as creating a SIP trunk. While the general technique shown will also work with bare Asterisk (no FreePBX) or with other Asterisk-based GUI’s, you’re pretty much on your own in making the necessary dialplan modifications, or you could try following Twinclouds’ instructions (as mentioned in his comment on this article), which use a mostly similar but slightly different technique.

I should probably warn you here that this technique could potentially stop working at any time. It’s worked for years now, but when dealing with Google that doesn’t necessarily mean anything. There have been reports in late 2018 that although incoming Google Voice calls always seem to complete, outgoing calls to Google Voice will sometimes fail repeatedly for a period of time, particularly during daytime hours. Also, by publishing this I am explicitly NOT commenting on whether Google would approve of its use – I don’t work for Google, and I’m not a lawyer. If you suspect that using this technique may violate Google’s Terms of Service or some such thing, then please don’t use it until you consult with your own attorney. If you try anything shown in this post you are doing so of your own volition and at your own risk. I will not be responsible for any consequences that may occur. With that in mind, if you still want to try this technique, here’s what you need to do.

First, you must have a number coming into your system that is NOT a Google Voice number. This is sometimes referred to as a DID (and will be called that in this article), and if you don’t already have one, it is possible to get free DID’s from Callcentric. You need to have at least one DID coming into your Asterisk server, and you need to configure it as a destination (forwarding number) in your Google Voice account. So get your DID working first, and make sure you can make incoming calls to it using its assigned number. Then go into your Google Voice account(s) and set it/them up to forward calls to the DID. If you have already set up a forwarding number at some point in the past, you may still want to log in to Google Voice and check to make sure it doesn’t need to be re-validated – if you have let it lapse into an unvalidated state, Google Voice won’t forward calls to it until you re-validate it. If you tell Google Voice that the number is a “Work” number (you may need to go into “Legacy Google Voice” to do that), it can be used as a forwarding destination for at least two Google Voice accounts, and it is possible use one DID with two Google Voice accounts. So once you have your DID set up, you should be able to call your Google Voice number, and it will forward the call to your DID, and then the DID will send the call on to your Asterisk server. Note: If using Callcentric, you may wish to refer to this post: How to receive incoming Callcentric calls in FreePBX without creating multiple trunks.

Assuming you have your incoming DID working and Google Voice configured to use it as a destination, and you have tested it to make sure that the forwarding to your DID works when you call your Google Voice number, the next thing to do is is make a test call using pygooglevoice. But first you should determine whether it is installed on your system. From a Linux command prompt, enter which gvoice – if it returns a path such as /usr/bin/gvoice then it is already installed. If no path is returned, then install it using the instructions in RonR’s post mentioned above. EDIT: I’m interrupting this to note that RonR released a newer version written in PHP rather than Python, called gvcallback, which is an adaptation of an earlier program (you can read the entire thread if interested). However the syntax for calling the program isn’t exactly the same as with PyGooglVoice (though it’s very close) so you’d need to make some adaptations to the following instructions to account for the different syntax. The possible advantage of using the gvcallback program is that you don’t have to install all the dependencies that you have to install to get PyGoogleVoice to work. However, if you already have PyGoogleVoice installed on your system, there’s no compelling reason to switch to gvcallback that I’m aware of. Continuing on with the article…

Once PyGoogleVoice is installed, from a Linux command prompt, enter gvoice – it should prompt you for your Google Voice email address and password. If it connects successfully, you will see a prompt that looks like this: gvoice>. If you see a bunch of error messages (this is not unusual on the first run), refer to this DSLReports post by Cam_, which shows some of the things you may need to do to get it working. In addition, you may also need to let less secure apps access your Google account. (EDIT: Also see this DSLReports post by AllThumbs which notes that in addition to allowing less secure apps using this link, while logged into your Google Voice account and just prior to running pygooglevoice you may also need to visit this “Allow access to your Google account” link to get it working. Immediately after you click the “Continue” button, run pygooglevoice so that Google knows which “new device or application” you are trying to allow access from. Then, log into Gmail using your Google Voice account and check the Inbox – there will probably be an email from Google asking you to confirm that it was really you that just logged in, if so, do whatever the email tells you to do to confirm it. AllThumbs’ DSLReports post implies that you may have to do this again from time to time, and that will be particularly true if you don’t respond to any email Google may send asking for confirmation that it was really you, so save notes on this process. Yes, Google’s ultra-paranoid security can be a real pain in the butt sometimes).

If you think you may have a bad or old version of pygooglevoice, prior to reinstalling remove the following files from the /usr/bin directory: asterisk-gvoice-setup, gvi, and gvoice, and also check any /user/lib/python*/site-packages directories you may have for a directory called googlevoice and/or a file that starts with “pygooglevoice” and if you find either of those, remove those as well. Otherwise you may wind up with a mixture of files from the old and new versions, and that usually won’t work (also, do not run asterisk-gvoice-setup, it’s not meant for what we’re doing here).  Note that there is a current version of pygooglevoice included in a download link in RonR’s post.

If you do get the gvoice> prompt, then enter the word call, and then it should prompt you for the outgoing number, which can be almost any valid 10 digit number in the USA or Canada. After that, it will prompt you for “Forwarding number [optional]:” but it really isn’t optional. What it is wanting here is one of your validated Google Voice destination numbers, such as your DID – NOT your Google Voice number! – and it wants it in the format +1 plus the ten digit number. If you try using just the ten digit number alone, it won’t work (at least not in my tests), it has to be in the form +1XXXXXXXXXX. Finally it will ask for the phone type; if you specified the number as a “work” number in the Google Voice interface then use 3. If you don’t remember how you specified it, try all three of the digits 1 through 3, one at a time – one of those should work. It may not actually matter if this number is correct in some cases; I’ve seen “1” work when the number had been specified as a “Work” number, for which the code should be “3”, but that’s not always the case.

If you entered everything correctly, you should not see any error messages, and in second or two a call should come in on your DID (hopefully you have created an Inbound Route, and made a nearby extension the temporary destination), and when you answer it you should hear the destination number start ringing. This part MUST work before you go any further – if you can’t get this to work then there is no point in doing any further configuration, because it won’t work either.

If it does work, you have a choice at this point. You can follow RonR’s instructions verbatim, which are probably fine if you are only dealing with one or two Google Voice accounts. But if you are dealing with a higher number of accounts, or if you just don’t like the fact that he hardcodes Parking Lot extension numbers, or if you don’t care to install and configure the Parking Lot module, you should know that I have made some modifications to his method, which I have added at the bottom of this article. For now you can do it either way, but be aware that because he hardcodes Parking Lot extensions, it will be impossible to place two calls on the same Google Voice account at the same time. However it may be impossible to do that anyway, if Google limits the number of simultaneous connections per account to three or fewer. Remember that with this method, there are actually two calls being placed from your account for each call you make – one to call your DID, and one to connect your call through to the called party.

I prefer not to use the Parking Lot at all, and instead to use Asterisk’s Bridge application, which I feel is much more suitable for this purpose, as I will explain in a moment. I do have some additional notes on using RonR’s original method, but I have moved them to the bottom of this article to make it a bit easier to read.

There is a caveat here. If Google changes their authentication protocols, this method could stop working until a pygooglevoice maintainer comes up with a patch. It’s happened before, though rarely, and it could happen again. If it does, incoming calls would still work, but outgoing calls would fail until the pygooglevoice code is modified to account for the change.

One other possible drawback to this method is that because pygooglevoice is considered a “less secure” app, Google may nag you with a “Security Alert” email every single time you place a call! One would hope that after you’ve confirmed that it was really you a few times, the emails would at some point stop, but if they don’t there is a way to turn them off – however in that case you won’t be notified if someone else really does try to hack your account. This is the method, according to Google:

We strongly advise leaving alerts on so you can hear about suspicious activity on your account. If you still want to disable alerts, follow the steps below.

Note: It takes about a week for alerts to get turned off. This is because Gmail wants to confirm it’s you that’s turning them off, and not someone else who might have access to your account.

  1. On your computer, open Gmail.
  2. In the bottom right, click Details.
  3. At the bottom of the page next to “Alert preference,” click Change.
  4. Select Never show an alert for unusual activity.

I have discovered that you don’t see the “Details” link unless you switch to the “basic HTML” view.

Here is my revision of RonR’s method – this uses Asterisk’s Bridge application, rather than the Asterisk Parking Lot. The advantage of using Bridge is that you don’t have to deal with the Parking Lot at all (you don’t even need to have the FreePBX Parking Lot module installed), and therefore the number of simultaneous calls is not limited to the number of available Parking Lot slots. Also you don’t have to worry about the changes in the “Park” application syntax between Asterisk versions. And, this method is better about cleaning up after itself, by removing database entries it has created after they are no longer needed. The only disadvantage is that the custom dialplan is slightly more complex.

If for some reason you really prefer to use the Asterisk Parking Lot (which I do NOT recommend), I do show alternative contexts that you can use, that more gracefully deal with a larger number of Google Voice accounts because they assign Parking Lot extensions starting with the highest available, and working down until one is found that is not in use. They are set to start with extension 78 and work down to 71. If you think there might ever be more than eight simultaneous outgoing Google Voice calls then you may need to extend the range of available Parking Lot extensions, but I think this will work for most people.

The instructions for installing PyGoogleVoice are the same (so refer to his post for that), but here’s how I configured it – note that values that you must change are in bold type:

Connectivity -> Trunks -> Add Custom Trunk

Trunk Name : username
Custom Dial String : LOCAL/$OUTNUM$@custom-username-out

Trunk Name : user2name
Custom Dial String : LOCAL/$OUTNUM$@custom-user2name-out

… and so on …

To help you keep the accounts straight, the user names should be the the same as the part of the Google Voice login names before the @ symbol. So if the login name is, the username would be just foo. This will be the case wherever you see “username” or “user2name” in bold.

Connectivity -> Outbound Routes -> Add Route

Route Name : username
Dial Pattern : see discussion below
Trunk Seq : username

Route Name : user2name
Dial Pattern : see discussion below
Trunk Seq : user2name

… and so on …

RonR only showed the dial pattern NXXNXXXXXX but that is only valid if your system only allows 10 digit dialing, and it doesn’t restrict a route to use by a particular extension. Possible patterns you might want to use include, but are not limited to:

NXXNXXXXXX/eee (where eee is a specific extension number that can use this route, and you can use patterns here such as 10X for all extensions in the range 100 to 109, or multiple instances of this line if needed for non-contiguous extensions).
1|NXXNXXXXXX/eee (same as above except allows dialing calls with a leading “1”, in case you allow 11 digit dialing)
aaa+NXXXXXX/eee (same as above except allows 7 digit calls to a particular area code, in case you allow 7 digit dialing – replace aaa with the area code)

The basic point here is that Google Voice expects to receive the called number as 10 digits, with no leading 1.

Admin -> Custom Destinations -> Add Custom Destination

Custom Destination : custom-NXXNXXXXXX-in,s,1
Description : Incoming calls NXXNXXXXXX

You need one Custom Destination for each DID you have coming into your system that is used by Google Voice. Replace “NXXNXXXXXX” with the 10 digit DID number, NOT your Google Voice number. Again, this change is just for your convenience in keeping everything straight.

Connectivity -> Inbound Route -> Callback Number
Destination : Custom Destination -> Incoming calls NXXNXXXXXX

Here you are making an Inbound Route for your DID, and sending it to the Custom Destination that contains the phone number of the DID, that was created in the previous step. So again, you need one of these Inbound Routes for each DID you have coming into your system that is used by Google Voice. In this case the Description can be anything you find meaningful. Leave ALL the other settings at the default – in particular do not enable “Detect Faxes” or “CID Superfecta”, or anything that might slow processing of the incoming call. If you need any of those features in incoming calls, you can enable them in the next section:

Connectivity -> Inbound Route -> Add Incoming Route

Destination : Normal destination for this number

Here the DID number is the same as in the previous step except there is an added * character at the end. This is the Inbound Route for your DID that is used when it is NOT a Google Voice callback that arrives because you are making an outgoing call. In other words, if someone other than Google Voice calls your Google Voice number, or calls the DID that your Google Voice number is forwarded to directly, the call will wind up here, so normally you’d want the destination to be an Extension, Ring Group, IVR, or whatever. Since by the time the call gets here you know it’s NOT a Google Voice callback, you can enable features like Detect Faxes or CID Superfecta if you like. Again, the Description can be anything you find meaningful.

Additions to /etc/asterisk/extensions_custom.conf – first, the common contexts used by all accounts – these contexts are only added once, no matter how many Google Voice accounts or DID’s you have. I suggest using the “bridge” method rather than the Parking Lot method:

exten => _X.,1,System(gvoice -b -e ${ACCTUSER} -p ${ACCTPASS} call ${EXTEN} +${RINGBACK} 1 &)
exten => _X.,n,Set(DB(gv_dialout_${CUT(ACCTUSER,@,1)}/channel)=${CHANNEL})
exten => _X.,n,Wait(25)
; The following Noop lines are NOT optional, do not delete them
exten => _X.,n,Noop(Never received callback from Google Voice on channel ${DB_DELETE(gv_dialout_${CUT(ACCTUSER,@,1)}/channel)} – exiting)
exten => _X.,n,Goto(custom-gv-error,s,1)
exten => h,1,Noop(User hung up while waiting for callback from Google Voice on channel ${DB_DELETE(gv_dialout_${CUT(ACCTUSER,@,1)}/channel)})
exten => h,n,Macro(hangupcall,)

Do NOT remove the Noop lines, they contain the function that deletes the unused database item if for some reason the returned call from Google is never received, or if the user hangs up before the callback is received. If you want your callers to hear Music on Hold rather than silence while waiting for the callback, replace

exten => _X.,n,Wait(25)


exten => _X.,n,Answer
exten => _X.,n,MusicOnHold(default,25)

You do have to “answer” the call or the music will not be heard. You can optionally replace “default” with any other valid Music on Hold context you have created.


exten => _X.,1,Set(PARKINGEXTEN=79)
exten => _X.,n(parkloop),Set(PARKINGEXTEN=$[${PARKINGEXTEN} - 1])
exten => _X.,n,GotoIf($["${EXTENSION_STATE(${PARKINGEXTEN}@park-hints)}" != "NOT_INUSE"]?parkloop)
exten => _X.,n,GotoIf($["${PARKINGEXTEN}" < "71"]?custom-gv-error,s,1)
exten => _X.,n,Set(DB(gv_dialout_${CUT(ACCTUSER,@,1)}/parkslot)=${PARKINGEXTEN})
exten => _X.,n,System(gvoice -b -e ${ACCTUSER} -p ${ACCTPASS} call ${EXTEN} +${RINGBACK} 1 &)
exten => _X.,n,Park(default,t(25)c(custom-gv-error,s,1)rs)
;exten => _X.,n,Park(15000,custom-gv-error,s,1,rs)
exten => h,1,Macro(hangupcall,)

This is the custom-gv-out-common context as used in the “Parking Lot” method. In the first line, 79 is one greater than the highest numbered Parking Lot extension (by default the Parking Lot uses parking extensions 71-78). You may need to change that if you increase the number of Parking Lot extensions. Also, I may be wrong but I believe that for the “${EXTENSION_STATE(${PARKINGEXTEN}@park-hints)}” function to work correctly, the “BLF Capabilities” setting in the FreePBX Parking module must be set to Enabled. While you’re in the Parking configuration, you may wish to set the “Pickup Courtesy Tone” option to None if you don’t want the beep tone when the callback arrives.

If you have an older version of Asterisk you might need to switch which of the “Park” lines is commented out – the one that is uncommented now is for newer versions of Asterisk. Also in the Park lines, the “r” in the “rs” signifies that you want fake ringing generated while waiting for the callback – if you omit it, it will play Music on Hold as specified in the “Parked Music Class” option in the FreePBX Parking module.

Two more additions to /etc/asterisk/extensions_custom.conf – Again these contexts are added only once. The second one is needed only if you are using the “bridge” method, which I recommend:

exten => s,1,Playback(silence/1&cannot-complete-as-dialed)
exten => s,n,Wait(1)
exten => s,n,Playtones(congestion)
exten => s,n,Wait(10)
exten => s,n,StopPlaytones
exten => s,n,Hangup()
exten => h,1,Macro(hangupcall,)

The above is straight from RonR’s original instructions except for the hangup handler at the end; other than that only the context name is changed. When everything is working as it should, this context should rarely be used.

exten => s,1,Answer
exten => s,n,Wait(1)
exten => s,n,Hangup()

The only real drawback of the “bridge” method is that if a user changes their mind about placing a call, and hangs up before the callback is received from Google Voice, Asterisk doesn’t know what to do with the callback unless you explicitly tell it what to do. So this answers the call and then hangs up, after a one second delay. In previous incarnations of this method there was a “cancel” option in pygooglevoice that could be used to cancel a call. The “cancel” function still seems to exist in pygooglevoice, but in testing it doesn’t seem to actually do anything, at least not for several seconds. I watched as Asterisk repeatedly sent the pygooglevoice cancel, only to see the call come right back in, and that loop lasted several seconds! So, it appears that the only reliable way to cancel the callback is to answer it and then hang up. If you want to experiment with the pygooglevoice cancel option, the syntax is simply:

exten => s,n,System(gvoice -b -e -p password cancel &)

But if you can get it to work, you are having better luck than I did.

User-specific additions to /etc/asterisk/extensions_custom.conf – You must create these contexts for each user account or DID, as explained below:

exten => _X.,1,Set(
exten => _X.,n,Set(ACCTPASS=password)
exten => _X.,n,Set(RINGBACK=1NXXNXXXXXX)
exten => _X.,n,Goto(custom-gv-out-common,${EXTEN},1)
exten => h,1,Macro(hangupcall,)

You need one of the above for each Google Voice account, and you must change the username value in both places (don’t skip the context name) and the password value, and set the RINGBACK setting to the 11-digit DID number associated with this account (NOT your Google Voice number). “username” is just the part of the Google Voice login name before the @ symbol, same as in the Custom Trunks. If you are one of the very few people who has a Google Voice account where the login name doesn’t end in, then change that in the ACCTUSER setting as well.

exten => s,1,GotoIf($["${CALLERID(number)}" = "Google Voice Number"]?cb1)
;exten => s,n,GotoIf($["${CALLERID(number)}" = "Google Voice Number 2"]?cb2);
exten => s,n,Goto(from-trunk,NXXNXXXXXX*,1)
exten => s,n(cb1),NoCDR()
exten => s,n,GotoIf($[${ISNULL(${DB(gv_dialout_username/channel)})}]?custom-gv-cancel,s,1)
exten => s,n,Bridge(${DB_DELETE(gv_dialout_username/channel)})
exten => s,n,Hangup()
;exten => s,n(cb2),NoCDR()
;exten => s,n,GotoIf($[${ISNULL(${DB(gv_dialout_user2name/channel)})}]?custom-gv-cancel,s,1)
;exten => s,n,Bridge(${DB_DELETE(gv_dialout_user2name/channel)})
;exten => s,n,Hangup()
exten => h,1,Macro(hangupcall,)

This uses the “bridge” method, which I recommend. You need one of the above for each of your DID’s that Google Voice sends calls to. You can have one or two Google Voice accounts coming to a DID if you have specified the DID as a “Work” phone in both accounts. If you have two, then uncomment the five commented-out lines. As usual, replace both instances of NXXNXXXXXX with the DID number (don’t skip the context name, and don’t lose the * character at the end of the number in the Goto line). “Google Voice Number” and (optionally) “Google Voice Number 2” should be replaced by the Google Voice numbers associated with your accounts in 10-digit format (no leading +1 here). “username” and (optionally) “user2name” are once again just the part of the Google Voice login names before the @ symbol – make sure to change them in both lines where they appear.


exten => s,1,GotoIf($["${CALLERID(number)}" = "Google Voice Number"]?cb1)
;exten => s,n,GotoIf($["${CALLERID(number)}" = "Google Voice Number 2"]?cb2);
exten => s,n,Goto(from-trunk,NXXNXXXXXX*,1)
exten => s,n(cb1),ParkedCall(default,${DB_DELETE(gv_dialout_username/parkslot)})
;exten => s,n(cb2),ParkedCall(default,${DB_DELETE(gv_dialout_user2name/parkslot)})
exten => h,1,Macro(hangupcall,)

This is the custom-NXXNXXXXXX-in context as used in the “Parking Lot” method. You need one of the above for each of your DID’s that Google Voice sends calls to. You can have one or two Google Voice accounts coming to a DID if you have specified the DID as a “Work” phone in both accounts. If you have two, then uncomment the two commented-out lines. As usual, replace both instances of NXXNXXXXXX with the DID number (don’t skip the context name, and don’t lose the * character at the end of the number in the Goto line). “Google Voice Number” and (optionally) “Google Voice Number 2” should be replaced by the Google Voice numbers associated with your accounts in 10-digit format (no leading +1 here). “username” and “user2name” are once again just the part of the Google Voice login names before the @ symbol. In the last two lines, in the ParkedCall options, you may need to omit the string “default,” if you are using an older version of Asterisk, because at some point prior to the current version the order of the items was flipped. In current versions the Parking Lot name is specified first, followed by the Parking Lot extension (which in this case is retrieved from a temporary database location), but in older versions the Parking Lot extension was given first, and then optionally the Parking Lot name.

EDIT: When using this method, you may run into a weird issue if you set one or more of your Inbound Routes for DID’s used by Google Voice to “Force Answer” under the Advanced tab, as you might if you are trying to keep calls from ever going to Google’s voicemail, or if your calls are answered immediately by an announcement or an IVR or by an Asterisk voicemail greeting or something similar. What happens is that when Google Voice forwards a call to a DID, and it’s not a “callback” of the type that the system receives when placing an outgoing call, you cannot answer the call too quickly. If you do, you will hear nothing but silence while the caller will continue to hear ringing until the call is sent to Google’s voicemail, which is in many cases exactly what you are trying to avoid.

In FreePBX inbound routes there is a setting called “Pause Before Answer” but for whatever reason it doesn’t seem to fix this problem. I think perhaps that may be because it doesn’t send a Ringing signal back to Google Voice, and Google Voice apparently really wants to see a couple seconds of Ringing before it will let the call audio go through!

So the only solution is to create a custom context in /etc/asterisk/extensions_custom.conf and then use that as the Context in the trunk associated with the provider of your DIDs. Here’s an example context:

exten => DID1/GV1,1,Goto(from-pstn-e164-us,${EXTEN},1)
exten => DID1/GV2,1,Goto(from-pstn-e164-us,${EXTEN},1)
exten => DID2/GV1,1,Goto(from-pstn-e164-us,${EXTEN},1)
exten => DID2/GV2,1,Goto(from-pstn-e164-us,${EXTEN},1)
exten => _X!,1,Ringing()
exten => _X!,n,Wait(2)
exten => _X!,n,Goto(from-pstn-e164-us,${EXTEN},1)
exten => h,1,Macro(hangupcall,)

The four lines that include DIDx and GVx are just examples – you would replace DIDx with your DIDs that you use with Google Voice (only the ones that are used for Google Voice callbacks when you are placing outgoing calls), and replace GVx with the one or two Google Voice numbers you have forwarded to that particular DID. So you might have only one such line, or you might have a few, depending on how many Google Voice numbers come into your system. The purpose of those lines is to avoid the delay when placing an outgoing call, because in that specific case it’s apparently not needed. The rest of the context puts the trunk in a Ringing state, delays two seconds, and then lets the call proceed to its ultimate destination. If your current trunk Context is not “from-pstn-e164-us” you can substitute whatever context it’s currently using in all the above lines where that context is referenced.

Change the Wait value if two seconds isn’t sufficient. This seems to be somewhat of a regional thing – in certain areas it seems no delays are needed at all, while in other areas an even longer delay might be required. Test using different delay values until you find the shortest one that lets your calls arrive reliably. Two seconds seems to be good for many people, but maybe not for all.

I’m including the following additional hints and information for those that for whatever reason really would prefer to user RonR’s original instructions, rather than the instructions shown above. I actually wrote these notes prior to documenting the above method. A small subset of these comments may still be applicable to the above method, but others clearly will not be applicable.

RonR shows two contexts, pgv-out-1 and pgv-out-2. First of all, I like to rename those to the Google Voice account names (the part of the email address before the followed by -out, but if you are going to do that, you need to change those strings in all the other places where they appear in his instructions. If you have several accounts, using more meaningful context names could make it easier to know which account you are dealing with (I do this in my revisions above). And, you don’t need the second context (pgv-out-2) unless you are using the same DID as the forwarding destination for two Google Voice accounts. In the contexts themselves, you need to replace and Passwordn with the actual login username and password for the account, and you must replace Callback Number with the actual 11 digit number of your DID (you do use the leading “1” here, but in this case the “+” character is added for you). The Callback Number is NOT your Google Voice number!

Also, the CALLPARK numbers must be unique in each context. You can see (and change) the allowable range of Parking Lot numbers by going into Applications | Parking. If you can’t find that selection, you may need to install the FreePBX Parking Lot module. Note that if you actually use the Parking Lot feature for something other than Google Voice, then make sure you use the highest available Parking Lot numbers in these contexts. If, probably like many users, you’re asking “What’s a Parking Lot doing in my PBX?” and have never used it and can’t imagine why you would, then you can use any of the allowable range of parking lot numbers (71 through 78 by default) in the CALLPARK settings.

In the pgv-out-common context there is a line that begins with exten => _X.,n,Park … and the line shown there is correct for the newest version of Asterisk, but the older ones used a much different syntax. For example, exten => _X.,n,Park(15000,pgv-error,s,1,rs) would be the correct equivalent in somewhat older versions. You may need to consult the Asterisk Wiki to figure out the proper syntax – in the left hand column, select your version of Asterisk’s Documentation, then Command Reference, then Dialplan Applications, and then Application_Park to see the proper syntax and the command options in your Asterisk version. By the way, the “r” option (in the “rs” string in the example) controls whether you hear a fake ringing tone while waiting for the callback from Google Voice – if you omit that “r”, you’ll hear the Music on Hold specified in the Parking Lot configuration for that (hopefully brief) period. I mention this only because some people may prefer not to hear a ringing tone until the called phone has actually started ringing.

Finally, the pgv-in-common context is another I like to rename, replacing pgv with something more meaningful (again you could use the Google Voice username, but that might not be appropriate if your DID is shared by two Google Voice accounts – I use the ten digit DID number in my revisions below). But again, if you change that string then you need to make the same change everywhere it appears in RonR’s instructions. In the first lines of the context, the “Google Voice Number n” strings must be replaced by the actual 10-digit Google Voice numbers, and if there’s only one Google Voice account associated with the DID then you can comment out (or remove) the line with “Google Voice Number 2” in it, and also the line with the (cb2) label. Also note that the ParkedCall(nn) statements must contain the correct parking lot numbers as set in the corresponding -out contexts. So each Parking Lot number should appear twice (and only twice), once in a -out context (or pgv-out-n if you use RonR’s naming system), and then again in a line with the (cbn) label in a -in-common context.

In the middle of the context there is a line, “exten => s,n,Goto(from-trunk,Callback Number*,1)” – here you replace “Callback Number” with the DID number that Google Voice is sending your incoming calls to, but in this case you’ll probably want it to be in 10-digit format (no leading + or 1). Do leave the * character, it’s not a typo. The purpose of this line is to handle calls that come in where someone has called your Google Voice number or your Callback Number (DID) directly, in other words when someone is calling you and the call is not a callback from Google Voice as a result of you placing an outgoing call. This line is why you’ll need a separate -in-common context for each of your DID’s used with Google Voice.

If you have multiple Google Voice accounts, then the general rule is that there has to be one -out (or pgv-out-n) context, and an associated Custom Trunk and Outbound Route for each Google Voice account. And, there must be one pgv-in-common context (if there is more than one context, each must have a unique name) for each DID that is used as a destination number by one of your Google Voice accounts, along with an associated Custom Destination. As for Inbound Routes, you’ll need two of those for each DID used by Google Voice, but one of them will have the * character appended to the phone number, as shown in RonR’s instructions. When you create the Inbound Routes, if you want to enable Caller ID Superfecta or any other type of local Caller ID lookup, do it only in the route with the * character at the end of the number. The use of any kind of Caller ID lookup on the non-starred number is pointless, and will slow down the connection time for your outgoing calls.

I also like to end all my contexts with a line of the form
exten => h,1,Macro(hangupcall,)
So just on the off chance the caller hangs up while in that part of the context, the hangup is correctly handled. But that is up to you.

It bothers me just a little that there appears to be no good way to cancel the call if the caller hangs up before the callback is received, but if that happens it appears that when the call comes in from Google the PBX will play a very short message about the parking lot number being invalid and then disconnect. So just be aware that if you call a number and then after dialing the last digit quickly change your mind and hang up, the called party’s phone may still ring once.

Up near the top of RonR’s post he shows how to set up the Outbound Routes (“Connectivity -> Outbound Routes -> Add Route”) and shows a Dial Pattern of NXXNXXXXXX which is correct for 10-digit dialing, but obviously you may need to add additional patterns if your system supports 7 or 11 digit dialing. You can limit the use of any particular Outbound Route to one or more specific extensions using Asterisk’s “ex-girlfriend logic” if you like.

That’s pretty much it. If you spot any errors, including any typos I haven’t yet caught, or know of a better way to do this, please leave a comment. This article may be updated if new information is received.

OAuth 2.0 Support for Asterisk 13, so XMPP connections to Google Voice can be made using the more secure oAuth authentication

If you are running Asterisk 13 (or are ready to upgrade to Asterisk 13) and are using it to connect to one or more Google Voice accounts, you can now use oAuth authentication instead of the problematic username/password, without resorting to the use of a pre-built distribution that may contain features you don’t need and don’t want. The details are here:

OAuth 2.0 Support for Asterisk 13

Also, if you have a Raspberry Pi and would like to make a clean build of Asterisk and FreePBX, the same author (RonR) has provided instructions here. Just be sure to select Asterisk 13 when installing if you want to use the oAuth 2.0 support:

FreePBX for the Raspberry Pi

Or, if you’re sick of FreePBX and are ready to try a new interface to Asterisk, he has you covered there as well:

XiVO PBX for the Raspberry Pi

All of the above links are to threads at DSLReports. Note that the install scripts in the last two links can take some time to run, especially on an older model Raspberry Pi where they could take a few hours to complete (I believe you must have a Raspberry Pi 2 at a minimum to use the XiVO build). But when you are through, you’ll have a nice clean install, without the extraneous and mostly non-useful stuff found in a certain pre-built image.

Read this before you pay $10 to Obihai for support


EDIT (May, 2018): FreePBX and Asterisk users that wish to continue using Google Voice after Google drops XMPP support should go here: How to use Google Voice with FreePBX and Asterisk without using XMPP or buying new hardware.

Various parts of this article have been edited numerous times throughout 2018 to reflect recent changes.

As you may be aware, I removed all of the Obihai-related articles on this blog in protest of Obihai’s decision to attempt to charge users an additional $10 support fee in order to get firmware updates, and I no longer recommend Obihai devices. Since mid-2018 there is simply no way to get older OBi100 or OBi110 devices to work with Google Voice, since Google no longer supports the XMPP protocol that those devices used, so if you own one of those devices there is no reason to upgrade the firmware or pay Obihai for continued support, which they may not even offer on those models anymore. Those devices will still continue to work fine with anything that uses standard SIP protocol, which is to say, almost any VoIP service EXCEPT Google Voice. They also work perfectly fine for extensions on a FreePBX/Asterisk based system, or any other SIP-based software PBX.

However, if you previously purchased a newer Obihai (Obi200 or OBi202 or later) and find that you need to upgrade the firmware in order to continue using Google Voice, this Reddit thread explains how to do it without paying the $10. But before you do anything else, first try dialing * * * 6 from a phone that’s connected to your Obihai device, since you might be able to upgrade the firmware that way (although that’s not likely if you are still using username and password authentication for Google Voice). If that doesn’t work, try the instructions found here:

Read this before you pay $10 to Obihai for support (Reddit)
(Also posted at DSLReports: *** READ THIS before you pay $10 to Obihai for support ***)

The first post in the thread, from Reddit user Mango123456, reads as follows:

Obihai’s $10 support fee is optional. If you wish to avoid it, you can update your firmware manually to save the $10 support fee. This solves the May 2016 problem of Google Voice not working on OBi100/OBi110.

1a) If you have an OBi100/OBi110, follow the directions to update your firmware manually. Thanks to taoman54, rchandra, yorktown, and others who contributed to this.

1b) If you have an OBi200/OBi202, you can download the latest version of the 2xx firmware here (thanks taoman54).

2) If you cannot manually update your firmware because you do not know your OBi ATA’s admin password, follow the directions to factory reset your OBi ATA.

Please note: the links are not the latest versions any more. At the time of this post, they are builds 2872 and 5110 respectively.


Note that if you are reading this article after May, 2016 there might be newer versions of the firmware available (particularly for the OBi 200 series models) but after you have installed the correct firmware from one of the above links, you should be able to get any later firmware updates by dialing * * * 6 from a phone connected to the Obihai device. For example, here is a link to a newer firmware version that apparently worked for OBi200 and OBi202 models in late 2018 (I found this link in a blog post linked on Reddit: How to use an Obihai 200 series VoIP device as a gateway between Google Voice and FreePBX and I have not tested it in any way, so use at your own risk, however the link does point to the official download site and does at least appear to download Obihai firmware).

I have also read reports of Obihai users getting new firmware if they completely removed their device from the Obitalk portal (as they would if they were going to sell the device), then did a factory reset on the device itself, and then added it back to their account in the Obitalk portal as if it were a newly-purchased device. However I cannot guarantee that will work, and you would lose your existing configuration by doing this. You will know that you have the latest firmware if it says Polycom in the upper corner, where the Obihai brand was formerly located.

If you have an older OBi100 and OBi110 model, you MAY for some reason have some interest in Crowdsourced updates for Obihai ATAs and IP Phones. I have NOT tested these personally, and I take no responsibility if they don’t work as intended. Whether you stay with the original Obihai firmware or try the modded firmware, those older devices usually continue to work perfectly well for anything other than Google Voice. However, I don’t really see buying a new unit from Obihai as a solution to restoring Google Voice connectivity, since you don’t know if or when they will come out with yet a newer model and drop support for the current models. For more current information about alternative firmware for Obihai devices, see the ObiHAI Obi100/Obi110 Firmware Mod Discussion and/or the Obihai OBi200/202/302 + OBi1022/1032/1062 firmware mods thread at DSLReports. FreePBX and Asterisk users that wish to continue using Google Voice now that Google has dropped XMPP support should go here: How to use Google Voice with FreePBX and Asterisk without using XMPP or buying new hardware.

Final word, at the end of 2021 the announcement was made that the 200-series devices are being discontinued.

Forum thread: User-specific Caller ID/whitelist/blacklist in Asterisk/FreePBX

Occasionally I see a forum thread that contains enough interesting material that it could be the start of an article, but because it’s stretched through a number of posts, I can only link to the thread. And also, because I’m not the author of any of the original posts, I can’t just copy and paste without possibly violating someone’s copyright. This is one such thread, which discusses the possibility of creating user-specific whitelists or blacklists, or Caller ID name lookup sources in FreePBX or Asterisk. The Caller ID name lookup would be most useful to Google Voice users, since Google Voice doesn’t provide a Caller ID name on incoming calls, just a number. Since there is no way that a user can add or change such listings in the FreePBX interface at present, the trick seems to be to use Google Contacts as the user’s web interface, and then import the data from the user’s Google Contacts list into the Asterisk database at periodic intervals using a cron job.

The interesting thing about this is that it appears that users can have their own individual lists, since each user would apparently have their own Google Contacts, which means that a user could blacklist a caller without blacklisting that caller for all users on the system. It may be a bit tricky to figure out what’s being done from the posts shown, but still it looks like a possibly interesting technique.

Even though FreePBX 12 now offers a contact list in the User Control Panel, there are limitations on how it can be used. What is discussed in this thread apparently does not share those limitations, but does have the limitation that any changes made will not be seen by Asterisk until the next time the Google Contacts database is imported into Asterisk’s database, which is done using some downloadable software, a python script, and a cron job.

Thread here:
User-specific Caller ID/whitelist/blacklist in Asterisk/FreePBX (

Link: Quick trick for Missing Forwards calls to Google Chat Option in Google Voice Account

Forwards calls to Google Chat is an important option for people who are using Google Voice as free VOIP solution. In order to able to receive calling, forwards calls to Google Chat option must be activated so the VOIP adapter can acts as a Google Chat to receive calling, eg: OBi Devices. Without that, the phone will never ring when people call your Google Voice number.

If the Google Voice Account was newly set up, in default the “Forwards calls to Google Chat” option is inactivated. Google didn’t provide any selectable option for adding the option to Google Voice.


Here is how you can add Google Chat to the “Forwards calls to” list.

Full article here:
Quick trick for Missing Forwards calls to Google Chat Option in Google Voice Account (ALL4OS)

Link: GVMax Forwards Google Voice Notifications to Your Phone

Google Voice may have its own mobile webapp now, but it doesn’t provide notifications on your phone when you get new SMS messages. Free web service GVMax solves this problem by putting full SMS support into email and IM on your smartphone.


GVMax is an open source web service that allows you to send and receive SMS messages through either email or GTalk, as well as get push notifications of new SMS messages on your iPhone without keeping your computer on at home.

Full article here:
GVMax Forwards Google Voice Notifications to Your Phone (Lifehacker)
GVMax – Most comprehensive Google Voice Notification system [Tutorial] (TruVoIPBuzz)
GVMax makes Google Voice and iPhone Play Nice (Brain Dungeon)

Proof of concept: Automatically transfer Google Voice voicemail to Asterisk voicemail


This article is a guest post. We may not be able to answer questions about this article.

The following should be considered proof-of-concept material. Feel free to use and/or modify it at your own risk.

The problem: You have Google Voice calls coming into an Asterisk server but even though you take care to answer calls when they arrive, every so often some hiccup causes voicemails to be left in Google Voice’s voicemail, and no one checks those. The solution: Transfer those voicemails to Asterisk’s voicemail box for that user.

The following assumes that there is already an active voicemail box established for the target user.

Prerequisites: php-xml (do yum install php-xml on a Centos-based system). Also, go to the Google-Voice-PHP-API page on GitHub and grab the file GoogleVoice.php – be sure to get the Raw version of the file. It is suggested that you place it your root directory, and make it executable. Note that if you have downloaded this file in the past, you should check to make sure you have the most recent version, since older versions available prior to June, 2013 did not include the ability to download voicemails.

Then in the same directory create a new file. Call it anything you want but give it a .php extension:



// NOTE: If you get errors from GoogleVoice.php, try installing the php-xml package
// You must change the name and password on the following line. NOTE: Full email address required.
$gv = new GoogleVoice('', 'gv_account_password');
// On the next line insert the extension number of the target voice mail box.  Must have voicemail enabled!
$vmbox = '1111';
// On the next line specify an email address for delivery of new voicemail notification.  Use $email=FALSE; if you don't want this.
// Note that this will not send the voicemail as an attachment so if you want that, do it from within the Google Voice account.

// Don't change anything below unless you know what you are doing!

// Set path to user's mailbox
$dir = '/var/spool/asterisk/voicemail/default/'.$vmbox.'/INBOX/msg';

// Set flag that determines if message waiting indications will be updated
$mwi = FALSE;

// Get data on all unread Google Voice voicemail messages into array.
$voice_mails = $gv->getUnreadVoicemail();
$msgIDs = array();
$keys = array_keys($voice_mails);

// process each available message
foreach($voice_mails as $v) {
	//	echo 'Message id: '.$v->id.' from '.$v->phoneNumber.' on '.$v->displayStartDateTime.': '.$v->messageText."<br><br>\n";

	// Downloads individual voicemail
	// Uses getVoiceMailMP3 function added to GoogleVoice.php - WILL FAIL with unmodified GoogleVoice.php 
	$mp3 = $gv->getVoicemailMP3($v->id);

	// construct temporary filenames used
	$mp3file = $v->id.".mp3";
	$wavfile = $v->id.".wav";

	// write temporary mp3 file to disk
	$fh = fopen($mp3file, 'w') or die("can't open file");
	fwrite($fh, $mp3);

	// convert mp3 to temporary wav file
	system("mpg123 -q -w mp3towavtmp.wav ".$mp3file);

	// convert wav file to format required by Asterisk
	system("sox mp3towavtmp.wav -r 8000 -c 1 ".$wavfile." vol 3 dB");

	// If caller's number starts with +1 strip it
	if (substr($number, 0, 2) == '+1') {
		$number=substr($number, 2);

	// Calculate approximate duration of file from file size
	$duration=(int) (filesize($wavfile)/16000);

	// Construct Message Information file for Asterisk - following must be one long continuous line!
	$txt=";\n; Message Information file\n;\n[message]\norigmailbox=$vmbox\ncontext=macro-vm\nmacrocontext=ext-local\nexten=s-NOANSWER\nrdnis=unknown\npriority=2\ncallerchan=\ncallerid=<$number>\norigdate=$v->displayStartDateTime\norigtime=".substr($v->startTime,0,10)."\ncategory=\nflag=\nduration=$duration\n";

	// Find next unused voicemail file number in Asterisk voicemail directory
	$exists = TRUE;
	$i = 0;
	while ($exists) {
		$exists = file_exists($file);

	// $file will contain path and base filename of voicemail files, without extension
	$file = $dir.substr("000$i",-4);

	// Write Message Information file for this voicemail
	$fh = fopen($file.".txt", 'w') or die("can't open file");
	fwrite($fh, $txt);

	// Change owner and group of file to asterisk
	chown($file.'.txt', "asterisk");
	chgrp($file.'.txt', "asterisk");

	// Move wav file to voicemail directory with proper filename
	rename($wavfile, $file.".wav");

	// Change owner	and group of file to asterisk
	chown($file.'.wav', "asterisk");
	chgrp($file.'.wav', "asterisk");

	// Mark message read in Google Voice so we don't read it again
	if(!in_array($v->id, $msgIDs)) {
		// Mark the message as read in your Google Voice Voicemail.
		$msgIDs[] = $v->id;

	// If email address specified construct and send email to user
	// Wanted option to attach voicemail but couldn't figure out how to do it correctly. uuencode does NOT work.
	if ($email) {
		// Construct email text
		$txt="There is a new voicemail in mailbox $vmbox that was imported from Google Voice's voicemail system:\n\n\tFrom:\t$number\n\tLength:\t$duration seconds\n\tDate:\t$v->displayStartDateTime\n";
		if ($v->messageText) {
		$txt=$txt."\nDial *98 to access your voicemail by phone.\n";
		`echo "$txt" | mail -s "New message $i in mailbox $vmbox" "$email"`;

	// Remove temporary files

	// Set flag to indicate message waiting indication needs to be reset
	$mwi = TRUE;


// If messages were processed tell Asterisk to reset message waiting indications
// This may not be the best way to do this but only way I know
if ($mwi) {
	`/usr/sbin/asterisk -rx "voicemail reload"`;


After you have changed the information at the top of the above code so it is correct for your installation, save it to a file with the extension .php and don’t forget to make it executable. Remember, this is proof-of-concept code, and we do not guarantee that it is ready for use in a production environment. It could probably benefit from additional error checking and possibly other enhancements.

You may want to call the above file on a schedule, perhaps every 15 minutes or every hour, depending on how urgently you want to receive Google Voice voicemails. I would not do it too often because you never know if Google would feel you are abusing their system with very frequent accesses. Note that when you call the script you’ll need to call it using php, for example:

php scriptname.php

and if that doesn’t work try adding the -f option after “php” but before the script name. Also, if you are running multiple copies of this script from a bash script (because you are collecting voicemail for more than one Google Voice user) then use a sleep statement between executions (such as sleep 30), otherwise you may see errors such as this:

PHP Fatal error: Uncaught exception ‘Exception’ with message ‘Could not log in to Google Voice with username:’ in /root/GoogleVoice.php:67

Note that when this inserts voicemails into the Asterisk voicemail directory, it is not quite the same as when using a user leaves a voicemail. The known differences are:

  • When a user leaves a voicemail, the audio is saved in two files, a larger one with a .wav extension and a smaller one with a .WAV extension. The larger one is standard .wav format but the smaller seems to be some sort of GSM file, and I cannot figure out how to get SOX to create a compatible file, so I just don’t bother with it. It doesn’t seem to be needed anyway.
  • While this will let you send a notification e-mail to the message recipient, it does not let you attach the mp3 or wav file to the email. Again, don’t know how, but remember you can configure Google Voice to send a notification (with out without audio file attachment) when someone leaves a voicemail.

I hope someone will expand upon this to create something a bit more robust.

Link: Google Voice: a step-by-step primer on ditching your land line while keeping your number

Note that this process may not work in certain areas of the country.

All told, using the mechanism I’m going to describe below, it’ll cost you about $45 per phone line ported.

Google Voice: a step-by-step primer on ditching your land line while keeping your number (ZDNet)

How it used to be done: How to use Google Voice for free outgoing calls on an Asterisk/FreePBX system (the no-XMPP way)


This article contains text excerpted from a post that originally appeared on a blog called The Michigan Telephone Blog, which was written by a friend before he decided to stop blogging. It is reposted with his permission. Certain edits, including those in the green boxes below, were made on or after December 1, 2013.

EDIT (May 23, 2018): This post is seriously outdated. For more recent information, see How to use Google Voice with FreePBX and Asterisk without using XMPP or buying new hardware. You may also wish to visit this thread at DSLReports for additional information.

It appears that some people are getting upset because Google is dropping the use of its XMPP protocol with Google Hangouts, and there is much speculation that they might drop XMPP support altogether, which could break the method used by PBX software (such as Asterisk, FreeSWITCH, or Yate) and even some hardware to connect to Google Voice.

We would just like to remind everyone that back in the ancient days of Google Voice, Asterisk users had another way to initiate Google Voice calls that did not involve the use of XMPP. While we do not suggest attempting to use this method today, unless absolutely nothing else works, we are reposting a portion of the original instructions here. Again, please note that this method is being reposted as a matter of historical interest only (see this article for more recent recommendations). It is just intended to show that it used to be possible to connect outgoing calls using Google Voice, but without using XMPP.

This method was used by those using Asterisk and FreePBX that wanted to enable free Google Voice outgoing calls. It was assumed that you already had a Google Voice number and has it coming into your system via an Inbound Route (that is, you had it forwarded to a DID that came into your system, that was then handled by an Inbound Route).

Before you began the process, you had to make sure that your Google Voice account was set up correctly.  In your Google Voice account, under the Settings link, Calls tab, you had to make sure the following four options on that page were set up as follows:

Call Screening: Off
Caller ID (in): Display caller’s number (very important!)
Do Not Disturb: Make sure this is unchecked!
Call Options: Make sure this is unchecked!

You also needed to install some Python additions and the pygooglevoice program, assuming you had not done so previously.  Under CentOS you’d do the following from a command prompt:

cd /root
yum -y install python-setuptools
easy_install simplejson

If (and only if) you receive a series of error messages while attempting to install simplejson, it may be because your system is running an older version of Python, such as version 2.4 (if some of the error lines contain the string “python2.4”, this is almost certainly the problem). In that case, you can try this (note that the first line might be split into two lines on your display, but should be entered as a single line):

tar xzvf simplejson-2.0.9.tar.gz
cd simplejson-2.0.9
sudo python install

You’d then download the latest version of pygooglevoice and install it, using a line similar to this (this is all one line):


Then you’d extract and install pygooglevoice:

tar zxvf pygooglevoice-0.5
cd pygooglevoice-0.5
python install

There was also a patch that needed to be installed (again this is all one line):

sed -i 's||\&continue=|' /usr/lib/python2.4/site-packages/googlevoice/

The above was found in this thread in the PBX in a Flash forum, which explains why the patch was needed.

Then you’d open /etc/asterisk/extensions_custom.conf in a text editor and add two new contexts (assuming you were using Asterisk 1.6 or later):

exten => _X.,1,System(gvoice -e -p userpassword call ${EXTEN} gvregphonenum code &)
exten => _X.,n,Set(DB(gv_dialout_username/channel)=${CHANNEL})
exten => _X.,n,Wait(20)
exten => _X.,n,Noop(Never received callback from Google Voice on channel ${DB_DELETE(gv_dialout_username/channel)} – exiting)
exten => h,1,GotoIf($[“${CHANNEL(state)}” = “Ring”]?:bridged)
exten => h,n,Noop(Hangup on channel ${DB_DELETE(gv_dialout_username/channel)})
exten => h,n,System(gvoice -e -p userpassword cancel &)
exten => h,n,Hangup()
exten => h,n(bridged),Noop(The channel has been bridged successfully)

Replacing username with the name of the user associated with the Google Voice account (the name before in the associated Gmail account), userpassword with the password of the Google Voice account, gvregphonenumber with the registered phone number in Google Voice that you want to forward calls to (this had to be a number that came into your Asterisk/FreePBX box, and that you had already registered it as a destination in Google Voice, NOT your Google Voice number.  And sometimes you had to use just ten digits, other times you had to add the “1” at the start of the number, and that could vary from account to account so you just had to try and see which worked), and code with a single digit that was one of the following:  1-Home, 2-Mobile, or 3-Work (you’d just use the single digit, not the word, and when you registered the destination phone number with Google Voice you had to tell them if the number was a Home, Work, or Mobile, so the code would correspond to what you’d put there. Some people found that they could omit the code and it would still work, but that wasn’t always true).

In the System() calls it was important not to omit the space and ampersand just before the final parenthesis — this allowed the dial plan to move ahead rather than imposing extra and unnecessary delays on the caller.

One strange thing about this context was that the Noop line was NOT optional – things just didn’t work as expected if it was left out or commented out.

On one Asterisk 1.8 system, the following changes were necessary:

  1. The first instance of System(gvoice -e … had to be changed to System(sudo gvoice -e … (adding sudo before gvoice)
  2. In the file /etc/sudoers the following line had to be added: asterisk ALL = NOPASSWD: /usr/bin/gvoice
  3. The hangup portion of the context (everything below the first Noop statement) did not work as intended, and actually cancelled the Google Voice callback!. So it was changed to simply:

exten => h,1,Hangup

As you will see, the line that cancels an abandoned call was added to the second context. The first two changes were necessary because without them, Asterisk could not successfully execute the gvoice program, despite the fact that permissions were set to make it readable and executable by everyone.

The second context that had to be added in /etc/asterisk/extensions_custom.conf was this one:

exten => s,1,NoCDR()
exten => s,n,Bridge(${DB_DELETE(gv_dialout_username/channel)})

On one Asterisk 1.8 system it was found necessary to change the above context to read as follows:

exten => s,1,NoCDR()
exten => s,n,GotoIf($[${ISNULL(${DB(gv_dialout_username/channel)})}]?ext-did-0002,gvregphonenum,1)
exten => s,n,Bridge(${DB_DELETE(gv_dialout_username/channel)})
exten => s,n,System(sudo gvoice -e -p userpassword cancel &)
exten => s,n,Hangup()

The purpose of the line that begins with exten => s,n,GotoIf… is to correctly route the incoming call in case you initiated a callback from the Google Voice web page. The string gvregphonenum is replaced by the registered phone number in Google Voice that you are forwarding calls to, which should also be the same as the DID in your Inbound Route for Google Voice calls – this is NOT your Google Voice number! This line is optional, and note that it sends calls to the context ext-did-0002 in extensions_additional.conf, which could possibly be different in differently-configured versions or future versions of FreePBX. If it doesn’t work for you, you can leave the entire line out, but you won’t be able to initiate callbacks from your Google Voice page.

The purpose of the line that begins with exten => s,n,System… is to cancel the call in case the caller has hung up before the callback from Google Voice is received. If the call is not cancelled, weird stuff happens! You can omit the “sudo” if you did not find it necessary to add it above.

Again replacing all instances of username and userpassword with the name and password of the user associated with the Google Voice account. After saving those changes you would then go into the FreePBX GUI, go to the Tools menu, Custom Destinations module, and create a new Custom Destination. In the Custom Destination: text box you’d enter this string:


In the Description: field, you could use a meaningful description such as Google Voice Bridge username and then click on “Submit Changes.” After saving that you’d go into Trunk settings and create a new CUSTOM trunk with these settings:

Maximum Channels: set to 1
Dial Rules: Use what you like, it’s suggested that you at least add 1+NXXNXXXXXX but if your area allows seven digit dialing, you may also want to add one like 1areacode+NXXXXXX where areacode is replaced with your local three digit area code.
Custom Dial String: Set to Local/$OUTNUM$@custom-gv-trunk-username — once again, replace username with the name of the user associated with the Google Voice account.

Once you had created and saved this trunk, it could be used as a trunk selection for any USA/Canada Outbound Route.

One assumption was that you had already set up Google Voice to send incoming calls to your Asterisk system via a DID that did not change the incoming Caller ID number. Normally this would be accomplished by getting a DID from some provider (either a free one or one you paid for — it didn’t matter as long as they would pass incoming Caller ID number correctly). Once that was working, you’d create a second inbound route for that same DID, without changing the original in any way — this would be a new Incoming Route, which would be set it up as follows:

Description: Anything meaningful, such as Username Google Voice”.

DID Number: Same as on your other Inbound Route that handles your Google Voice traffic.

Caller ID number: This had to be be your Google Voice number (the one associated with your Google Voice account), but depending on how your DID provider sent Caller ID, you might have to specify it as either a ten or eleven digit Caller ID, or even +1 followed by ten digits.  Whatever format your DID provider used, you had to match their format, which sometimes meant watching the Asterisk CLI during a test call to see what format they used. If it didn’t match what they sent, it wouldn’t work.

Destination: the Custom Destination created above (e.g. Custom Destinations: Google Voice Bridge username).

No other settings of the Inbound Route were changed and in particular, you were advised not to set a CID Lookup Source because it would cause an unwanted delay in connection time and was totally useless in this route, and there’s no reason to do so since this route is only triggered when a single Caller ID comes in).

Once you had submitted these changes, you should have been able to add your Google Voice custom trunk as a trunk selection for one or more of your USA/Canada Outbound Routes.

If it didn’t work it was generally one of three things. Either the Custom Trunk hadn’t been specified as a destination in the appropriate Outbound Route, or the incoming Caller ID of the Google Voice call didn’t exactly match what you set up in the Inbound Route you created, or you got something wrong in extensions_custom.conf such as the username or password (or you missed a place where you were supposed to change one of those items).

For test purposes, you could go to a Linux command prompt (not a CLI prompt in Asterisk!) and try entering a gvoice command directly, using this format (note this is all one line):

gvoice -e -p userpassword call numbertocall gvregphonenum code

All of those values are as explained earlier, except for numbertocall, which had to be a USA or Canada phone number in 11 digit format.  Yes, the number to call had to be in 11 digit format (with the leading “1”) whereas the gvregphonenum might (or might not) need to be TEN digits (no leading “1”) – go figure.  If it worked from the command line then you needed to double check your values in extensions_custom.conf.  If it did not work from the command line, then either there was something wrong with your pygooglevoice installation, or with Python on your system (you had to have at least Python version 2.4 or higher), or you could have been using incorrect values (EDIT: Or, on some systems, it might be necessary to execute the gvoice command using sudo from within Asterisk, as described above).  And, some people got confused over the fact that that the “gvregphonenum” value was NOT supposed to be their Google Voice number, but instead the number to which Google Voice forwarded their calls, and it had to be a number that had been previously registered as a destination with Google Voice.

That’s the basics of how it was done. Note this is not intended to be a guide as to how to set this up now, since many things have changed since then. Just because this method worked back then does not mean it will still work today, and it’s definitely slower in the setup of calls than more recent methods. However, it is worth noting that at no point was the XMPP protocol used. It’s also worth mentioning that there are other programs that can interact with Google Voice besides PyGoogleVoice (see for example Google-Voice-PHP-API, google-voice-java, SharpGoogleVoice, voice.js, etc.) that may or may not be more suitable for use in this type of application.

Recent Posts

Recent Comments




GiottoPress by Enrique Chavez