textbee 是一个开源的短信网关,把闲置的 Android 手机变成可编程的短信收发通道。手机端安装配套应用并扫码绑定设备后,你就能在网页控制台、REST API 或 Webhook 中发送单条/批量短信、接收回复并查看发送状态,支持多设备并行提升吞吐。它还提供官方 MCP 服务器,让 Claude、Cursor 等 AI 客户端直接读写短信,可用于验证码下发、订单通知、服务器告警等场景。整套服务用 React/Next.js/NestJS/MongoDB 加 Kotlin 安卓端实现,可自行部署掌控数据,也有托管版本。
Send and receive SMS messages using your own Android phone - no Twilio, no per-message fees. Free, open-source, and self-hostable.
The open-source SMS gateway for developers, automations, and AI agents. Manage SMS messages through a web dashboard, a REST API, or the MCP server for AI agents. textbee is ideal for businesses, developers, and hobbyists looking for a reliable and cost-effective solution to automate SMS messaging.
Website: https://textbee.dev

| textbee | Twilio & similar APIs | |
|---|---|---|
| Cost per SMS | Your carrier plan (often free/unlimited) | ~$0.008+ per message |
| Phone number | Your own SIM | Rented number |
| Self-hostable | ✅ Full control over your data | ❌ |
| Open source | ✅ | ❌ |
| Setup time | ~2 minutes | Account approval, compliance forms |
Messages go out through your default device, or otherwise the enabled device with the most recent heartbeat. Pass an optional deviceId in the request body to send from a specific device instead. The older /gateway/devices/{deviceId}/send-sms route still works but is deprecated.
const API_KEY = 'YOUR_API_KEY';
await axios.post('https://api.textbee.dev/api/v1/gateway/send-sms', {
recipients: [ '+12025550123' ],
message: 'Hello World!',
}, {
headers: { 'x-api-key': API_KEY },
});
Python
import requests
API_KEY = 'YOUR_API_KEY'
requests.post(
'https://api.textbee.dev/api/v1/gateway/send-sms',
json={
'recipients': ['+12025550123'],
'message': 'Hello World!',
},
headers={'x-api-key': API_KEY},
)
curl
curl -X POST "https://api.textbee.dev/api/v1/gateway/send-sms" \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"recipients": [ "+12025550123" ],
"message": "Hello World!"
}'
Enable SMS receiving in the mobile app, then access incoming messages via the REST API, the dashboard, or webhook notifications delivered to your preferred URL. Message history is account-level: one call covers every device, no device id needed.
const API_KEY = 'YOUR_API_KEY';
await axios.get('https://api.textbee.dev/api/v1/gateway/messages?direction=received', {
headers: { 'x-api-key': API_KEY },
});
curl
curl -X GET "https://api.textbee.dev/api/v1/gateway/messages?direction=received" \
-H "x-api-key: YOUR_API_KEY"
The official textbee MCP server lets Claude, Cursor, and any MCP-compatible client send and read SMS through your account. Three tools: send_sms (send to one or many recipients), get_messages (read replies and verification codes, check delivery status), and list_devices. Plan limits apply server-side like any other send.
claude.ai, Claude Desktop, and the Claude mobile apps (nothing to install; the Free plan allows one custom connector):
textbee and the URL https://mcp.textbee.dev/mcp, then click Continue twice.The mobile apps use connectors added on the web or desktop. On Team and Enterprise plans, an owner adds the connector for the organization first.
Claude Code:
# Hosted: run /mcp afterwards and choose Authenticate to sign in with your API key
claude mcp add --transport http -s user textbee https://mcp.textbee.dev/mcp
# Or local: the key stays on your machine
claude mcp add textbee -s user -e TEXTBEE_API_KEY=YOUR_API_KEY -- npx -y @textbee/mcp
Cursor and other MCP clients (local server, the key stays on your machine):
{
"mcpServers": {
"textbee": {
"command": "npx",
"args": ["-y", "@textbee/mcp"],
"env": { "TEXTBEE_API_KEY": "YOUR_API_KEY" }
}
}
}
With the hosted connector, textbee checks your key and does not store it. Self-hosted instances use the local server with TEXTBEE_BASE_URL. Full setup at textbee.dev/mcp and the MCP docs.
Will my carrier block my number for sending too many messages?
Carriers apply their own rate limits and anti-spam policies, which vary by country and plan. For personal and low-volume use this is rarely an issue. For higher throughput, use multiple devices/SIMs and keep sending rates reasonable. You are responsible for staying within your carrier's terms.
Is it legal to send marketing SMS this way?
SMS marketing is regulated in most countries (e.g., TCPA in the US, GDPR/ePrivacy in the EU). textbee is a tool. You are responsible for obtaining consent and complying with the laws that apply to you and your recipients.
Does my phone need to stay on?
Yes. Messages are sent through your phone, so it needs to be powered on with the app running and connected to the internet. A spare Android phone plugged into a charger works great as a dedicated gateway.
Is there a limit on the cloud-hosted version?
See textbee.dev for current plans and limits. You can always self-host for full control.
Technology stack: React, Next.js, Node.js, NestJS, MongoDB, Android, Kotlin, Jetpack Compose, Java (legacy)
google-services.json file with your Firebase project configuration.textbee.dev with your own domain in the project../gradlew assembleRelease
web directory..env.example file to .env:
cp .env.example .env
.env file with your own credentials.pnpm install
pnpm build
api directory..env.example file to .env:
cp .env.example .env
.env file with your own credentials.pnpm install
pnpm build
A self-hosted instance reports nothing to anyone by default. With no analytics environment variables set, the web app loads no analytics or ad-platform scripts and the API sends no analytics events to any external service. Every provider below is opt-in, and one that is listed without its id is skipped.
(This is separate from the services the API talks to when you configure them yourself: Firebase for push, Cloudflare Turnstile, Polar for billing, and your own SMTP server.)
Web (web/.env, and the marketing site if you run it):
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_ANALYTICS_PROVIDERS | Comma separated list of providers to load: ga, clarity, meta. Unset means none. |
NEXT_PUBLIC_GA_MEASUREMENT_ID | Google Analytics measurement id, required for ga. |
NEXT_PUBLIC_CLARITY_PROJECT_ID | Microsoft Clarity project id, required for clarity. |
NEXT_PUBLIC_META_PIXEL_ID | Meta pixel id, required for meta. |
NEXT_PUBLIC_ATTRIBUTION_COOKIE_DOMAIN | Cookie domain for signup attribution, for example .example.com, when the dashboard and the marketing site are on different subdomains. Leave unset for a single domain. |
API (api/.env):
| Variable | Purpose |
|---|---|
ANALYTICS_PROVIDERS | Comma separated list of server-side destinations. Only meta today. Unset means no events are sent. |
META_PIXEL_ID | Same id as the browser pixel. |
META_CAPI_ACCESS_TOKEN | Conversions API token. Keep it out of version control and out of any NEXT_PUBLIC_ variable. |
META_CAPI_TEST_EVENT_CODE | Optional. Routes events to Events Manager's test view instead of live reporting. |
NEXT_PUBLIC_ values are baked in at build time, so changing them means a
rebuild, not just a restart. ANALYTICS_PROVIDERS on the API is read at
runtime, so unsetting it and restarting stops all outbound events immediately.
Signup attribution (which channel an account came from) is separate from the providers above. It is stored only in your own database, makes no external request, and is always on.
pnpm, pm2, and Caddy on your VPS.pm2 to manage your Node.js processes:
pm2 start dist/main.js --name textbee-api
Caddy to serve your web application and API. Example Caddyfile:
textbee.dev {
reverse_proxy /api/* localhost:3000
reverse_proxy /* localhost:3001
}
.env in web && api folder.
cd web && cp .env.example .env \
&& cd ../api && cp .env.example .env
web container, api container alongside with MongoDB and MongoExpress. textbee database will be automatically created.
docker compose up -d
To stop the containers simply type
docker compose down
Contributions are welcome!
main branch.main branch.Please feel free to create an issue in the repository for any bug reports or feature requests. Make sure to provide a detailed description of the issue or feature you are requesting and properly label whether it is a bug or a feature request.
Please note that if you discover any vulnerability or security issue, we kindly request that you refrain from creating a public issue. Instead, send an email detailing the vulnerability to [email protected].
Feel free to reach out to us at [email protected] or Join our Discord server
内容由编辑整理,部分信息来自 GitHub 与项目官网,版权归原作者所有。发现错误?报告问题