Choose Theme

Midnight
Ocean
Forest
Sunset
Rose
Amber
Mono
Light
Creator Themes
Olemad Creator
DarkModz Creator
MirkoKing Creator

Custom Theme

Paste an image URL to generate your own theme from it
Custom
Tip: Use direct image links (.jpg, .png, .webp). Imgur, Discord CDN, and most image hosts work great.
📡 Public API Documentation

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.

📑 On This Page

🚀 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.

🌐
Base URL
https://whatsploitsareonline.kdns.fr/api/v1
🔓
Authentication
None required
📦
Response Format
application/json
⏱️
Rate Limit
30 requests / min per IP
🌍
CORS
* (all origins)
💾
Edge Cache
60 seconds

🖥️ Roblox Versions

GET

Returns the latest Roblox client versions for all supported platforms (Windows, Mac, Android, iOS) along with their release dates. Cached for 5 minutes server-side.

GET 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

Field
Type
Description
Windows
string
Current Windows client version hash
WindowsDate
string
Release timestamp (UTC)
Mac
string
Current macOS client version hash
MacDate
string
Release timestamp (UTC)
Android
string
Current Android app version
AndroidDate
string
Release timestamp (UTC)
iOS
string
Current iOS app version
iOSDate
string
Release timestamp (UTC)

Code 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

GET

Returns a list of all tracked Roblox exploits with their name, version, and update status. The list is sorted alphabetically by name.

GET 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

Field
Type
Description
count
number
Total number of exploits returned
exploits
array
Array of exploit objects (see below)

Exploit Object

Field
Type
Description
name
string
Display name of the exploit
version
string
Current version of the exploit
updated
string
One of: Updated, Not Updated, Upcoming, Unknown

Code 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

GET

Get info about a single exploit by name. The name lookup is case-insensitive. Returns 404 if not found.

GET 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.

⏱️
30 requests per minute per IP

If you exceed this, you'll get a 429 Too Many Requests response. Check the Retry-After header for when to retry.

💾
Responses are edge-cached for 60s

Polling more than once per minute won't give you fresher data — it's just wasted requests. Aim for every 1–5 minutes.

🤖
Always send a User-Agent header

Use something descriptive like MyTrackerBot/1.0 (discord:yourname) so we can contact you if there's an issue with your bot.

🚫
Don't scrape the website

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:

Header
Type
Description
X-RateLimit-Limit
number
Max requests allowed per minute (30)
X-RateLimit-Remaining
number
Requests remaining in the current window
Retry-After
number
Seconds until the limit resets (only on 429 responses)
⚠️ Abusive traffic (high RPS, scraping, etc.) will be blocked at the Cloudflare level without notice.

💬 Support

Got a question, found a bug, or want to show off your bot? Join our Discord!

Copied!