FreeSWITCH can run scripts written in several programming languages directly inside the media server process. Embedded scripting is used to implement dynamic IVR flows, custom routing logic, database lookups, REST API calls, and any other call behavior that goes beyond what static XML dialplan extensions can express. Scripts run in-process and have full access to the FreeSWITCH session API, letting them answer calls, play audio, collect DTMF, query databases, and transfer callers — all from within a single script file.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/signalwire/freeswitch/llms.txt
Use this file to discover all available pages before exploring further.
Supported Languages
| Module | Language | Runtime |
|---|---|---|
mod_lua | Lua | Lua 5.x (bundled) |
mod_python3 | Python | Python 3.x (system) |
mod_v8 | JavaScript | Google V8 engine |
mod_perl | Perl | System Perl |
mod_java | Java | JVM via JNI |
mod_managed | C# / .NET | Mono or .NET |
mod_basic | BASIC | Embedded BASIC interpreter |
CoreSession object through language-specific SWIG-generated bindings. This means the session API (answer(), streamFile(), getDigits(), transfer(), etc.) is identical across languages — only the syntax differs.
mod_lua (Recommended)
mod_lua embeds the Lua 5.x interpreter directly in the FreeSWITCH process. Scripts have access to the freeswitch global module (which wraps CoreSession and other APIs) as well as all standard Lua libraries. The module is defined in src/mod/languages/mod_lua/mod_lua.cpp.
Running Lua Scripts
There are two ways to invoke a Lua script from the dialplan:lua— Runs a Lua script in the context of a call. The script receives the active session and can interact with the call synchronously.luarun— Runs a Lua script in a background thread, independent of any specific call. Used for scheduled tasks, background processing, or triggering outbound calls.
Session API Reference
Thesession object is the primary interface for controlling a call from within Lua:
| Method | Description |
|---|---|
session:answer() | Answer the call |
session:preAnswer() | Send early media (183 Session Progress) |
session:hangup([cause]) | Hang up the call with an optional hangup cause string |
session:streamFile(path) | Play an audio file to the caller |
session:getDigits(max, term, timeout) | Collect DTMF digits |
session:playAndGetDigits(min, max, tries, timeout, term, file, invalid, regex, var) | Play and collect in one call |
session:transfer(ext, dialplan, context) | Transfer the call to a new extension |
session:setVariable(name, value) | Set a channel variable |
session:getVariable(name) | Get the value of a channel variable |
session:say(text, module, type, method) | Speak text using a language module |
session:recordFile(path, limit, silence_threshold, silence_hits) | Record audio to a file |
session:ready() | Returns true if the call is still active |
Example: Lua IVR Script
The following Lua script answers a call, plays a greeting, collects a single digit, and routes the call based on the input:Running an API Command from Lua
You can execute any FreeSWITCH API command from Lua using thefreeswitch.API() object:
XML Handler / Dialplan from Lua
Lua can also register as an XML binding, generating dynamic dialplan XML responses to FreeSWITCH’s XML lookup requests. This is configured inlua.conf.xml via the xml-handler-script parameter.
mod_python3
mod_python3 embeds the Python 3 interpreter in FreeSWITCH (the default Python module since replacing mod_python). Python scripts are invoked from the dialplan using the python application. The module is defined in src/mod/languages/mod_python3/mod_python3.c.
Invoking Python Scripts
handler(session, args) function. FreeSWITCH calls this function with the active CoreSession object.
Example: Python 3 IVR Script
mod_python3 uses SWIG-generated Python bindings (freeswitch.py and _freeswitch.so) that are installed alongside the module. The CoreSession class provides the same methods as the Lua session object — answer(), hangup(), streamFile(), getDigits(), transfer(), etc.mod_v8
mod_v8 embeds the Google V8 JavaScript engine, allowing call control scripts written in JavaScript (ECMAScript 5+). The API surface mirrors the Lua and Python bindings.
Invoking JavaScript Scripts
Example: Basic V8 Script
mod_v8 Configuration
Configure the JavaScript script path and startup scripts inconf/autoload_configs/v8.conf.xml. The startup-script parameter can load a global JavaScript file at FreeSWITCH startup.
Calling Scripts from the Dialplan
All embedded language modules expose their scripts via dialplan<action> elements. The general pattern is:
Configuring the Lua script search path
Configuring the Lua script search path
By default, FreeSWITCH looks for Lua scripts relative to the FreeSWITCH base directory. You can configure additional search paths by adding them to the
lua_path parameter in conf/autoload_configs/lua.conf.xml:ESL as an Alternative to Embedded Scripting
For some use cases, using the Event Socket Layer (ESL) from an external process is a better choice than embedding a script inside FreeSWITCH:| Scenario | Embedded Scripting | ESL (External) |
|---|---|---|
| Simple IVR logic | ✅ Simpler, lower latency | — |
| Complex business logic | Works, but limited by scripting env | ✅ Full access to all libraries/frameworks |
| Crash isolation | ❌ A crash can affect FreeSWITCH | ✅ External process is isolated |
| Long-running daemons | ❌ Not intended for persistent threads | ✅ Natural fit |
| Multi-server orchestration | ❌ One FreeSWITCH instance only | ✅ Control multiple FS instances |
| Debugging / testing | ❌ Harder to unit test | ✅ Easy to test independently |
socket dialplan application to hand off a call from FreeSWITCH to an external program over a TCP connection. See ESL Overview for details.