Build with the WSAO API
Free, public API for tracking Roblox versions and Roblox exploit status in real time. Perfect for Discord bots, in-game scripts, and update trackers.
🚀 Getting Started
The WSAO public API is completely free and requires no authentication. Just make a GET request and you'll get JSON back.
All endpoints live under the /api/v1/ prefix and return JSON with full CORS enabled — so you can use it from servers, bots, browsers, or in-game scripts.
https://whatsploitsareonline.kdns.fr/api/v1
None required
application/json
30 requests / min per IP
* (all origins)
60 seconds
🖥️ Roblox Versions
GETReturns the latest Roblox client versions for all supported platforms (Windows, Mac, Android, iOS) along with their release dates. Cached for 5 minutes server-side.
https://whatsploitsareonline.kdns.fr/api/v1/versions
Example Response
{
"Windows": "version-76173e47a79145c7",
"WindowsDate": "6/9/2026, 11:25:09 PM UTC",
"Mac": "version-5e5ddbfddbdf4c6c",
"MacDate": "6/9/2026, 11:25:17 PM UTC",
"Android": "2.725.1142",
"AndroidDate": "6/12/2026, 8:53:36 PM UTC",
"iOS": "2.724.735",
"iOSDate": "6/5/2026, 10:04:02 AM UTC"
}
Response Fields
WindowsWindowsDateMacMacDateAndroidAndroidDateiOSiOSDateCode Examples
const res = await fetch(
"https://whatsploitsareonline.kdns.fr/api/v1/versions",
{ headers: { "User-Agent": "MyTrackerBot/1.0" } }
);
const data = await res.json();
console.log("Windows:", data.Windows);
console.log("Last update:", data.WindowsDate);
import requests
res = requests.get(
"https://whatsploitsareonline.kdns.fr/api/v1/versions",
headers={"User-Agent": "MyTrackerBot/1.0"}
)
data = res.json()
print("Windows:", data["Windows"])
print("Last update:", data["WindowsDate"])
⚙️ Exploits List
GETReturns a list of all tracked Roblox exploits with their name, version, and update status. The list is sorted alphabetically by name.
https://whatsploitsareonline.kdns.fr/api/v1/exploits
Example Response
{
"count": 3,
"exploits": [
{
"name": "Solstice",
"version": "1.0.0",
"updated": "Updated"
},
{
"name": "Synapse",
"version": "3.0.1",
"updated": "Not Updated"
},
{
"name": "Viktor Executor",
"version": "1.0.0",
"updated": "Updated"
}
]
}
Response Schema
countexploitsExploit Object
nameversionupdatedUpdated, Not Updated, Upcoming, UnknownCode Examples
const res = await fetch(
"https://whatsploitsareonline.kdns.fr/api/v1/exploits",
{ headers: { "User-Agent": "MyTrackerBot/1.0" } }
);
const data = await res.json();
const updated = data.exploits.filter(e => e.updated === "Updated");
console.log(`${updated.length} of ${data.count} exploits are updated`);
for (const e of updated) {
console.log(`✅ ${e.name} v${e.version}`);
}
import requests
res = requests.get(
"https://whatsploitsareonline.kdns.fr/api/v1/exploits",
headers={"User-Agent": "MyTrackerBot/1.0"}
)
data = res.json()
updated = [e for e in data["exploits"] if e["updated"] == "Updated"]
print(f"{len(updated)} of {data['count']} exploits are updated")
for e in updated:
print(f"✅ {e['name']} v{e['version']}")
🔍 Single Exploit Lookup
GETGet info about a single exploit by name. The name lookup is case-insensitive. Returns 404 if not found.
https://whatsploitsareonline.kdns.fr/api/v1/exploits/{name}
Example Request
GET /api/v1/exploits/Synapse
GET /api/v1/exploits/Viktor%20Executor
Example Response (200 OK)
{
"name": "Synapse",
"version": "3.0.1",
"updated": "Updated"
}
Example Response (404 Not Found)
{
"error": "not_found",
"message": "No exploit found matching 'FakeName'"
}
Code Examples
const name = "Synapse";
const url = `https://whatsploitsareonline.kdns.fr/api/v1/exploits/${encodeURIComponent(name)}`;
const res = await fetch(url, {
headers: { "User-Agent": "MyTrackerBot/1.0" }
});
if (res.status === 404) {
console.log("Exploit not found");
} else {
const data = await res.json();
console.log(`${data.name} v${data.version} — ${data.updated}`);
}
import requests
from urllib.parse import quote
name = "Synapse"
url = f"https://whatsploitsareonline.kdns.fr/api/v1/exploits/{quote(name)}"
res = requests.get(url, headers={"User-Agent": "MyTrackerBot/1.0"})
if res.status_code == 404:
print("Exploit not found")
else:
data = res.json()
print(f"{data['name']} v{data['version']} — {data['updated']}")
🤖 Build a Tracker Bot
Two ready-to-use examples to get your Discord bot pinging the moment Roblox or an exploit updates.
Example 1: Roblox Update Tracker Bot
Pings a Discord webhook whenever Roblox releases a new Windows version.
const WEBHOOK = "https://discord.com/api/webhooks/YOUR/WEBHOOK";
const API = "https://whatsploitsareonline.kdns.fr/api/v1/versions";
const UA = "RobloxTrackerBot/1.0 (discord:yourname)";
let lastVersion = null;
async function check() {
try {
const res = await fetch(API, { headers: { "User-Agent": UA } });
if (!res.ok) return;
const data = await res.json();
if (lastVersion && lastVersion !== data.Windows) {
await fetch(WEBHOOK, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
username: "Roblox Tracker",
embeds: [{
title: "🚨 Roblox just updated!",
description: `**New version:** \`${data.Windows}\`\n**Released:** ${data.WindowsDate}`,
color: 0x6366f1
}]
})
});
}
lastVersion = data.Windows;
} catch (err) {
console.error("Check failed:", err);
}
}
setInterval(check, 5 * 60 * 1000);
check();
import requests, time
WEBHOOK = "https://discord.com/api/webhooks/YOUR/WEBHOOK"
API = "https://whatsploitsareonline.kdns.fr/api/v1/versions"
UA = "RobloxTrackerBot/1.0 (discord:yourname)"
last_version = None
def check():
global last_version
try:
data = requests.get(API, headers={"User-Agent": UA}, timeout=10).json()
if last_version and last_version != data["Windows"]:
requests.post(WEBHOOK, json={
"username": "Roblox Tracker",
"embeds": [{
"title": "🚨 Roblox just updated!",
"description": f"**New version:** `{data['Windows']}`\n**Released:** {data['WindowsDate']}",
"color": 0x6366f1
}]
})
last_version = data["Windows"]
except Exception as e:
print("Check failed:", e)
while True:
check()
time.sleep(300)
Example 2: Exploit Status Tracker Bot
Watches specific exploits and pings Discord when one changes status to Updated.
const WEBHOOK = "https://discord.com/api/webhooks/YOUR/WEBHOOK";
const API = "https://whatsploitsareonline.kdns.fr/api/v1/exploits";
const UA = "ExploitTrackerBot/1.0 (discord:yourname)";
const WATCHING = ["Synapse", "Solstice", "Viktor Executor"];
const lastStatus = {};
async function check() {
try {
const res = await fetch(API, { headers: { "User-Agent": UA } });
if (!res.ok) return;
const data = await res.json();
for (const name of WATCHING) {
const exploit = data.exploits.find(
e => e.name.toLowerCase() === name.toLowerCase()
);
if (!exploit) continue;
const status = exploit.updated;
if (lastStatus[name] && lastStatus[name] !== status && status === "Updated") {
await fetch(WEBHOOK, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
username: "Exploit Tracker",
embeds: [{
title: `✅ ${exploit.name} is now Updated!`,
description: `**Version:** ${exploit.version}`,
color: 0x22c55e
}]
})
});
}
lastStatus[name] = status;
}
} catch (err) {
console.error("Check failed:", err);
}
}
setInterval(check, 5 * 60 * 1000);
check();
import requests, time
WEBHOOK = "https://discord.com/api/webhooks/YOUR/WEBHOOK"
API = "https://whatsploitsareonline.kdns.fr/api/v1/exploits"
UA = "ExploitTrackerBot/1.0 (discord:yourname)"
WATCHING = ["Synapse", "Solstice", "Viktor Executor"]
last_status = {}
def check():
try:
data = requests.get(API, headers={"User-Agent": UA}, timeout=10).json()
for name in WATCHING:
exploit = next(
(e for e in data["exploits"] if e["name"].lower() == name.lower()),
None
)
if not exploit:
continue
status = exploit["updated"]
if (name in last_status
and last_status[name] != status
and status == "Updated"):
requests.post(WEBHOOK, json={
"username": "Exploit Tracker",
"embeds": [{
"title": f"✅ {exploit['name']} is now Updated!",
"description": f"**Version:** {exploit['version']}",
"color": 0x22c55e
}]
})
last_status[name] = status
except Exception as e:
print("Check failed:", e)
while True:
check()
time.sleep(300)
⚠️ Rate Limits & Fair Use
The API is free and open, but please be a good citizen to keep it that way for everyone.
If you exceed this, you'll get a 429 Too Many Requests response. Check the Retry-After header for when to retry.
Polling more than once per minute won't give you fresher data — it's just wasted requests. Aim for every 1–5 minutes.
Use something descriptive like MyTrackerBot/1.0 (discord:yourname) so we can contact you if there's an issue with your bot.
Use the /api/v1/ endpoints instead of parsing HTML — they're faster, smaller, and won't break when we update the site.
Rate Limit Headers
Every API response includes these headers so your bot can self-throttle:
X-RateLimit-LimitX-RateLimit-RemainingRetry-After💬 Support
Got a question, found a bug, or want to show off your bot? Join our Discord!