SMS & messages
Check if a text message is a scam
Coverage: Indicative result based on automatic signals, not sender verification. No result guarantees that a message is safe.
Open toolOn this page
Purpose
Upload a screenshot and we'll tell you if it's a scam, who it impersonates and what to do.
Requirements
Tool plan: Pro
Anyone can read these guides, no account needed. Some tools require Pro, as indicated in each guide.
Activate NoCall Pro to analyze the sender and message, or a screenshot of the SMS, with AI.
How to use it
Paste the suspicious SMS here
or paste the sender and message
Analyze an SMS screenshot
Analyze PRO
Read the available fields alongside their limitations. An empty result does not prove safety or identify a person.
Synthetic example
Invented example, not a real lookup. Do not call or open its links.
DHL: Last warning. Your parcel is blocked. Action required at https://parcel.exampleInterpret the result
Suspicious
Safe
Needs review
No data
Confidence
Read the available fields alongside their limitations. An empty result does not prove safety or identify a person.
Limitations
Only when you press the button, the sender and message are sent securely for remote analysis. No inbox access or automatic action.
Only the screenshot you choose is sent for this analysis, and NoCall does not store it.
Indicative result based on automatic signals, not sender verification. No result guarantees that a message is safe.
Troubleshooting
Type the message or add a screenshot.
We couldn’t read the image. Try another screenshot (JPG, PNG or WebP).
The screenshot is too large. Try a smaller one.
Your session has expired. Sign in again.
Too many requests. Try again later.
Use with the API
Needs an API key and credits. Each completed call costs 1 credit, even when there is no data. An active Pro account includes 20 credits per UTC calendar month, shared by every API route and spent first; unused monthly credits do not roll over. Credits bought on your account page work without Pro and never expire.
Errors are never charged: 401 invalid_api_key (missing or invalid key), 403 pro_required (no Pro credits and no purchased credits), 422 invalid input, 429 quota_exceeded (no credits left), rate_limit_exceeded or ai_busy (the AI of sms-check is at capacity), 503 tool_warming (the data is still being prepared) or tool or provider unavailable. After a 429 or 503, retry once the seconds in the Retry-After header have passed.
The message is analysed by AI. Only the redacted text (phone numbers, email addresses and card and bank details removed), features derived from it, the sender type, the optional country and the language reach the model, and API calls never add to the community campaign data. The AI is limited to 20 calls a minute, 5 of them per account; when it is busy the answer is 429 ai_busy, which is not charged.
AI analysis of one SMS: allow or suspicious, with the model's confidence in that verdict (0–100) and a short reason. Only the redacted text, features derived from it, the sender type, the optional country and the language reach the model.
Send the JSON body to the tool's own route, or to POST /v2/tools with the tool field added. Both routes return the same result.
POST https://api.nocall.io/v2/sms-check
POST https://api.nocall.io/v2/tools {"tool":"sms-check","message":"Your parcel is held. Pay the fee at https://example.invalid/pay","sender":"Correos","language":"en","country":"GB"}Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| message | string (1–4000) | Yes | SMS text to analyse. Phone numbers, email addresses and card and bank details are redacted before the AI sees it. |
| sender | string (≤120) | No | Sender name or number shown on the SMS. Only its type (brand name, short code, number…) reaches the AI. |
| language | string (enum, 33) | No (default: "en") | Language of the reason. |
| country | string (enum, 55) | No | Country where the SMS was received, named in the AI analysis. Optional: without it the country is unknown. |
REQUEST_ID="$(uuidgen)" && [ -n "$REQUEST_ID" ] &&
curl --request POST 'https://api.nocall.io/v2/sms-check' \
--header "Authorization: Bearer $NOCALL_API_KEY" \
--header 'Content-Type: application/json' \
--header "Idempotency-Key: $REQUEST_ID" \
--data '{"message":"Your parcel is held. Pay the fee at https://example.invalid/pay","sender":"Correos","language":"en","country":"GB"}'import json
import os
import urllib.request
import uuid
api_key = os.environ.get('NOCALL_API_KEY')
if not api_key:
raise SystemExit('Set NOCALL_API_KEY')
request = urllib.request.Request(
'https://api.nocall.io/v2/sms-check',
method='POST',
data=json.dumps({'message': 'Your parcel is held. Pay the fee at https://example.invalid/pay', 'sender': 'Correos', 'language': 'en', 'country': 'GB'}).encode(),
headers={
'Authorization': 'Bearer ' + api_key,
'Content-Type': 'application/json',
'Idempotency-Key': str(uuid.uuid4()),
},
)
with urllib.request.urlopen(request, timeout=30) as response:
result = json.load(response)
print(result['data']['result'], result['meta']['unitsCharged'])import { randomUUID } from 'node:crypto';
const requestId = randomUUID();
const apiKey = process.env.NOCALL_API_KEY;
if (!apiKey) throw new Error('Set NOCALL_API_KEY');
const response = await fetch('https://api.nocall.io/v2/sms-check', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + apiKey,
'Content-Type': 'application/json',
'Idempotency-Key': requestId,
},
body: JSON.stringify({ message: 'Your parcel is held. Pay the fee at https://example.invalid/pay', sender: 'Correos', language: 'en', country: 'GB' }),
});
const result = await response.json();
if (!response.ok) throw new Error(result.error?.code ?? 'request_failed');
console.log(result.data.result, result.meta.unitsCharged);Example response (200)
This is the documented example from the API reference. Lookups use a fictional number, and aggregates and AI answers show the shape of the result, not live data.
{
"data": {
"tool": "sms-check",
"result": {
"verdict": "suspicious",
"confidence": 80,
"reason": "Unexpected payment request with a link."
}
},
"meta": {
"requestId": "req_example",
"unitsCharged": 1,
"usage": {
"periodStart": "2026-10-01",
"unitLimit": 20,
"unitsUsed": 3,
"unitsRemaining": 17
}
}
}Result fields (data.result)
| Field | Type | Description |
|---|---|---|
| verdict | "allow" | "suspicious" | Verdict of the AI analysis. |
| confidence | integer (0–100) | The model's confidence in the verdict, from 0 to 100. |
| reason | string (≤160) | Short reason for the verdict, up to 160 characters. |
