Receive SMS verification codes with Python
Quick answer
With the Noir SMS API you can buy a number and read its SMS code in about 30 lines of Python. Create an API key in the dashboard, call POST /api/v1/numbers with a service code and a 2-letter country, then poll GET /api/v1/numbers/{id} every 3 to 5 seconds until status is received. The code is in sms[0].code. Numbers without an SMS are refunded automatically after 20 minutes.
This guide uses the requests library and an API key stored in an environment variable. The same flow works from any language that can make HTTPS calls.
Set up
- Create an account, add funds and open the API page in the dashboard to generate a key (it starts with nsk_live_).
- Run pip install requests.
- Export the key: export NOIRSMS_KEY=nsk_live_...
Buy a number and wait for the code
The script buys a Telegram (tg) number in the US, prints it, then polls until the SMS arrives or the number closes.
import os, time, requests
API = "https://noirsms.com/api/v1"
H = {"Authorization": f"Bearer {os.environ['NOIRSMS_KEY']}"}
def buy(service, country, max_price=None):
body = {"service": service, "country": country}
if max_price:
body["max_price"] = max_price
r = requests.post(f"{API}/numbers", json=body, headers=H, timeout=20)
r.raise_for_status()
return r.json()
def wait_for_code(number_id, timeout=20 * 60):
end = time.time() + timeout
while time.time() < end:
n = requests.get(f"{API}/numbers/{number_id}", headers=H, timeout=20).json()
if n["status"] == "received":
return n["sms"][0]["code"]
if n["status"] in ("canceled", "expired"):
return None
time.sleep(4)
return None
n = buy("tg", "us")
print("Enter this number in the app:", n["phone"])
print("Code:", wait_for_code(n["id"]))Good habits
- Read service codes from GET /services?country=us instead of hard-coding prices.
- Pass max_price so a price change can't surprise you (HTTP 409 price_above_max).
- Stay under 120 requests per minute per key; polling every 4 seconds is plenty.
- Call POST /numbers/{id}/finish when you're done, or /cancel after 2 minutes if the app refused the number.
Use it responsibly
Use the API only for your own legitimate accounts or apps you're authorized to test, and make sure your customers follow the same Acceptable Use Policy.
Frequently asked questions
Is there an official Python SDK?
No, the API is plain REST and JSON, so requests or httpx is all you need.
Can I use webhooks instead of polling?
Yes. Set a webhook URL in the dashboard and you'll receive a signed sms.received event.
Services in this guide
Keep reading
Receive SMS verification codes with Node.js
Buy a temporary number and read SMS verification codes from Node.js with fetch and the Noir SMS REST API. Complete example with error handling.
Read the guide →DevelopersAutomate receiving SMS codes: polling or webhooks
Two ways to receive SMS verification codes automatically with the Noir SMS API: polling GET /numbers/{id} or a signed sms.received webhook. Code included.
Read the guide →DevelopersCommon Noir SMS API errors and how to handle them
Every Noir SMS API error code explained: invalid_api_key, insufficient_balance, no_numbers, too_early, rate_limited and more, with a retry pattern.
Read the guide →DevelopersUsing virtual numbers to test SMS flows
How QA teams use real virtual numbers to test SMS sign-up and OTP flows end to end, when to use them vs test numbers, and how to automate with an API.
Read the guide →DevelopersReceive SMS verification codes with PHP
Use PHP and cURL to buy a temporary number and read the SMS verification code with the Noir SMS API. Copy-paste example for panels and scripts.
Read the guide →DevelopersTesting OTP and SMS sign-up flows in staging
Run end-to-end tests of your app's SMS sign-up in staging with real temporary numbers: Playwright example, what to check and how to keep costs low.
Read the guide →