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

  1. Twilio Console β†’ Voice β†’ SIP Domains β†’ Create new SIP Domain. Example: yourname.sip.twilio.com.

  2. Enable SIP Registration.

  3. Add a Credential List with a strong username and password, for example:

    • Username: linphone
    • Password: StrongPassword123!
  4. 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:

FieldValue
Usernamelinphone
PasswordStrongPassword123!
Domainyourname.sip.twilio.com
TransportTLS
Outbound proxysip.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>/getUpdates and read message.chat.id

2) Add Twilio Function environment variables

Twilio Console β†’ Functions & Assets β†’ Settings β†’ Environment Variables

  • TELEGRAM_BOT_TOKEN = your Telegram bot token
  • TELEGRAM_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

ItemHow to testExpected result
Linphone registrationLinphone Accounts screenStatus shows Registered
Inbound callCall your Twilio numberLinphone rings
Outbound callDial sip:+34XXXXXXXXX@yourname.sip.twilio.comPSTN call connects
SMS forwardSend an SMS to your Twilio numberTelegram receives a message
MMS forwardSend a photo to your Twilio numberTelegram 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 +E164 and 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_TOKEN and TELEGRAM_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