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

Note: If you installed any of the custom dialplan shown in this article prior to June 10, 2018, please be aware that there have been several corrections made to that code.  Please check your dialplan in extensions_custom.conf against the dialplan shown in this article.

As you have probably heard, Google is AGAIN threatening to discontinue XMPP access to Google Voice in mid-June, 2018 – if you somehow haven’t heard about this, you can start reading the long, long thread on DSLReports: Google Voice XMPP support will go away in June. That is where you will find the most current information. The problem is that if you are currently using the Google Voice module in FreePBX, it uses the XMPP protocol to connect to Google Voice, and that’s what’s going to stop working. Of course we’ve been to this dance before – about three years ago, Google was supposedly going to discontinue XMPP support, and then didn’t. Will they really do it this time? Only Google knows. EDIT: At a week and a half past the supposed cutoff date, XMPP access is still working.

Anyway, 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.

EDIT:  I had previously mentioned on this page the alternative of using the Simon Telephonics Google Voice Gateway.  Unfortunately, on Thursday, June 29, 2018 this Notice of Simon Telephonics Google Voice Gateway Discontinuation was posted, so that is no longer an option.

However, many FreePBX users like to “do it themselves” and it appears there is a way to do it. However, if Google Voice really does stop supporting XMPP then the FreePBX Google Voice module will become useless, so this process may be a bit more “hands on” than you are used to. I’m hoping a better method than this comes along soon (this page of Google Voice SIP Information and/or these Work-In-Progress GVSIP changes to Asterisk (discussion thread here) may prove helpful to developers and Asterisk users), but for now this is it if you don’t want to buy new hardware or use someone else’s server.

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, but it does not use the XMPP protocol, so it won’t be directly affected by the removal of XMPP support by Google Voice (and if anyone tells you differently, they’re wrong). It’s worked for years now, but when dealing with Google that doesn’t necessarily mean anything. 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 and/or TelecomsXChange. 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 RonR’s post shows how to 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 you decide to use 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. Once it 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, 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 the notes that follow were written based on his original instructions, and you may want to follow them and get his method working with a Google Voice account or two first. Just 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.

So, here are some additional hints and information regarding RonR’s instructions. 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 below). 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.

Hopefully all that should get you going, but there is a caveat here. This method could stop working at any time. Contrary to what you may read in some other places, this method does not use the XMPP protocol at all, so if Google really does end support for XMPP in mid-June, that by itself would not affect this. But if Google changes their authentication protocols, this 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 more gracefully deals with a larger number of Google Voice accounts because it assigns Parking Lot extensions starting with the highest available and working its way down until it finds one not in use. It’s set to start with extension 78 and work its way 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. (EDIT June 7, 2018: If you don’t have the FreePBX Parking Lot module installed or just don’t care to use the Parking Lot for this purpose, I have added instructions to use the alternative “Bridge” method at the end of this article, so you may want to read to the end of the article before you begin making configuration changes.) 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 two contexts are only added once, no matter how many Google Voice accounts or DID’s you have:

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(15)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.  To use the alternative “Bridge” method, scroll down to find another version of this context, then come back here and add the custom-gv-error and custom-username-out contexts shown below, and continue from there.

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.

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.

More 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),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.  To use the alternative “Bridge” method, scroll down to find another version of this context  If using the “Bridge” method, be sure to also add the custom-gv-cancel context .

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.


There is an alternative to using the Asterisk Parking Lot, that instead uses Asterisk’s Bridge application. 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 disadvantage is that the custom dialplan is slightly more complex. Use the instructions for setting up the Parking Lot version above, with these exceptions:

Replace the custom-gv-out-common context with this:

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(20)
; 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(20)


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

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.

Replace each custom-NXXNXXXXXX-in context with this:

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,)

As 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 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.

Add the following context:

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.

