Data
Everything on ix.watch is public, and the pages are built on the same API you can use. No key, no sign-up, and CORS is open.
Endpoints
| Request | Returns |
|---|---|
GET https://api.ix.watch/ix-violators.json | Every source seen in the last 7 days, the IXPs we watch and whether each capture is up, and how many sources we couldn't tie to a network. |
GET https://api.ix.watch/ix-violators/events | Server-sent events: a packet event per sampled frame, carrying the source's full state. |
GET https://api.ix.watch/ix-violators/as/<asn>.json | One network: its sources with their recent frames, plus hourly frame counts over 7 days. |
GET https://api.ix.watch/ix-violators/as/<asn>.pcap | The raw frames behind that network's page, for Wireshark. |
A source
A source is one MAC address on one IXP. Times are Unix seconds. recent holds the decoded headers of the last few frames, never payloads. via names who runs the sensor when it isn't us.
{
"ix": "AMS-IX",
"mac": "00:00:5e:00:53:01",
"asn": 64500,
"name": "Example Networks",
"vendor": "MikroTik",
"ports": [{ "ipv4": "192.0.2.10", "ipv6": "2001:db8::10" }],
"types": [{ "type": "ra", "count": 1340, "first": 1791100000, "last": 1791700000 }],
"total": 1340,
"first": 1791100000,
"last": 1791700000,
"recent": [{ "ts": 1791700000.1, "type": "ra", "layers": [ ... ] }],
"via": null
}Try it
# who's sending right now
curl -s https://api.ix.watch/ix-violators.json | jq '.sources[] | select(.last > now - 300) | .name'
# follow the live stream
curl -N https://api.ix.watch/ix-violators/eventsOnly sources we could tie to a network are published. The snapshot is cached for a few seconds; follow the event stream for anything live.