Developer docs
JSON API
Create distributed checks, poll results, and list active nodes. Responses use application/json. Send Accept: application/json on every request.
01 Authentication & CSRF
Creating a check from a browser (or any client that uses the site session cookie) requires a CSRF token.
- Open the homepage once to receive the session cookie
- Read the hidden
_csrf field from the check form, or reuse a token from that page
- Send it as form field
_csrf or header X-CSRF-Token
GET /api/result.php and GET /api/nodes.php do not require CSRF.
02 Create a check
Endpoint: POST https://netstats.ir/api/check.php
Content-Type: application/x-www-form-urlencoded
Parameters
| Name | Required | Description |
host | yes | Hostname, IPv4/IPv6, URL, host:port, or [ipv6]:port |
type | yes | ping, http, tcp, dns, or udp |
max_nodes | no | Max nodes to use (capped by site settings) |
node | no | Repeatable node id to force specific nodes |
_csrf | yes* | CSRF token (*or X-CSRF-Token header) |
Example
curl -c cookies.txt -b cookies.txt \
-H "Accept: application/json" \
-H "X-CSRF-Token: YOUR_CSRF_TOKEN" \
-d "host=example.com&type=ping&max_nodes=5" \
https://netstats.ir/api/check.php
curl -c cookies.txt -b cookies.txt \
-H "Accept: application/json" \
-H "X-CSRF-Token: YOUR_CSRF_TOKEN" \
--data-urlencode "host=[2001:db8::1]:443" \
-d "type=tcp&max_nodes=3" \
https://netstats.ir/api/check.php
Success response
{
"ok": 1,
"request_id": "a1b2c3d4e5f6g7h8",
"permanent_link": "https://netstats.ir/report.php?id=a1b2c3d4e5f6g7h8",
"nodes": {
"us-nyc-1a2b": ["us", "United States", "New York", "1.2.3.4", "AS13335"]
}
}
Each node value is [country_code, country, city, ip, asn].
03 Get check results
Endpoint: GET https://netstats.ir/api/result.php?id=REQUEST_ID
Poll until every node value is non-null (or until your client timeout). Pending nodes return null.
curl -H "Accept: application/json" \
"https://netstats.ir/api/result.php?id=REQUEST_ID"
{
"ok": 1,
"command": "ping",
"created": 1710000000,
"host": "example.com",
"nodes": { "...": ["us", "United States", "New York", "1.2.3.4", "AS13335"] },
"results": {
"us-nyc-1a2b": [[["OK", 0.042, "93.184.216.34"], ["OK", 0.041, "93.184.216.34"]]],
"de-fra-9x8y": null
}
}
Node agents may also POST signed results to the same endpoint; that path is for nodes only, not public clients.
04 List nodes
Endpoint: GET https://netstats.ir/api/nodes.php
curl -H "Accept: application/json" \
https://netstats.ir/api/nodes.php
{
"nodes": {
"us-nyc-1a2b": {
"asn": "AS13335",
"ip": "1.2.3.4",
"location": ["us", "United States", "New York"]
}
}
}
Only active nodes are returned. Tokens and secrets are never exposed.
05 Check types & host formats
| Type | Host examples | Notes |
ping | example.com, 1.1.1.1, 2001:db8::1 | IPv4 and IPv6 |
http | https://example.com, http://[2001:db8::1]/ | Status and timing |
tcp | example.com:443, [2001:db8::1]:443 | Port required |
udp | example.com:53, [2001:db8::1]:53 | Port required |
dns | example.com | A and AAAA (+ TTL when available) |
Private, loopback, link-local, ULA, CGNAT, and cloud-metadata targets are rejected for both IPv4 and IPv6. Hostnames prefer AAAA when available.
06 Errors & limits
Error bodies look like:
{ "ok": 0, "error": "Rate limit exceeded" }
| HTTP | Meaning |
400 | Invalid host, type, or input |
403 | CSRF failure or forbidden callback |
404 | Unknown request id |
405 | Wrong method (use POST to create) |
429 | Rate limit exceeded |
500 | Server / dispatch error (e.g. no active nodes) |
IP Info / WHOIS is available on the website at /ip.php (form UI). Distributed checks use the endpoints above.