Build Your Own Skype Replacement with Twilio, Linphone, and Telegram (Serverless DIY Guide)
π οΈ DIY Skype Alternative: In this guide, youβll rebuild the core of Skype using Twilio + Linphone for voice calls and Telegram for messages. No central servers, no subscriptions β just your own cloud-based communication system.
Microsoft may have retired Skype, but you can create your own fully functional replacement in just a few hours using Twilioβs programmable voice and messaging services. Weβll configure Linphone as your VoIP client for calls (inbound and outbound) and use Telegram to receive SMS messages instantly β all powered by Twilio Functions, no backend servers required.
What you will set up
- Inbound calls to your Twilio number ring in Linphone
- Outbound calls from Linphone through Twilio to the PSTN
- Incoming SMS and MMS forwarded to your Telegram chat
- All logic runs on Twilio Functions (serverless)
Prerequisites
- A Twilio account with a Voice and SMS capable number
- Linphone installed on desktop or mobile
- A Telegram account
- Basic familiarity with Twilio Console
Understanding the Key Technologies
What is SIP?
SIP (Session Initiation Protocol) is the standard protocol for Voice over IP (VoIP) communications. Think of it as the βlanguageβ that VoIP devices and services use to establish, manage, and terminate phone calls over the internet. When you make a call using SIP, it handles everything from ringing the other party to negotiating audio codecs and tearing down the connection when you hang up.
Unlike traditional phone lines that use circuit-switching, SIP works over standard internet connections, making it perfect for building your own communication systems without relying on traditional telecom infrastructure.
What is Linphone?
Linphone is a free, open-source VoIP softphone client that supports SIP. Available for Windows, macOS, Linux, iOS, and Android, Linphone turns your computer or smartphone into a full-featured phone capable of making and receiving calls over the internet.
Key features:
- SIP/VoIP calls with HD audio quality
- Video calling capabilities
- Secure communication with TLS and SRTP encryption
- Cross-platform compatibility
- Free and open-source (GPL license)
For this guide, weβll use Linphone as your primary phone interface β it will ring when someone calls your Twilio number and let you make outbound calls through Twilio to any regular phone number worldwide.
Twilio Cost Overview
Twilio operates on a pay-as-you-go model with no monthly contracts:
Phone Numbers:
- US local number: ~$1.15/month
- US toll-free number: ~$2.15/month
Voice Calls:
- Inbound calls: ~$0.0085/minute
- Outbound calls: ~$0.014/minute
SMS Messaging:
- Send or receive: starts at ~$0.0083/message
Example monthly cost for light personal use:
- 1 phone number: $1.15
- 100 minutes of calls: ~$1.25
- 50 SMS messages: ~$0.42
- Total: ~$2.82/month
This makes it incredibly affordable compared to traditional phone plans, especially if youβre using it as a secondary number or for international calling.
Part 1. Configure Twilio SIP with Linphone
1) Create a SIP Domain in Twilio
-
Twilio Console β Voice β SIP Domains β Create new SIP Domain. Example:
yourname.sip.twilio.com. -
Enable SIP Registration.
-
Add a Credential List with a strong username and password, for example:
- Username:
linphone - Password:
StrongPassword123!
- Username:
-
Leave IP Access Control Lists empty unless you have a static IP PBX. For softphones this is not needed.
Security tip: Use TLS transport in your client and a long random password.
2) Configure Linphone
Create a new SIP account in Linphone with:
| Field | Value |
|---|---|
| Username | linphone |
| Password | StrongPassword123! |
| Domain | yourname.sip.twilio.com |
| Transport | TLS |
| Outbound proxy | sip.twilio.com (optional) |
Linphone should show Registered.
3) Inbound calls: Twilio number β Linphone
Create a TwiML Bin in Twilio Console β TwiML Bins β Create.
Name: Forward to Linphone
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Sip>sip:linphone@yourname.sip.twilio.com</Sip>
</Dial>
</Response>
Assign it to your number:
- Phone Numbers β Active Numbers β select your number
- Voice β A CALL COMES IN β TwiML Bin β select
Forward to Linphoneβ Save
4) Outbound calls: Linphone β Twilio β PSTN
When dialing from Linphone, simply enter the international phone number you want to call. Linphone automatically formats numbers in E.164 format (e.g., +1234567890) and sends them to your SIP domain like this:
sip:+346XXXXXXXX@yourname.sip.twilio.com
Note: E.164 is the international phone number format that includes a country code prefix (e.g., +1 for USA, +34 for Spain, +54 for Argentina). You donβt need to manually format this β just dial the number with the country code and Linphone handles the rest.
Twilio must know how to process the INVITE. Create a Twilio Function and link it in the SIP Domain.
Function path: /outbound
exports.handler = async function (context, event, callback) {
const VoiceResponse = require("twilio").twiml.VoiceResponse;
const twiml = new VoiceResponse();
// Extract +E164 from To or Called (SIP INVITE looks like sip:+E164@yourdomain)
const raw = event.To || event.Called || "";
const match = String(raw).match(/\+[\d]{6,}/);
const e164 = match ? match[0] : null;
if (!e164) {
twiml.say("Invalid destination.");
return callback(null, twiml);
}
const dial = twiml.dial({ callerId: "+12313543803" }); // replace with your Twilio number
dial.number(e164);
return callback(null, twiml);
};
Wire it in your SIP Domain:
- Voice β SIP Domains β open
yourname.sip.twilio.com - Call Control Configuration β Configure with Function β pick
/outboundβ Save
Enable outbound countries:
- Voice β Settings β Geo Permissions β allow Spain, USA, Argentina, or others as needed
Caller ID rule: the callerId must be a Twilio number you own or a verified caller ID.
Part 2. Forward Twilio SMS and MMS to Telegram
1) Create a Telegram bot and get chat_id
- In Telegram chat with @BotFather β
/newbotβ get your bot token - Send any message to your bot
- Open
https://api.telegram.org/bot<TOKEN>/getUpdatesand readmessage.chat.id
2) Add Twilio Function environment variables
Twilio Console β Functions & Assets β Settings β Environment Variables
TELEGRAM_BOT_TOKEN= your Telegram bot tokenTELEGRAM_CHAT_ID= your numeric chat id
Save.
3) Create Function /sms-to-telegram
exports.handler = async function (context, event, callback) {
const BOT = context.TELEGRAM_BOT_TOKEN;
const CHAT = context.TELEGRAM_CHAT_ID;
const from = event.From || "";
const to = event.To || "";
const body = event.Body || "";
const numMedia = parseInt(event.NumMedia || "0", 10);
const base = `https://api.telegram.org/bot${BOT}`;
const send = (method, payload) =>
fetch(`${base}/${method}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
const escape = (s) => String(s).replace(/[_*\[\]()~`>#+\-=|{}.!]/g, "\\$&");
const text = [
"π© *New SMS*",
`*From:* \`${escape(from)}\``,
`*To:* \`${escape(to)}\``,
body ? `*Body:*\n${escape(body)}` : "*Body:* _empty_",
].join("\n");
await send("sendMessage", {
chat_id: CHAT,
text,
parse_mode: "MarkdownV2",
disable_web_page_preview: true,
});
for (let i = 0; i < numMedia; i++) {
const url = event[`MediaUrl${i}`];
const type = (event[`MediaContentType${i}`] || "").toLowerCase();
const payload = { chat_id: CHAT, caption: `From ${from}` };
if (type.startsWith("image/"))
await send("sendPhoto", { ...payload, photo: url });
else if (type.startsWith("video/"))
await send("sendVideo", { ...payload, video: url });
else if (type.startsWith("audio/"))
await send("sendAudio", { ...payload, audio: url });
else await send("sendDocument", { ...payload, document: url });
}
return callback(null, { statusCode: 200, body: "OK" });
};
Connect it to your number:
- Phone Numbers β your SMS capable number β Messaging β A MESSAGE COMES IN β Function β choose
/sms-to-telegramβ Save
Testing checklist
| Item | How to test | Expected result |
|---|---|---|
| Linphone registration | Linphone Accounts screen | Status shows Registered |
| Inbound call | Call your Twilio number | Linphone rings |
| Outbound call | Dial sip:+34XXXXXXXXX@yourname.sip.twilio.com | PSTN call connects |
| SMS forward | Send an SMS to your Twilio number | Telegram receives a message |
| MMS forward | Send a photo to your Twilio number | Telegram receives the photo |
Troubleshooting quick fixes
- Call hangs on outbound: Add the Function in SIP Domain Call Control. Verify Geo Permissions and callerId.
- Error 13224 invalid phone number: Your TwiML tried to dial
sip:+...@domain. Use the Function to extract+E164and dial<Number>. - 11200 webhook error: Your Function URL is wrong or returns 404. Use Configure with Function instead of manual URL or include the correct path.
- Twilio says user not registered: Open Linphone. Check that the SIP account is Registered. Registration expires periodically.
- No audio or one way audio: Prefer TLS. Check firewall for RTP ranges. Try Opus or PCMU codecs.
- Telegram not receiving: Check Function logs. Verify
TELEGRAM_BOT_TOKENandTELEGRAM_CHAT_ID.
Security and best practices
- Use long random SIP passwords and TLS transport
- Do not open IP ACL to 0.0.0.0/0
- Restrict Geo Permissions to the countries you need
- Store tokens and chat ids in Function environment variables
Final notes
You now have a complete DIY Skype replacement powered by Twilio. Linphone handles calls, Telegram delivers your messages, and Twilio Functions keep everything serverless and simple.
Next steps:
- Add a Telegram β Twilio bridge for two-way SMS replies
- Implement call recording or voicemail with Twilio Studio
- Share your setup with teammates for a private, global VoIP network