Asterisk cmd ChanSpy



Listen in on a call, or whisper into a conversation. Useful in a call center to monitor agents on the phone.


This adds the ability to spy on any bridged call, this includes VoIP-only calls where in the past ZapScan/ZapBarge couldn't - this can.

Chanspy([<chanprefix>][|<options>]) in Asterisk 1.4

May be empty, can also be set to 'all' (without the quotes) meaning empty
Is typically set to something like 'SIP' or 'Agent'

Valid Options:
- b: Only spy on channels involved in a bridged call.
- g(grp): Match only channels where their ${SPYGROUP} variable is set to contain 'grp' in an optional : delimited list (by colon). Multiple arguments for 'grp' are not possible in asterisk 1.4 though and require a later asterisk release - see Asterisk-15294 and Asterisk-11894. The SPYGROUP variable, however, may contain multiple values also in Asterisk 1.4. The number of SPYGROUPs was raised from 25 to 128 as well in Asterisk-11894.
- q: Don't play a beep when beginning to spy on a channel, or speak the selected channel name.
- r([basename]): Record the session to the monitor spool directory. An optional base for the filename may be specified.
The default is 'chanspy'. ChanSpy only records to a .raw file.
- v([value]): Adjust the initial volume in the range from -4 to 4. A negative value refers to a quieter setting.

Included with and since 1.4:
- w Enable 'whisper' mode, so the spying channel can talk to the spied-on channel.
- W Enable 'private whisper' mode, so the spying channel can talk to the spied-on
channel but cannot listen to that channel.

Included with and since 1.6.x:
- o: Only listen to audio coming from this channel.
- X: Allow the user to exit ChanSpy to a valid single digit numeric extension in the current context or
the context specified by the SPY_EXIT_CONTEXT channel variable. The name of the last channel
that was spied on will be stored in the SPY_CHANNEL variable.
- e(ext): Enable 'enforced' mode, so the spying channel can only monitor extensions whose name
is in the 'ext' : delimited list.


If <chanprefix> is specified, only channel names *beginning* with that string will be scanned.
('all' or an empty string are also both valid <chanprefix>)

While spying, the following actions may be performed:

Dialing # cycles the volume level.
Dialing * will stop spying and look for another channel to spy on.
Dialing a series of digits followed by # builds a channel name to append to <chanprefix>
(e.g. run ChanSpy(Agent) and dial 1234# while spying to jump to channel Agent/1234)

Update: Asterisk 1.4 includes a 'whisper' feature as part of ChanSpy(): A third party may speak to only one of the two parties of a bridged call.


  • Up to and including Asterisk 1.4.17 ChanSpy can cause a crash/segfault if used together with Monitor or MixMonitor at the same time. 1.4.18 is supposed to attack this issue by using "audiohooks" that replaces the current ChanSpy approach.


ChanSpy will not work if you are Record()-ing the spied channel; unless you add transmit_silence_during_record=yes to the options section in /etc/asterisk/asterisk.conf


exten => 554,1,ChanSpy()
exten => 556,1,ChanSpy(|b)
exten => 556,1,ChanSpy(all|q)
exten => 557,1,ChanSpy(SIP,g(hotline)b)
exten => 558,1,ChanSpy(SIP/mypeer,g(hotline:outbound:internal)qw)

;Dialing either 8810, 8820 and 8830 will all match this SIP call - see Asterisk-6886 from 2006
exten => 1000,1,Set(SPYGROUP=10:20:30)
exten => 1000,2,Dial(SIP/1000@somewhere)
exten => _88XX,1,Chanspy(|g(${EXTEN:2}))

exten => 456,1,Answer()
same => n,ChanSpy(SIP/0004f2,g(TEST)d)
exten => 457,1,NoOp()
same => n,Set(SPYGROUP=TEST)
same => n,Playback(tt-monkeys)

exten => s,1(getext),Read(SPY,extension,4)
exten => s,n,GotoIf($[ ${LEN(${SPY})} != 4 ]?nospy)
exten => s,n(spy),UserEvent(ChanSpy,User ${CALLBACKNUM} spied on ${SPY})
exten => s,n,Chanspy(SIP/${SPY},r(monitor-ext-${SPY}))
exten => s,n,Hangup()
exten => s,n(nospy),Playback(sorry-cant-let-you-do-that3)
exten => s,n,UserEvent(ChanSpy,User ${CALLBACKNUM} failed to spy on ${SPY})
exten => s,n,Hangup()

exten = i,1, goto(${CONTEXT},s,1)
exten = s,1, verbose(1,[${CONTEXT}:${EXTEN}])
exten = s,n, read(AGENT-ID,enter-agent-number)
exten = s,n, set(SPYGROUP=${AGENT-ID})
exten = s,n, read(AGENT-ID,enter-agent-number)
exten = s,n, chanspy(,g(${AGENT-ID}))
exten = s,n, goto(s,1)

Similar third party DB-based solution

SpyGroup application runs in Asterisk and MySQL environment and used for spying on predefined groups of VoIP users. The spying operation is protected by unique password that used to select which group will be spyed on. All the data (group numbers, extensions list, passwords) are stored in MySQL database. The setspygroupd daemon checks all active calls for database extension match, if exact match found - the extension will be added to predefined group number. Spying can be done by dialing the special SpyGroup extension and entering the password.

See also

Version information

  • As of october 19 2004, ChanSpy is not included in the standard Asterisk distribution or the development CVS tree.
  • As of March 22 2005 this bug was reopened and can be viewed at above link.
  • On March 24 2005 ChanSpy was added into CVS HEAD and then added to the regular asterisk releases

Asterisk | Applications | Functions | Variables | Expressions | Asterisk FAQ

Created by: JustRumours, Last modification: Sun 30 of Dec, 2012 (09:49)
Please update this page with new information, just login and click on the "Edit" or "Discussion" tab. Get a free login here: Register Thanks! - Find us on Google+