Don’t forget that even if you are using the “Bridge” method, you still need to add the custom-gv-error and custom-username-out contexts, as shown in the “Parking Lot” method instructions.

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, and in particular if someone comes up with a better way to do this. Once again, please keep in mind that we aren’t 100% certain that XMPP connectivity will stop working in mid-June, so you might want to hold off on doing anything until then, first to see if XMPP really does get shut off, and second because there is always hope that in the meantime someone will discover a better way to connect to Google Voice from Asterisk and FreePBX.

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

  1. Twinclouds

    In Spring 2014, I wrote the original blog post “How to make and receive calls using Google Voice without XMPP” as it was likely Google was going to drop XMPP protocol in May 2014. The post attracted a lot of interest at that time. It received over 5000 visits. However, since Google eventually did not abandon XMPP, the blog was not very useful anymore.
    Recently, it was announced that Google is going to drop XMPP from Google Voice on June 17, 2018 and it looks more likely to happen this time. People have started looking into the possibility of using Google Voice without XMPP again [1][2].
    Due to the renewed interest, I tried the method described in my previous blog. It was found that the original approach still works after some necessary updates based on what described in [1]. The difference between my installation and that described in [1] and [2] is that mine is based on plain Debian/Ubuntu while theirs are build on top of Freepbx. The approach implemented in plain Linux may be less flexible and less versatile than the ones based on Freepbx. However, it should function fine for its scope. Moreover, the description in this revised blog uses a steps-by-step approach, which should be easier to follow if you want to try it out from ground zero.
    The new blog post can be found in (
    [1] RonR’s post in “Google Voice XMPP support will go away in June” on DSLReport Forum (»Google Voice XMPP support will go away in June).
    [2] How to use Google Voice with FreePBX and Asterisk without using XMPP or buying new hardware, TechNotes. (»

    1. Admin Post author

      Twinclouds, first of all I corrected the link in your comment for you, and second, I find it interesting that you bridge the calls together while RonR’s method (and my revision of his method) use the Parking Lot. I believe either method will work but it seems to me that in the early days of Google Voice, prior to the introduction of XMPP, the bridging method had a drawback in that it appeared to have a memory leak, so after about a week’s worth of usage you’d need to restart Asterisk or it would get really flaky (I had a cron job to do in in the middle of the night). However, I do not know if that memory leak has been fixed in newer versions of Asterisk (that problem was observed back in Asterisk 1.8, or maybe an even earlier version), and if it hasn’t then I don’t know that the Parking Lot approach doesn’t have the same issue. At this point I’m willing to say that either approach is probably just as valid unless actual usage proves me wrong. Anyway, thanks for your post, I’m sure it will be quite helpful to the bare Asterisk users.

      1. Twinclouds

        Hi, TechNotes Admin:
        Thank you for your correction and comment. As I said, I am not really a developer or expert on VOIP/Asterisk. I just picked up something that works for me. I will looking into the memory lead issue to see what I can do.
        Thank you again for your help and comment!

  2. Twinclouds

    I did a search on Asterisk bridge, not much was mentioned on the memory leak when using the bridge function, maybe this problem has been fixed?
    I also notice that the current GV implementation using XMPP in Asterisk, either using OAuth2.0 or not, uses simple_bridge. I don’t know if it is the same as the bridge or not.

    1. Admin Post author

      I think the memory leak may have been fixed, but I wanted to add the Bridge option to my article and while doing so, I noticed another problem that likely affects your code as well. You use this:

      System(gvoice -b -e [gvusername] -p [gvpassword] cancel &)

      But as noted in my June 7 addition to the article, my experience is that either this isn’t working at all, or it takes so long to work that it’s useless, I am not certain which. What I wound up doing was intercepting the “orphaned” incoming call from Google Voice, answering it and then immediately hanging up (after a one second wait). In my (admittedly very limited) testing that was the only thing that would reliably abort the callback. Perhaps gvoice cancel works in a non-FreePBX environment, but it does not seem to work in FreePBX for some odd reason

  3. Twinclouds

    I must took the line with cancel somewhere. It seems works fine so far on plain Asterisk. Not sure if it will cause problem on FreePBX or not. Due to my limited experience in Asterisk, sorry I just cannot help more.
    Please let me know if you find out more, though.


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.