
How to Send an SMS from Your Android Phone with Python
Use a short Python script and your Android phone to send real SMS messages: no Twilio, no carrier contracts. Just textbee, requests, and a small script.
Most SMS APIs charge you per message and route texts through shared short codes your recipients don't recognize. With textbee, the message leaves from your Android phone: your number, your SIM, your carrier rate. Python just tells it what to send.
Here's the entire flow: install the textbee app on your Android device, grab an API key, and run a script. That's it.
Prerequisites
- textbee app installed and linked to your account: download here, then follow the quickstart
- Your device ID and API key from the textbee dashboard
- Python 3 with
requestsinstalled (pip install requests) - Android 15+ users: SMS permissions need an extra step. See the permissions guide
The script
import os
import requests
API_KEY = os.environ["TEXTBEE_API_KEY"]
def send_sms(to: str, body: str) -> dict:
resp = requests.post(
"https://api.textbee.dev/api/v1/gateway/send-sms",
json={"recipients": [to], "message": body},
headers={"x-api-key": API_KEY},
timeout=30,
)
resp.raise_for_status()
return resp.json()
result = send_sms("+15551234567", "Hello from Python")
print(result)Set TEXTBEE_DEVICE_ID and TEXTBEE_API_KEY as environment variables (don't hard-code them). A .env file with python-dotenv works too.
What the API returns
A successful call means your message was accepted and queued for the device to process (not that delivery to the handset is already finished). The body is wrapped in data, for example:
{
"data": {
"success": true,
"message": "SMS added to queue for processing",
"smsBatchId": "…",
"recipientCount": 1
}
}After you send: open the textbee dashboard to see each message move through states like sent, delivered, or failed. If you have webhooks configured, you can get notified there too.
If something is wrong (device offline, bad API key, invalid payload), you get a non-2xx HTTP status and a JSON error body with "success": false, so keep using raise_for_status() or inspect the body on failure.
A few things to keep in mind
Phone numbers: You can use local numbers without a country code when sending within the same country (for example, a 10-digit national number). We still recommend E.164 when you can (+ then country code and number, e.g. +15551234567), especially for international or automated sends, so formatting stays unambiguous.
Multiple recipients: Pass more numbers in the recipients array. One API call, multiple messages, same SIM.
Don't spam: These are real messages from your real phone number. Make sure recipients have opted in. If you're unsure about the rules, the SMS compliance checklist is a good starting point.
Unlike traditional SMS gateways that charge per message, textbee works with your existing carrier plan. Check out the pricing to see what's included.
Where to go from here
- How to send SMS programmatically: examples in more languages
- API documentation: full endpoint reference
- Pricing and plans
Get more textbee in Google Search
Add textbee.dev as a preferred source. Our posts show up more often in your Google results.
You may also like

Send SMS in Django and Flask: textbee Integration Guide
Send SMS from Django and Flask applications using textbee and your Android phone as the gateway. Service class, Celery async tasks, Django signals, Flask blueprints: zero per-message fees.

How to Receive SMS and Process Webhooks with textbee
Set up inbound SMS webhooks with textbee. Payload structure, signature verification, Node.js and Python handler examples, STOP keyword handling, OTP reply capture, and local testing with ngrok.

Send SMS from Java: No Twilio, Just Your Android Phone
Send real SMS from Java using textbee and your Android phone as the gateway. Native HttpClient, OkHttp, and Spring Boot examples, zero per-message fees.