A Voice CAPTCHA in FreePBX

This guide explains how to set up a Voice CAPTCHA in FreePBX to filter out robocalls, telemarketers, and unsolicited traffic from toll-free or blocked caller IDs. By using a custom Asterisk dialplan, the system will intercept these calls and play a recorded message asking the caller to enter a randomly generated digit. The caller is given 10 seconds and two total attempts to press the correct number. If they pass the challenge, the system seamlessly forwards the call to your standard IVR or ring group. If they fail or timeout, the system routes them directly to a specified voicemail box, keeping your phones from ringing unnecessarily.


Step 1: Record Your Audio Prompts

You will need three separate audio files for the CAPTCHA process. In FreePBX, navigate to Admin > System Recordings and create the following three recordings. Note their exact names, as the dialplan will reference them directly.

  1. Name: captcha_greeting
  • Suggested Script: “We do not accept unsolicited calls. To prove you are human and proceed, please press the following number…”
  1. Name: captcha_invalid
  • Suggested Script: “That input was not valid. Let’s try one more time. Please press…”
  1. Name: captcha_voicemail
  • Suggested Script: “Invalid input. You are being routed to our voicemail system.”

Step 2: Inject the Custom Dialplan

Next, we write the logic that generates the random number, handles the 10-second timeout, and tracks the attempts.

  1. Navigate to Admin > Config Edit (or SSH into your server).
  2. Open the extensions_custom.conf file.
  3. Paste the following block of code at the very bottom of the file:
[custom-caller-captcha]
exten => s,1,NoOp(Entering Caller CAPTCHA)
exten => s,n,Answer()
exten => s,n,Set(ATTEMPTS=0)

; Start of loop
exten => s,n(loop),Set(ATTEMPTS=$[${ATTEMPTS} + 1])
exten => s,n,Set(EXPECTED=$[${RAND(0,9)}])

; Play greeting
exten => s,n,Playback(custom/captcha_greeting)
exten => s,n,SayDigits(${EXPECTED})

; Wait for 1 digit with a 10 second timeout
exten => s,n,Read(ENTERED,,1,,,10)

; Evaluate input
exten => s,n,GotoIf($["${ENTERED}" = "${EXPECTED}"]?success:wrong)

; Wrong input or timeout block
exten => s,n(wrong),GotoIf($[${ATTEMPTS} >= 2]?fail)
exten => s,n,Playback(custom/captcha_invalid)
exten => s,n,Goto(loop)

; Hard failure block (2 failed attempts)
exten => s,n(fail),Playback(custom/captcha_voicemail)
; CHANGE "100" IN THE NEXT LINE TO YOUR ACTUAL VOICEMAIL EXTENSION
exten => s,n,Voicemail(100@default,u) 
exten => s,n,Hangup()

; Success block
exten => s,n(success),NoOp(Passed CAPTCHA)
exten => s,n,Return()
  1. Important: Change the 100@default line to match the exact extension number of the voicemail box you want failed callers to land in.
  2. Click Save and then Apply Config.

Step 3: Install the Custom Destinations Module (If Missing)

To link the GUI to your new dialplan code, you need the Custom Destinations module. In some FreePBX installations, it is found under the Applications menu, and in others, it is under the Admin menu.

If you do not see it in either menu, you will need to install it:

Via the FreePBX GUI:

  1. Go to Admin > Module Admin.
  2. Click Check Online.
  3. Locate Custom Applications (this is the parent package for Custom Destinations).
  4. Select Install or Download and Install.
  5. Click Process, confirm, and then click Apply Config.

Via Command Line (SSH): If you prefer the terminal, run the following commands as root:

fwconsole ma downloadinstall customappsreg
fwconsole ma enable customappsreg
fwconsole reload

Step 4: Map the Code to a Custom Destination

Now we tell FreePBX how to execute the dialplan you wrote.

  1. Navigate to Custom Destinations (under Applications or Admin, depending on your version).
  2. Click Add Destination.
  3. Target: custom-caller-captcha,s,1 (Ensure you use the letter s here).
  4. Description: Caller ID CAPTCHA
  5. Return: Check the Yes box. (This is crucial—it tells FreePBX that if the caller passes the test and triggers the Return() command in our code, they should be routed to the normal destination below).
  6. Destination: Choose where the call normally goes if they are a legitimate caller (e.g., your main IVR, Ring Group, or an Extension).
  7. Click Submit and Apply Config.

Step 5: Route Specific Callers to the CAPTCHA

Finally, configure your Inbound Routes to force unwanted traffic into your new CAPTCHA challenge.

For Toll-Free (1-800) Numbers:

  1. Navigate to Connectivity > Inbound Routes and click Add Inbound Route.
  2. Description: Block 800 Numbers
  3. DID Number: Leave blank (or enter your main DID).
  4. CallerID Number: _800NXXXXXX (The underscore denotes a pattern. You can create additional routes for _1800NXXXXXX, _888NXXXXXX, _877NXXXXXX, etc., to cover all toll-free variants).
  5. Destination: Choose Custom Destinations > Caller ID CAPTCHA.
  6. Click Submit.

For Unknown / Anonymous Callers:

  1. Create another Inbound Route.
  2. Description: Block Anonymous
  3. CallerID Number: anonymous
  4. Destination: Choose Custom Destinations > Caller ID CAPTCHA.
  5. Click Submit.

(Note: Telecom carriers pass blocked IDs using different text strings. Repeat the step above creating separate routes using hidden, unknown, and restricted in the CallerID Number field to catch them all).

Click the red Apply Config button one final time. Legitimate callers will now bypass the CAPTCHA entirely, while flagged numbers will be forced to prove they are human before your phones will ring.

Leave a Comment

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