Links, websites & email
Check a link
Coverage: Checks wording and visible links only. The sender, attachments and website contents are not verified.
Open toolOn this page
Purpose
Check numbers, messages and links
Checks wording and visible links only. The sender, attachments and website contents are not verified.
Requirements
Anyone can read these guides, no account needed. Some tools require Pro, as indicated in each guide.
Enter one complete HTTP or HTTPS link, or a domain name.
How to use it
Check a link or website
In Email, paste the message text; in Link, its address. Press Check and review the signals and actual domain. It does not open links or authenticate senders.
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.
https://[email protected]/noticeInterpret the result
Text before @ can hide the actual domain shown below.
Uses HTTP, without HTTPS encryption.
An internationalized domain needs careful review: some characters can look alike.
Uses a numeric IP address instead of a domain name.
No obvious warning signs found
Limitations
Checked on this device. Your text is not uploaded or saved.
Checks wording and visible links only. The sender, attachments and website contents are not verified.
Troubleshooting
Enter one complete HTTP or HTTPS link, or a domain name.
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.
Static inspection of one URL: host in Unicode and ASCII, whether it is an official brand or government domain (and whose), structural link flags and rule-engine signals. No fetch, redirect following or reputation lookup.
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/link-check
POST https://api.nocall.io/v2/tools {"tool":"link-check","url":"http://192.168.1.1/login","country":"ES"}Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| url | string (1–2000) | Yes | URL to inspect. It is never fetched. |
| country | string (enum, 55) | No (default: "ES") | Country whose SMS rule set is used. |
REQUEST_ID="$(uuidgen)" && [ -n "$REQUEST_ID" ] &&
curl --request POST 'https://api.nocall.io/v2/link-check' \
--header "Authorization: Bearer $NOCALL_API_KEY" \
--header 'Content-Type: application/json' \
--header "Idempotency-Key: $REQUEST_ID" \
--data '{"url":"http://192.168.1.1/login","country":"ES"}'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/link-check',
method='POST',
data=json.dumps({'url': 'http://192.168.1.1/login', 'country': 'ES'}).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/link-check', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + apiKey,
'Content-Type': 'application/json',
'Idempotency-Key': requestId,
},
body: JSON.stringify({ url: 'http://192.168.1.1/login', country: 'ES' }),
});
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": "link-check",
"result": {
"host": "192.168.1.1",
"hostAscii": "192.168.1.1",
"official": false,
"brand": null,
"hosts": [
"192.168.1.1"
],
"linkFlags": [
"http",
"ipAddress"
],
"signals": [
"suspicious_domain"
],
"attention": true
}
},
"meta": {
"requestId": "req_example",
"unitsCharged": 1,
"usage": {
"periodStart": "2026-10-01",
"unitLimit": 20,
"unitsUsed": 3,
"unitsRemaining": 17
}
}
}Result fields (data.result)
| Field | Type | Description |
|---|---|---|
| host | string | Host name of the URL, in Unicode form. |
| hostAscii | string | Host name of the URL, in ASCII (punycode) form. |
| official | boolean | Whether the host is an official brand or government domain. |
| brand | string | null | Whose official domain the host is (a brand or a government body), or null. |
| hosts | array<string> | Host names found in the text. |
| linkFlags | array<"http" | "userinfo" | "internationalHost" | "ipAddress" | "nonStandardPort"> | Structural warnings about the link: http, userinfo, international host, IP address or non-standard port. |
| signals | array<string (enum, 10)> | Rule signals that matched. |
| attention | boolean | Whether the content deserves a closer look. |
