Once upon a time, using a service like Twilio to send and receive SMS was trivial. Sign up, get an API key, and you were good to go. But fast forward to today, and the landscape has shifted — hard. Now, how to send SMS from python?
Thanks to increased regulation, spam control, and A2P (Application-to-Person) rules, what used to be a few lines of code now requires you to register a business, explain your use case to a mobile carrier, and wait for approval — only to possibly get flagged anyway. For solo developers or personal projects, it’s a frustrating dead end.
The Alternative: Just Use a SIM Card
So I built my own SMS gateway — powered by hardware that I control, using a simple prepaid SIM card (I use T-Mobile). No carrier registration forms, no delays, and no approval committees. Because I’m impatient I got all the hardware on Amazon.
Here’s the stack:
🔧 Hardware
- Raspberry Pi 4 Model B (4GB) (amazon $65)
A reliable single-board computer that serves as the brains of the operation. Runs linux. (As a bunus I learned about Tailscale. No more figuring out the IP for your raspberry pi). You will need to setup your Pi by flash a SD card. - Waveshare SIM7600G-H-PCIE Module (amazon $60)
A globally-compatible 4G LTE modem that supports SMS, calls, GNSS (GPS), and data. Mini-PCIe form factor. - GeeekPi RPi 4G/3G Hat (amazon $20)
This adapter board lets the SIM7600G module interface cleanly with the Pi. It handles power, UART routing, and has headers for antennas. - Antenna (recycled from an old SIM800C USB GSM module) (amazon $15)
The SIM800C module never worked correctly, but the antenna did — so I reused it here. No need to reinvent the wheel if a wire still works.
Everything fits together easily. The GeeekPi hat screws directly onto the Raspberry Pi, and the Waveshare SIM7600 module plugs into the Mini-PCIe slot on the hat. The hat connects to the Pi via USB — either with a USB-C to USB-A cable or, in my case, a USB-C to USB-C cable using a USB-A adapter. The SIM card slots into the GeeekPi hat itself.
Once everything is connected and powered on, Linux detects the modem and exposes a TTY/serial interface — usually something like /dev/ttyUSB2. From there, you can send and receive text messages using standard AT commands.
Press enter or click to view image in full size
🧠 Why This Setup Works
This setup essentially gives your Raspberry Pi its own personal cellphone. It can send and receive SMS, make calls, or even use GPS location services — all without needing the cloud. Best of all: it’s cheap and under your control.
Here’s what I use it for:
- Personal alerts (like when my server goes down)
- Two-way text bots
- Message logging
- Home automation triggers
And because it’s a prepaid SIM, I don’t need approval from anyone. It’s just a phone on the network.
Now the the answer to how to send sms from python
import serialimport time
SERIAL_PORT = "/dev/ttyUSB2" # Adjust if your modem appears on a different port
BAUD_RATE = 115200
PHONE_NUMBER = "+1917XXXXXXXXX" # Replace with your target number
MESSAGE = "Hello from the SIM7600G module!"
def send_command(modem, command, delay=1):
modem.write((command + '\r').encode())
time.sleep(delay)
response = modem.read_all().decode(errors='ignore')
print(f"> {command}\n{response}")
return response
def send_sms(phone, message):
with serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=5) as modem:
time.sleep(2)
modem.reset_input_buffer()
send_command(modem, "AT") # Basic check
send_command(modem, "ATE0") # Turn off command echo
resp = send_command(modem, "AT+CMGF=1") # Set SMS to text mode
if "ERROR" in resp:
print("❌ Could not set SMS text mode. Aborting.")
return
resp = send_command(modem, f'AT+CMGS="{phone}"')
if ">" not in resp:
print("❌ Did not receive SMS prompt. Aborting.")
return
modem.write(message.encode() + b"\x1A") # Ctrl+Z ends the message
time.sleep(5)
response = modem.read_all().decode(errors='ignore')
print("SMS send response:\n", response)
if "OK" in response:
print("✅ SMS sent successfully!")
else:
print("❌ SMS may have failed.")
if __name__ == "__main__":
send_sms(PHONE_NUMBER, MESSAGE)
🧪 Gotchas
- Make sure your modem is recognized as
/dev/ttyUSB2(usedmesg | grep ttyorls /dev/ttyUSB*) - You might need to install
minicomorscreento test AT commands manually - Your SIM must be activated and have SMS credit
- If you’re in the US, T-Mobile prepaid works well with the SIM7600 series
I’ve written a lightweight SMS library with LLM integration. If there’s interest, I’ll publish it — just let me know in the comments.
Also, If you have any idea hot to get an enclosure for the whole think, I’d love some input.